防CRLF log 注入

来源:互联网 发布:mac docker 仓库地址 编辑:程序博客网 时间:2024/04/30 17:06
 


在项目开发时经常会用到第三方的代码包,当我们在代码重用时注意,像这种开源的第三方类的修改是不受控的,直接应用它时,留下了隐患。

应将其隐藏尽量避免其在项目代码中扩散,遵守“开扩展,闭修改”原则。组合、代理都是很好的方式。

Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。并可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。由于其用途的强大和简易,在开发中被经常使用,如下下面这段代码:

import java.net.InetAddress;import java.net.UnknownHostException;import org.apache.log4j.LogManager;import org.apache.log4j.Logger;import org.apache.log4j.MDC;import org.apache.log4j.helpers.LogLog;import org.apache.log4j.xml.DOMConfigurator;public final class LogConfig{    private static LogConfig lconfig = null;    public Logger mart_log = null; // 组合,    ...

上面显示了LogConfig类的部分代码。LogConfig类封装了一个 Logger 对象作为成员变量。

应用中要做日志记录,可以在程序中生成 logConfig类的对象,如: LogConfig logConfig = LogConfig.getInstance(); //(单例模式)

要记录日志时,调用其成员变量 mart_log的相应方法: this.logConfig.mart_log.debug("Account Num in Formbean : " + priceFormBean.getAccountNumber());

就会将指定内容按指定的格式输入到指定的位置。

其中priceFormBean.getAccountNumber()的内容程序运行时会从对象实例中取。这里就留下了漏洞,如果不做验证,就容易受到CRLF注入攻击。而实际上当我们对代码进行静态扫描的时候,就能扫出这一行存在风险。堵住漏洞我们需要对变量中可能存在的HTML Entity进行转义

apache的commons-lang.jar 包中提供了一个很好的类来处理HTML Entity:apache.commons.lang.StringEscapeUtils.escapeHtml(str);

escapeHtml方法可以从字符串str中将HTML Entity 过滤掉。有了这个包,我们可以对存在漏洞的地方进行这样的处理:

     this.logConfig.mart_log.debug(apache.commons.lang.StringEscapeUtils.escapeHtml("Account Num in Formbean : " +priceFormBean.getAccountNumber()));

这样每一个存在漏洞的地方我们都要修改一次,而且让commons.lang.StringEscapeUtils散落到多处,显然这给我们带来了很大的工作量,效果还不好。

看看下面的方发,代理模式

import org.apache.commons.lang.StringEscapeUtils;import org.apache.log4j.Logger;public class MartLog { //Logger的代理类,该类没有实现接口,所以这里简单的包装了一下,也没有接口     private Logger selflog;    public Logger getSelflog() {        return selflog;    }    public void setSelflog(Logger selflog) {        this.selflog = selflog;    }

public void error(String str){

selflog.error(MartLog.antiCRLF(str));//对Logger类的引用

}

..... public static String antiCRLF(String str){ return StringEscapeUtils.escapeHtml(str); }}

然后将LogConfig类中的 public Logger mart_log 换成其代理类:public MartLog mart_log,其他的地方就不用做修改。

如果以后日志记录还要加什么过滤功能直接修改这一个类就可以了。

 

 

附:

CRLF Injection CRLF 注入

Description 描述

The acronym CRLF stands for "Carriage Return, Line Feed" and refers to the sequence of characters used to denote the end of a line of text.

CRLF injection vulnerabilities occur when data enters an application from an untrusted source and is not properly validated before being used.

For example, if an attacker is able to inject a CRLF into a log file, he could appendfalsified log entries, thereby misleading administrators or cover traces of the attack.

If an attacker is able to inject CRLFs into an HTTP response header, he can use this ability to carry out other attacks such as cache poisoning. CRLF vulnerabilities

primarily affect data integrity.

CRLF 全名表示:回车/换行。回车换行符表示一行的结束,并另起一行。当一个不受信的数据源的数据没有经过检验就插入应用数据库时容易发生回车换行注入。

例如:当一个攻击者对日志文件做回车换行注入攻击时,他会伪造一条日志记录,从而误导管理员,或掩盖攻击路径。

一个攻击者将回车换行符插入到http响应头中,并利用这种能力实施一些其他的攻击,如:缓存病毒攻击。 CRLF漏洞主要破坏数据的完整性。

Recommendations 建议

Apply robust input filtering for all user-supplied data, using centralized data validation routines when possible. Use output

filters to sanitize all output derived from user-supplied input, replacing non-alphanumeric characters with their HTML entity

应用强大的输入过滤器对所有用户提供的数据进行过滤,也可以编写数据验证程序来过滤。

在输出时也要对用户提供的数据进行过滤,替换掉所有由非字母字符代表的HTML实体!

 

HTML Entity 相关知识

 

原创粉丝点击