0x00 简介
在文本处理中, CR, LF, CR/LF是不同操作系统上使用的换行符.Dos和windows采用回车+换行CR/LF表示下一行,而UNIX/Linux采用换行符LF表示下一行,苹果机(MAC OS系统)则采用回车符CR表示下一行.CR用符号’r’表示, 十进制ASCII代码是13, 十六进制代码为0x0D; LF使用’n’符号表示, ASCII代码是10, 十六制为0x0A.所以Windows平台上换行在文本文件中是使用 0d 0a 两个字节表示, 而UNIX和苹果平台上换行则是使用0a或0d一个字节表示.
0x01 原理
我们都知道,HTTP协议是依靠两个CRLF,即\r\n来分割HTTP头部及响应体。基于这个认知,可以推出,HRS问题是由于服务端程序没有过滤掉头部中的特殊字符%0D%0A,直接输出到了返回的数据中,导致错误的解析。而在日常开发中,最常见的莫过于有以下的两种功能(1)URL跳转(2)Cookie的设置中出现。
一旦我们能够控制http头,通过注入一些CRLF这样就可以控制header和body的分割线,这样我们就可以向body或是header中注入些东西了。所以CRLF Injection又叫HTTP Response Splitting,简称HRS。
0x02 危害
如果目标网页存在响应头部CRLF注入,在HTTP响应头注入回车换行符,就可以注入头部:
X-XSS-Protection: 0
HTTP header的定义就是基于这样的"Key: Value"的结构,用CRLF命令表示一行的结尾。
"Location:"头用来表示重定向的URL地址,
"Set-Cookie:"头用来设置cookies。
如果用户的输入经过验证,其中存在CRLF的字符就可以被用来达到欺骗的目的。
0x03 实例
测试代码:
index.php
<?php
/*
*@博客:http://byd.dropsec.xyz/
*@Author:w2n1ck
*/
echo '<pre>';
print_r(file("http://www.site1.com/api?test=$test"/images/test.png));
echo '</pre>';
?>
如果攻击者这样发送:
index.php?test=test%20HTTP /1.0%0D%0AHost%3A%20www.site2.com%0D%0AUser-Agent%3A%20joy_nick/0.0%0D%0AReferer%3A%20http%3A%2F%2Fwww.test.org%2F%0D%0ACookie%3A%20user%3Djoy_nick%0D%0A%0D%0AHTTP/1.0%0D%0AHost%3A%20http%3A%2F%2Fwww.SITE1.com%0D%0AUser-Agent%3A%20PHP/4.1.2
(必须在一行上)
这个 HTTP 请求将被发送给 www.site1.com:
GET /api?test=test HTTP/1.0
Host: www.site2.com
User-Agent: joy_nick/0.0
Referer: http://www.test.org/
Cookie: user=joy_nick
HTTP/1.0
Host: www.site1.st
User-Agent: PHP/4.1.2
你可以看到,真实的PHP头信息被正确发送,但被服务器忽略了,因为在它们指向的报头结束之前我们发送两个CRLF。
利用此缺陷,攻击者能够任意添加用户代理(user-agent),referers 和 cookies。如果站点1和站点2是同一台服务器上的虚拟主机,即使index.php有限制,攻击者也能绕过其限制非法访问站点2。
还有一个xss的能够轻松绕过filter的XSS,如果我们输入:
http://www.xxx.com%0d%0a%0d%0a%3Csvg%2fonload%3dprompt%281%29%3E
HTTP/1.1 200 ok
Date: XXX
Content-Type: text/html
Content-Length: 154
Connection: close
<svg/onload=prompt(1)>
从而形成XSS漏洞
0x04 防御
- 您需要限制用户输入CR(0x13)和LF(为0x10)或正确编码的输出,以防止自定义HTTP标头注射。
- 通过在PHP脚本中嵌入如下指令,确保所有这种类型的URL变量在使用时已被清空:
$var = preg_replace(’///s+/’, ’, $var);
- 如果你的脚本不需要访问URLs,建议在php.ini中关闭allow_url_fopen