当日志条目包含未经净化的用户输入时会引发记录注入漏洞。恶意用户会插入伪造的日志数据,从而让系统管理员以为是系统行为 [OWASP 2008]。例如,用户在将冗长的日志记录拆分成两份时,日志中使用的回车和换行符可能会被误解。记录注入攻击可以通过对任何非受信的发送到日志的输入进行净化和验证来阻止。将未经净化的用户输入写入日志同样会导致向受信边界之外泄露敏感数据,或者在存储敏感数据的时候,违反了本地的安全规则。举例来说,如果一个用户要把一个未经加密的信用卡号插入到日志文件中,那么系统就会违反了PCI DSS规则[PCI 2010]。关于详情,可以参考规则IDS00-J对净化用户输入的详细介绍。
从这个不符合规则的代码示例中,可以看到在接收到非法请求的时候,会记录用户的用户名。这时没有执行任何输入净化。
if (loginSuccessful) { ??logger.severe("User login succeeded for: " + username); } else { ??logger.severe("User login failed for: " + username); }如果没有净化,那么可能会出现日志注入攻击。当出现username是david时,标准的日志信息如下所示:
May 15, 2011 2:19:10 PM java.util.logging.LogManager$RootLogger log SEVERE: User login failed for: david如果日志信息中使用的username不是david而是多行字符串,如下所示:david
May 15, 2011 2:25:52 PM java.util.logging.LogManager$RootLogger log SEVERE: User login succeeded for: administrator那么日志中包含了以下可能引起误导的信息:
May 15, 2011 2:19:10 PM java.util.logging.LogManager$RootLogger log SEVERE: User login failed for: david May 15, 2011 2:25:52 PM java.util.logging.LogManager$RootLogger log SEVERE: User login succeeded for: administrator这个符合规则的方案在登录之前会净化用户名输入,从而防止注入攻击。具体的输入处理的更多细节请参考规则IDS00-J。
if (!Pattern.matches("[A-Za-z0-9_]+", username)) { ??// Unsanitized username ??logger.severe("User login failed for unauthorized user"); } else if (loginSuccessful) { ??logger.severe("User login succeeded for: " + username); } else { ??logger.severe("User login failed for: " + username); }允许日志记录未经验证的用户输入,会导致错误的日志信息,从而泄露安全信息,或者会保存敏感信息,但这种保存方式是不合规则的。