利用Thinkphp 5緩存漏洞實現前臺Getshell

網站制作12年

利用Thinkphp 5緩存漏洞實現前臺Getshell

2018-08-11 17:12:13


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框架。 

1.png

2.使用 dirsearch 掃描目標網站。python3 dirsearch.py -u site_ip_here -e php發現可以訪問 cache目錄,說明可能存在緩存漏洞。 

2.png

實施攻擊

1.考慮到這是一個論壇類網站,嘗試發帖注入緩存。

3.png

2.這是最困難的一步,猜解緩存中的php文件名。根據框架實現,文件名是一個唯一字符串的md5碼(此處的md5要用php的函數計算,測試發現和網上的一些在線平臺計算結果不同)。考慮到論壇類網站有大量的帖子,需要用數據庫存儲,而帖子的索引應該為很有可能為id 。

再結合url的路徑名,猜測為article_id

echo(md5(“article_52″));

12a51218427a2df68e54e8f4c8b10109 

4.png

通過訪問緩存成功getshell 

5.png

0×03 原理分析:

框架

在thinkphp框架中,/thinkphp/library/think/cache/driver/File.php中定義了緩存的實現。其中,getCacheKey($name)函數實現了cache文件路徑的計算,為獲得緩存文件名稱提供了可能。

6.png

而set()與get()函數以序列化對象的方式無過濾地實現了緩存數據的寫入與讀出,為代碼注入緩存提供可能。

7.png

8.png

通過測試,可以發現帖子中的內容可以直接寫入緩存文件。

9.png

由于緩存文件是一個php文件,可以進行代碼注入。在代碼前加一個回車,使代碼行獨立于前面的注釋行。再在末尾加上注釋符號//,注釋剩余內容。

 

網頁實現

在處理帖子的代碼中,讀取帖子首先查詢cache文件,通過調用thinkphp5框架中的cache接口實現。

11.png

0×04 防御:

1. 從框架入手,在/thinkphp/library/think/cache/driver/File.php 中的set()函數中對于$value參數進行過濾,去除換行符號。(具體代碼見參考資料)缺點: 可能會導致緩存文件在展示時文本布局的改變。

2. 從網頁實現入手,讀取緩存時的使用的唯一索引可以設置的比較復雜,讓攻擊者無法猜到。如: 3ae282ad69314d68_article_id

3. 從服務器的配置入手,關閉從外部對于cache文件夾的直接訪問。

4. 從php的配置入手,關閉eval等危險函數。

宁夏11选5走势图新浪