Thinkphp <= 5.0.10 緩存getshell復現


Thinkphp <= 5.0.10 緩存getshell復現

0x01 poc

首先看緩存函數的使用場景

然后會生成以下緩存文件

可以看到,字符串abc直接存儲到以php結尾的緩存文件中。嘗試使用\n換行getshell

語法有錯,注釋一下后面的垃圾字符,成功getshell。

0x02 跟蹤源碼

首先跟進18行的Cache::set()函數

跟進self::init()

self::$handler此時為null,進入true塊,由於上面調用的是self::init(),沒有參數,故67行條件不滿足。

69行,查看配置cache.type的值,發現默認為File,

故此條件也不滿足,進入72行。此處以上圖的cache數組作為參數,調用了self::connect()。跟進connect方法

這里通過一系列判斷,根據cache.type的值,找到cache驅動為File,對應44行的think\cache\driver\File類。然后在51行進行實例化,並return。

回溯到上個函數,也直接return

繼續回溯

這里調用了return過來的實例的set方法。跟進think\cache\driver\File的set方法

可以看到,在142行調用了getCacheKey方法。

跟進getCacheKey方法后發現,這里由於options['cache_subdir']默認值是true,所以這里直接用參數md5加密后的結果的前兩位作為目錄名,剩余30位作為緩存文件名。然后通過拼接.php后return。

繼續回來,獲取上面構造的filename之后,在146行將$value進行序列化,然后在149行使用gzcompress對其進行二進制壓縮。接着在151行在data前后拼接php標簽,最后在152行寫文件。

這里存在漏洞的點就是151行把用戶可控的數據放到了php標簽內。

0x03 審計思路

拿到源碼后,找到Cache::set(name, value, expire),其中緩存文件名是跟name相關聯的,因此可以看作是一個已知條件。漏洞的關鍵點就是value是否可控。

0x04 補丁

看一下修復之后的結果(v5.0.15)

這里在data之前加了一個exit()強制退出,基本杜絕了data執行php代碼的可能。

0x05 參考

ThinkPHP 5.0.10-3.2.3 緩存函數設計缺陷可導致 Getshell


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM