Joomla3.4.6 RCE漏洞深度分析
- 2019 年 10 月 26 日
- 筆記
筆者《Qftm》原文發佈:https://www.freebuf.com/vuls/216512.html
*嚴正聲明:本文僅限於技術討論與分享,嚴禁用於非法途徑
0×00 背景
10月9號國內幾家安全媒體公布了Joomla RCE的漏洞預警,並且網上已公布漏洞利用EXP,影響版本包括Joomla 3.0.0 – 3.4.6。
0×01 環境搭建
Joomla是一套全球知名的內容管理系統。Joomla是使用PHP語言加上MySQL數據庫所開發的軟件系統,目前最新版本是3.9.11 。可以在Linux、Windows、MacOSX等各種不同的平台上執行。
Joomla環境搭建下載:https://github.com/joomla/joomla-cms/releases/tag/3.4.6
PS:搭建環境要求php 5.3.10以上
0×02 漏洞分析
Session會話機制
PHP本身對Session的存儲默認放在文件中,當有會話產生使用到Session時候,將會在網站服務端設置好的路徑寫入相應的Session文件,文件的內容為默認序列化處理器序列化後的數據。然而在Joomla中則改變了PHP的默認處理規則,相反將序列化之後的數據存放在數據庫的” hzlnp_session”表中存儲:
將序列化之後的數據存放在數據庫中所對應的處理函數為由session_set_save_handler()設置的librariesjoomlasessionstoragedatabase.php 中的write():
相應的取值函數read()也位於librariesjoomlasessionstoragedatabase.php中
接着從代碼中可以看出,在存入數據庫之前,會將傳入數據中的chr(0) . ‘*’ .chr(0) 替換為 , 原因是mysql數據庫無法處理NULL位元組,而protected 修飾符修飾的字段在序列化之後是以x00x2ax00開頭的。然後從數據庫中取出來的時候,再將字符進行替換還原,防止無法正常反序列化。
Session會話逃逸
session 在 Joomla 中的處理存在一些問題,它會把沒有通過驗證的用戶名和密碼存儲在hzlnp_session表中
當用戶在登陸過程中,會有一個 303 的跳轉,主要是用於write()數據庫寫入用戶會話然後read()相應取出會話進行對比,顯示結果
通過分析Session會話機制和Session逃逸我們還不明確Session形成的漏洞到底在哪!
首先需要了解一下PHP的序列化的機制,PHP在序列化數據的過程中,如果序列化的字段是一個字符串,那麼將會保留該字符串的長度,然後將長度寫入到序列化之後的數據,反序列化的時候按照長度進行讀取。
知道PHP序列化過程之後,針對Joomla的內置序列化方法write和read函數,如果寫入數據庫的時候,是 , 取出來的時候將會變成chr(0) . ‘*’ . chr(0),這樣的話,入庫的時候生成的序列化數據長度為6( ), 取出來的時候將會成為3(N*N, N表示NULL),依據PHP反序列化原理,該數據在反序列化的時候,如果按照原先的長度進行讀取,就會導致溢出。
那麼由” ”溢出會造成什麼問題呢?按照PHP反序列化的特點,PHP按照長度讀取指定字段的值,讀取完成以分號結束,接着開始下一個,如果我們能夠控制兩個字段的值,第一個用來溢出第一個字段和第二個字段的前一部分,第二個字段的另一部分用來構造序列化利用的payload,最終序列化結果將會把第一個字段開始部分到第二個字段的前一部分當成第一個字段的全部內容,第二個字段內容成功逃逸出來並且被反序列化。
為了觸發我們的任意對象並實現RCE,我們需要將登錄框處的兩個字段username和password進行處理,第一個字段將導致“溢出”,第二個字段將包含漏洞利用的最後一部分。
漏洞利用大概思路
編寫本地測試代碼
此處偽代碼對Joomla內置的write()、read()函數進行模擬,username字段通過9組”