CRLF漏洞以及SOAP漏洞利用之CRLF与SSRF
CRLF漏洞
漏洞原理
CRLF是“回车+换行(\r\n)”的简称,在http协议中,httpheader和httpbody是用两个CRLF分隔的,浏览器是根据这两个CRLF来取出http内容并显示出来的,所以如果我们可以控制http消息头的字符,注入一些恶意的换行,这样可以注入一些会话Cookie或HTML代码,所以CRLF injection也叫HTTPReaponseSplitting,简称HRS
CRLF注入产生的会话固定漏洞
当我们可以控制httpheader中的location字段时,我们可以就可以给访问者设置一个SESSION
实例
1 | HTTP/1.1 302 |
然后当我们输入
1 | http://www.sina.com.cn%0d%0aSet-cookie:JSPSESSID%3Dwooyun |
此时我们就设置了一个SESSION,造成会话固定漏洞
1 | HTTP/1.1 302 Moved Temporarily Date: Fri, 27 Jun 2014 17:52:17 GMT |
CRLF注入造成无视浏览器Filter反射型XSS
实例
当一个网站接受url参数http://ip/?url=xxx,xxx放在location后面作为一个跳转,所以我们可以输入
1 | http://test.sina.com.cn/?url=%0d%0a%0d%0a<imgsrc=1onerror=alert(/xss/)> |
则我们的返回包为
1 | HTTP/1.1 302 Moved Temporarily Date: Fri, 27 Jun 2014 17:52:17 GMT Content-Type: text/html Content-Length: 154 Connection: close Location: |
之前说的浏览器会根据两个CRLF把HTTP包分成头和体,然后将体显示出来,所以这里这个标签会显示出来,,造成xss
对于无视filter,只有数据包中http头中含有X-XSS-Protection并且为0时,浏览器才不会开启filter,所以我们可以利用一个CRLF将X-XSS-Protection: 0注入到数据包中,再用两个CRLF来注入xss代码,这样就可以绕过filter
而对于Location的注入只有webkit内核浏览器可以使用,其它浏览器可能会跳转
SOAP漏洞利用之CRLF与SSRF
每种开发语言都有自己的webservice实现框架,php也有,php的SOAP扩展是可以提供和使用webservices,这个扩展实现六个类
1 | 高级类:SoapClient、SoapServer、SoapFault |
SoapClient语法
1 | public SoapClient :: SoapClient (mixed $wsdl [,array $options ]) |
由于SoapClinet类中的一个$options选项功能有这样一句话
1 | The user_agent option specifies string to use in User-Agent header |
可见这个类可以让我们自定义user-agent,而httpheader有一个重要的content-type和content-length字段,可以控制发送的方式以及内容的长度,而user-agent在它们的上面,所以可以进行覆盖
因此我们可以利用CRLF来构造payload
1 | $payload = new SoapClient(null,array('user_agent'=>"testrnCookie: PHPSESSID=08jl0ttu86a5jgda8cnhjtvq32rnContent-Type: application/x-www-form-urlencodedrnContent-Length:45rnrnusername=admin&password=nu1ladmin&code=470837rnrnrn",'location'=>$location, |
这个攻击的作用是从外网调用到soap的api来攻击内网,因此可以说是ssrf攻击
而这个攻击一般是利用SoapClient类中的魔术方法__call()触发的,猜测是触发__call()魔术方法发包
实例(bestphp’s revenge)
打开页面,审计源码
1 | <?php |
由于call_user_func()函数限制了一些函数,eval()函数在其中,而构造/flag.php,又得到一部分源码
1 | session_start(); |
可见我们要本地访问/flag.php才可以读取flag,所以我们可以利用SoapClient类来ssrf,首先我们需要利用反序列化来控制SoapClient类中的变量,所以我们可以利用序列化引擎和反序列化引擎的不同,导致无法正常反序列化,从而伪造数据
所以我们可以利用第一个call_user_func来构造
1 | session_start(['serialize_handler'=>'php_serialize']) |
来让序列化和反序列化的引擎不同,然后再通过将序列化数据赋值给$_SESSION[“name”],让它将数据存储到文件时再进行序列化,并进行变量覆盖,然后取出文件,放进内存时进行反序列化,而由于我们设置的序列化和反序列化的引擎不同,所以当反序列化时会将”|“前面的值当成是键名,从而可以触发漏洞,exp
1 | <?php |
所以我们可以先构造
1 | get提交 |
然后我们再构造
1 | get提交 |
通过extract函数来对$b变量进行覆盖,然后再通过调用SoapClient类中不存在的welcome_to_the_lctf2018函数来触发__call()魔术方法,从而将flag赋值给$_SESSION[“flag”]
最后用刚刚构造的PHPSESSID值来读取flag
1 | PHPSESSID=tcjr6nadpk3md7jbgioa6elfk4 |
参考文章:[https://cloud.tencent.com/developer/article/1515276]
[https://www.anquanke.com/post/id/153065#h2-1]
[https://www.jianshu.com/p/d4c304dbd0af]
[https://www.cnblogs.com/iamstudy/articles/unserialize_in_php_inner_class.html#_label1_0]