TypeCodes

小议网站HTTP响应拆分漏洞

1 问题描述

昨天博客重新改用了一个插件,这个插件虽然也是wordpress官方插件,但是在安装之后网站就出现了一个高危漏洞。根据WASC Threat Classification的说明,该漏洞名称叫做“HTTP响应拆分漏洞”,也叫“CRLF注入攻击”。CR、LF分别对应回车(%0d)、换行(%0a)字符。HTTP头由很多被CRLF组合分离的行构成,每行的结构都是“键:值”。如果用户输入的值部分注入了CRLF字符,它有可能改变的HTTP报头结构。

HTTP响应拆分是一个新的应用程序的攻击技术,使网页缓存中毒,跨用户涂改,如各种新的攻击,劫持用户的敏感信息和跨站点脚本(XSS)的网页。

小议网站HTTP响应拆分漏洞-1

2 解决思路

根据常识,这种现象往往表现在带有参数传递的网页,例如 typecodes.com/?page=传递的参数 。于是,我赶紧查看了一下这个插件。在它的一个页面里面我看到了两行代码: $post = $_GET['p'];、$download = $_GET['download']; 。然而,它后面却没有对这两个传递的参数$post和$download 进行处理。这样就很可能造成注入漏洞。例如,在数据库的操作中就很注重一些防注入的处理。在“PHP和ASP的数据库连接代码”这篇文章的conn.asp的代码中就对回车键和换行键进行了处理。所以,对参数$post和$download运用PHP语法中的正则表达式ereg_replace或者字符串处理函数str_replace进行操作。大家只要在参数被写入到数据库之前把它过滤即可。

3 解决代码

根据 ereg_replace 和 str_replace 这两个字符串处理函数可以用一下两种代码解决。

3.1 用ereg_replace函数解决
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?php
    $post = trim($post); //$post为需要过滤的参数
    $post = strip_tags($post,""); //清除HTML如<br/>等代码
    $post = ereg_replace("\t","",$post); //去掉制表符号
    $post = ereg_replace("\r\n","",$post); //去掉回车换行符号
    $post = ereg_replace("\r","",$post); //去掉回车
    $post = ereg_replace("\n","",$post); //去掉换行
    $post = ereg_replace(" ","",$post); //去掉空格
    $post = ereg_replace("'","",$post); //去掉单引号
?>
3.2 用str_replace函数解决
1
2
3
4
5
6
7
8
9
<?php
    $post = trim($post); //$post为需要过滤的参数
    $post = strip_tags($post,""); //清除HTML如<br/>等代码
    $post = str_replace("\n", "", str_replace(" ", "", $post));//去掉空格和换行
    $post = str_replace("\t","",$post); //去掉制表符号
    $post = str_replace("\r\n","",$post); //去掉回车换行符号
    $post = str_replace("\r","",$post); //去掉回车
    $post = str_replace("'","",$post); //去掉单引号
?>
3.3 问题延伸讨论

当然对$download参数的处理也是类似的(即把上述代码中的$post全部改成$download即可),就不贴出代码了。通过这个处理,解决了“HTTP响应拆分漏洞”的问题。

小议网站HTTP响应拆分-2

4 Update 2012-12-30 18:26
4.1 存在“http响应拆分漏洞”的CMS系统
WordPresswp-codebox插件
Shopex商城系统
wordpress评论者链接网址重定向跳转插件
ecshop商城系统
UCHOME
4.2 上述系统漏洞的解决方案

考虑到如果需要过滤的参数比较多的话(像Shopex的一个漏洞就需要过滤十多个参数),那么要修改的代码量就非常大,所以我把它封装在一个函数handel_http($parameter)里,这样以后只要在需要的地方调用即可。大家可以把下面任意一段代码扔到自己网站的出现漏洞的页面里面或者其它封装好的php文件中(然后在漏洞页面引入该文件并调用handel_http($parameter)即可),wordpress用户可以扔到自己主题下面的functions.php里面)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
    function handel_http($parameter){
        $parameter = trim($parameter); //$parameter为需要过滤的参数
        $parameter = strip_tags($parameter,""); //清除HTML如<br/>等代码
        $parameter = ereg_replace("\t","",$parameter); //去掉制表符号
        $parameter = ereg_replace("\r\n","",$parameter); //去掉回车换行符号
        $parameter = ereg_replace("\r","",$parameter); //去掉回车
        $parameter = ereg_replace("\n","",$parameter); //去掉换行
        $parameter = ereg_replace(" ","",$parameter); //去掉空格
        $parameter = ereg_replace("'","",$parameter); //去掉单引号
        return $parameter;
    }
?>

//方法二

<?php 
    function handel_http($parameter){  
        $parameter = trim($parameter); //$parameter为需要过滤的参数
        $parameter = strip_tags($parameter,""); //清除HTML如<br/>等代码
        $parameter = str_replace("\n", "", str_replace(" ", "", $parameter));//去掉空格和换行
        $parameter = str_replace("\t","",$parameter); //去掉制表符号
        $parameter = str_replace("\r\n","",$parameter); //去掉回车换行符号
        $parameter = str_replace("\r","",$parameter); //去掉回车
        $parameter = str_replace("'","",$parameter); //去掉单引号
        return $parameter;
    }
?>
4.3 上述代码调用方法示例

例如过滤网站注册用户名username参数,那么只需要在漏洞页面的username参数值被写入到数据库之前调用一下函数:

1
2
3
4
5
6
7
8
<?php
  $username = handel_http($username); 
  /
  ***接下来对$username的任何操作就都安全了***
  ***接下来对$username的任何操作就都安全了***
  ***接下来对$username的任何操作就都安全了***
  /
?>
5 Update 2013-03-01 21:01
5.1 定期更新的解决方案库

针对wordpress评论者链接网址重定向跳转插件造成的http拆分响应漏洞,博主给出解决方案,链接地址:http://pan.baidu.com/share/link?shareid=78704&uk=1879910561。在此感谢 “冬哥” 童鞋在评论中给出漏洞代码,博主得以写出解决方案。对于剩余的那几个系统的漏洞,有兴趣的读者可以提供相应的漏洞页面的代码,发到vfhky的邮件或QQ,博主也会及时公布对应的解决方案(请勿直接在文章的留言中加入代码!!!)

5.2 UCHOME漏洞解决演示

更新于2013-03-11 20:31。针对UCHOME中的link.php造成的http拆分响应漏洞,博主给出的解决方案依然是在上面的下载地址中。大家测试看看,记得反馈额。

6 Update 2013-7-15 23:35

根据 @神情话意 的评论反馈,由于函数ereg_replace在PHP5.3中被弃用而报错,所以废除ereg_replace函数的解决方案。建议大家无论自己的服务器的PHP版本是5.2或是5.3等等,统一使用str_replace函数的解决方案。

打赏支持

Comments »