CRLF入门
CRLF漏洞入门
参考文章:浅入深出谭谈 HTTP 响应拆分(CRLF Injection)攻击(上) - 先知社区 (aliyun.com)
0x00 前言
这段时间有空刷刷BurpSuite的CSRF,有道题需要HTTP头部注入,趁此机会学学。
另外,对漏洞的利用往往不是单独的,而是多个漏洞相互配合。比如本篇的CRLF可以和SSRF、CSRF配合。
0x01 CRLF 与 CRLF Injection
CRLF
CRLF 指的是回车符(CR,ASCII 13,\r,%0d)和换行符(LF,ASCII 10,\n,%0a)的简称(\r\n)。HTTP报文以状态行开始,跟在后面的是HTTP首部(HTTP Header),首部由多个首部字段构成,每行一个首部字段,HTTP首部后是一个空行,然后是报文主体(HTTP Body)。状态行和首部中的每行以CRLF结束,首部与主体之间由一空行分隔。或者理解为首部中每个首部字段以一个CRLF分隔,首部和主体由两个CRLF分隔。
CRLF Injection
HTTP报文的结构以CRLF划分,通过添加CRLF可以制造CRLF Injection,原理如下:
如果Web应用没有对输入做出严格过滤,那么攻击者便可以通过CRLF(%0a%0d)
配合特定字符串,恶意地改变HTTP报文的结构,实现添加Cookie甚至注入HTML代码等操作。所以CRLF注入漏洞又称为HTTP响应拆分漏洞(HTTP Response Splitting),简称HRS。
以下引用阐述更清晰的原文:
在HTTP协议中,HTTP Header 部分与 HTTP Body 部分是用两个CRLF分隔的,浏览器就是根据这两个CRLF来取出HTTP 内容并显示出来。所以,一旦我们能够控制 HTTP 消息头中的字符,注入一些恶意的换行,这样我们就能注入一些恶意的HTTP Header,如会话Cookie,甚至可以注入一些HTML代码。这就是CRLF注入漏洞的核心原理。
更深层地想,这个漏洞其实也是操控数据流入侵控制流。
0x02 CRLF injection应用
Location 字段的 302 跳转
概述
代码如下:
1 |
|
这段代码的意思是:当条件满足时,将请求包中的url参数值拼接到Location
字符串中,并设置成响应头发送给客户端。
思考得更深入一点:正常的url参数值仅仅是纯粹的数据流,不能影响到控制流。但是注入型漏洞往往可以通过自身语法或标准越过这一层限制。
综合上面两段话:url参数会被拼接到响应包的响应头Locaion
后面,我们可以通过%0d%0a
,使程序判断响应头Location
到这里结束,此时后面的payload可以视作下一行的请求头及内容。
正常情况
exp:
1 | /?url=https://xxx.top |
得到的正常的302跳转包:
1 | 302 |
现在尝试拼接
漏洞利用
payload:
1 | /?url=https://xxx.top%0d%0aSet-Cookie: PHPSESSID=whoami |
%0d和%0a分别是CR和LF的URL编码。前面我们讲到,HTTP规范中,行以CRLF结束。所以当检测到%0d%0a后,就认为Location首部字段这行结束了,Set-Cookie就会被认为是下一行
此时得到的302跳转包:
1 | HTTP/1.1 302 |
等跳转后用户就多了个Cookie:PHPSESSID=whoami
总结一下:通过改情况下的CRLF漏洞利用,我们可以给用户添加一个Cookie。但是目前通过 Location 字段的 302 跳转进行 CRLF 注入这个漏洞已经被修复了
PHP fsockopen() 函数
概述
fsockopen() 函数:
fsockopen($hostname,$port,$errno,$errstr,$timeout)
用于打开一个网络连接或者一个Unix 套接字连接,初始化一个套接字连接到指定主机(hostname),实现对用户指定url数据的获取。该函数会使用socket跟服务器建立tcp连接,进行传输原始数据。
fsockopen()将返回一个文件句柄,之后可以被其他文件类函数调用(例如:fgets(),fgetss(),fwrite(),fclose()还有feof())。如果调用失败,将返回false。
漏洞复现–云服务器
本次在服务器上运行如下服务:
1 |
|
url:http://xxx.top:111/index.php
监听的端口:http://xxx.top:112/index.php
payload:
1 | http://xxx.top:111/index.php?url=xxx.top:112/index.php%0d%0aSet-Cookie:1=1 |
响应包如下:
1 | GET / HTTP/1.1 |
但是,上述只是理论,下面谈谈我遇到的问题:
问题
本次利用一个IP的两个端口,使用Xshell7。
第一个问题:
payload只需要%0d,不需要后面的%0a。
第二个问题:
响应包的Set-Cookie有误,后面回环了,我采用多个+来占用,是否有用我不知道。
1 | root@iZ:~# nc -lvp 112 |
漏洞复现–Windows本地phpstorm
代码如下:
1 | <?php |
结果:
1 | root:~# nc -lvp 520 |
只有chr(13),存在回环。CRLF完整,结果正常。
感悟
对比云服务器和本机,有以下不同点:
- payload不同。这其实是输入点不同,一个在url框,另一个在代码处。
- Set-Cookie:1=1是否规范(回环)。
POST请求
概述:
通过添加两个CRLF,尝试构造POST数据包。
不过仍需要注意一个请求头:Content-Type
,需要把其值设置为:application/x-www-form-urlencoded
。
如果原本存在Content-Type
,我们可以尝试把它挤到请求体里(利用对应函数)。其实这里面又涉及到一个思想:
大胆尝试添加,改造,删除数据,而不是仅仅局限于字面意思,只要能达到目的就是好方法。
例子如下:
1 | POST / |
下面的Content-Type: text/xml; charset=utf-8
就是原本的,被挤下去了。
0x03 结语
还有许多历史漏洞没有复现。