利用Thinkphp 5緩存漏洞實現前臺Getshell
0×00 背景
網站為了實現加速訪問,會將用戶訪問過的頁面存入緩存來減小數據庫查詢的開銷。而Thinkphp5框架的緩存漏洞使得在緩存中註入代碼成為可能。(漏洞詳情見參考資料)
本文將會詳細講解:
1. 如何判斷緩存漏洞存在的可能性
2. 如何利用Thinkphp5的框架漏洞結合網站的一些配置實現前臺getshell
希望可以給予讀者一些關於漏洞應用的啟發。
0×01 環境
測試環境
1.某基於Thinkphp5.0.10搭建的論壇類測試網站
2.apache2
3.php5.6及以上版本,相關php組件
4.mysql
工具
1.dirsearch (github上的一個用python編寫的網站路徑掃描工具)
0×02 實現
判斷緩存漏洞存在的可能性
1.查看網頁的cookie,發現存在thinkphp_show_page_trace字段,確定網頁基於thinkphp框架。
2.使用 dirsearch 掃描目標網站。python3 dirsearch.py -u site_ip_here -e php
發現可以訪問 cache目錄,說明可能存在緩存漏洞。
實施攻擊
1.考慮到這是一個論壇類網站,嘗試發帖註入緩存。
2.這是最困難的一步,猜解緩存中的php文件名。根據框架實現,文件名是一個唯一字符串的md5碼(此處的md5要用php的函數計算,測試發現和網上的一些在線平臺計算結果不同)。考慮到論壇類網站有大量的帖子,需要用數據庫存儲,而帖子的索引應該為很有可能為id 。
再結合url的路徑名,猜測為article_id
echo(md5(“article_52″));
12a51218427a2df68e54e8f4c8b10109
通過訪問緩存成功getshell
0×03 原理分析:
框架
在thinkphp框架中,/thinkphp/library/think/cache/driver/File.php中定義了緩存的實現。其中,getCacheKey($name)函數實現了cache文件路徑的計算,為獲得緩存文件名稱提供了可能。
而set()與get()函數以序列化對象的方式無過濾地實現了緩存數據的寫入與讀出,為代碼註入緩存提供可能。
通過測試,可以發現帖子中的內容可以直接寫入緩存文件。
由於緩存文件是一個php文件,可以進行代碼註入。在代碼前加一個回車,使代碼行獨立於前面的註釋行。再在末尾加上註釋符號//,註釋剩余內容。
網頁實現
在處理帖子的代碼中,讀取帖子首先查詢cache文件,通過調用thinkphp5框架中的cache接口實現。
0×04 防禦:
1. 從框架入手,在/thinkphp/library/think/cache/driver/File.php 中的set()函數中對於$value參數進行過濾,去除換行符號。(具體代碼見參考資料)缺點: 可能會導致緩存文件在展示時文本布局的改變。
2. 從網頁實現入手,讀取緩存時的使用的唯一索引可以設置的比較復雜,讓攻擊者無法猜到。如: 3ae282ad69314d68_article_id
3. 從服務器的配置入手,關閉從外部對於cache文件夾的直接訪問。
4. 從php的配置入手,關閉eval等危險函數。
0×05 參考資料:
https://paper.seebug.org/374/
利用Thinkphp 5緩存漏洞實現前臺Getshell