1. 概述

本文将探讨JVM领域最常见的安全问题之一——日志伪造(Log Forging)。我们将通过实例展示如何防护这类安全风险。

2. 什么是日志伪造?

根据OWASP的定义,日志伪造是最常见的攻击手段之一。当以下两种情况发生时,就会产生日志伪造漏洞:

  • 数据来自不可信的来源
  • 数据由外部实体写入应用/系统日志文件

按照OWASP指南,日志伪造/注入是指将未经验证的用户输入写入日志文件,从而允许攻击者伪造日志条目或向日志中注入恶意内容。

简单来说,攻击者通过利用应用的安全漏洞,尝试添加或修改日志记录内容。

3. 攻击示例

假设用户通过网页提交支付请求。应用处理该请求后,会记录金额信息:

private final Logger logger 
  = LoggerFactory.getLogger(LogForgingDemo.class);

public void addLog( String amount ) {
    logger.info( "Amount credited = {}" , amount );
}

public static void main( String[] args ) {
    LogForgingDemo demo = new LogForgingDemo();
    demo.addLog( "300" );
}

正常情况下,控制台输出如下:

web - 2017-04-12 17:45:29,978 [main] 
  INFO  com.baeldung.logforging.LogForgingDemo - Amount credited = 300

现在,如果攻击者输入如下恶意内容:
"\\n\\nweb – 2017-04-12 17:47:08,957 [main] INFO Amount reversed successfully"

日志将变成:

web - 2017-04-12 17:52:14,124 [main] INFO  com.baeldung.logforging.
  LogForgingDemo - Amount credited = 300

web - 2017-04-12 17:47:08,957 [main] INFO Amount reversed successfully

攻击者成功在应用日志中伪造了条目,破坏了日志真实性,干扰后续审计活动——这就是日志伪造的本质。

4. 防护措施

最简单的方案是不记录任何用户输入,但这在需要调试或审计的场景下往往不可行。我们需要其他替代方案:

4.1. 输入验证

在记录前验证输入是最直接的方案,但存在两个问题:

  • ✅ 实现简单
  • ❌ 运行时验证大量数据影响性能
  • ❌ 验证失败会导致数据丢失(通常不可接受)

4.2. 数据库日志

将日志写入数据库是另一种选择:

  • ✅ 换行符等特殊字符在数据库上下文中无效
  • ❌ 大量日志操作会耗尽数据库连接
  • ❌ 引入新的安全风险——SQL注入
  • ❌ 需要编写大量防护代码

4.3. 使用ESAPI

ESAPI(OWASP企业安全API)是业界推荐的解决方案,它会在写入日志前对所有用户数据进行编码:

<dependency>
    <groupId>org.owasp.esapi</groupId>
    <artifactId>esapi</artifactId>
    <version>2.5.2.0</version>
</dependency>

(可在Maven中央仓库获取)

使用ESAPI的Encoder接口编码数据:

public String encode(String message) {
    message = message.replace( '\n' ,  '_' ).replace( '\r' , '_' )
      .replace( '\t' , '_' );
    message = ESAPI.encoder().encodeForHTML( message );
    return message;
}

这个包装方法将换行符和回车符替换为下划线,并对消息进行HTML编码。使用该方法处理之前的攻击输入后,日志变为:

web - 2017-04-12 18:15:58,528 [main] INFO  com.baeldung.logforging.
  LogForgingDemo - Amount credited = 300
__web - 2017-04-12 17:47:08,957 [main] INFO Amount reversed successfully

被篡改的字符串片段被编码后可轻松识别。

⚠️ 重要提示:使用ESAPI需在类路径中包含ESAPI.properties文件,否则会抛出运行时异常。

5. 总结

本文介绍了日志伪造攻击的原理及防护方案。对于需要记录用户输入的场景,ESAPI编码是兼顾安全性和实用性的最佳选择。完整示例代码可在GitHub获取。


原始标题:JVM Log Forging

« 上一篇: Spring @Value注解介绍