前言
Open Source Social Network(OSSN),是一款用PHP編寫的社交網絡軟件。OSSN允許用戶創建一個社交網站,幫助擁有相似專業或個人興趣的人建立社交關系。該軟件擁有約50萬下載量。
OSSN官網地址:
https://www.opensource-socialnetwork.org/
漏洞簡介
Open Source Social Network(OSSN)5.3之前版本中存在一處任意文件讀取漏洞(CVE-2020-10560)。漏洞因OSSN生成的Site_Key強度過低從而可以遭受被暴力破解而產生,成功破解Site_Key的攻擊者可以利用Site_Key構造出任意文件讀取鏈接,通過components\OssnComments\ossn_com.php文件提供的文件預覽接口,讀取文件。
漏洞分析
Open Source Social Network應用可以從如下官網鏈接下載:
https://www.opensource-socialnetwork.org/download
應用首頁如下圖
OSSN中提供Comment功能,訪問者可以對帖子進行評論,見下圖:
評論帖子時,用戶可以上傳圖片以及表情,如下圖紅框處:
當選擇本地圖片並上傳后,將在評論中生成一個預覽,見下圖:
注意,這時還沒有點擊發布評論,上圖圖片只是上傳成功后的一個預覽圖片。該臨時圖像文件存儲於tmp目錄並在前端呈現了預覽。
我們來看下這個臨時圖片文件是如何獲取並在頁面中展示的。查看一下圖片鏈接,如下圖:
鏈接如下:
我們可以猜測出image參數對應的字符串應該是文件地址的加密形式,只有構造出正確的base64字符串,攻擊者就可以讀取任意文件。
最重要的是,經過測試發現,訪問這個鏈接並不需要用戶登陸。任何人都可以通過這個鏈接直接訪問我們上傳的這個圖片文件。
接下來分析下后台代碼,看看這個base64字符串是如何還原出文件路徑以及如何被構造出來的
上文鏈接對應的后台代碼位於 \components\OssnComments\ossn_com.php
在ossn_com.php中case 'staticimage'分支里,程序將請求中image參數值取出,並進行base64_decode解碼。見下圖:
隨后,對解碼后的值再次base64_decode解碼,然后利用ossn_string_decrypt方法解碼並獲取文件地址。見下圖:
接着,通過ossn_validate_filepath方法對文件路徑進行校驗。見下圖紅框:
ossn_validate_filepath方法如下圖所示,可見該方法對目錄遍歷進行了過濾
即使過濾了../ 我們仍然可以通過絕對路徑來進行文件讀取,例如直接讀取/etc/passwd
最后,程序利用file_get_contents方法對文件內容進行讀取,並使用echo進行打印。見下圖紅框:
通過閱讀代碼也可以驗證之前的測試結果:該接口並未進行身份校驗,未登錄的用戶依然可以通過該接口訪問文件。
問題又回到了如何構造加密字符串上。我們首先來看一下程序是如何解碼的,位於libraries\ossn.lib.system.php文件中
通過上圖的代碼看,在解碼過程中,需要用到site_key值。
經過分析后發現,程序通過ossn_site_settings方法在數據庫中讀取site_key值,我們先來看一下存儲於ossn_site_settings表中site_key值是什么,見下圖:
site_key值為c1a725ed,可見是一個8位數
這樣看來,只要破解出這個8位數的site_key,即可構造出指向任意文件路徑的鏈接。
我們接着分析這個site_key是如何生成的,生成代碼位於libraries\ossn.lib.upgrade.php文件中,見下圖:
通過分析上圖加密過程不難發現,該8位隨機數是通過如下方式產生的:
-
以字符串“ ossn”開頭。
-
通過rand方法生成一個隨機數並拼接到“ ossn”字符串后。
-
計算此字符串的md5值。
-
將字符3-11取出作為site_key值。
本次漏洞就出在計算site_key值的第二步,也就是通過rand產生隨機數這一步。
關於rand方法,可以參考php官網
在官網介紹頁面中明確的給出了警告,見上圖底部
警告
此函數不會生成加密安全值,並且不應將其用於加密目的。如果需要密碼安全的值,請考慮改用random_int(),random_bytes()或openssl_random_pseudo_bytes()。
rand方法之所以不安全,其中一個比較重要的原因是它能產生的隨機數范圍有限:
rand方法在沒有提供可選參數 min 和 max時,返回 0 到 RAND_MAX之間的偽隨機整數.
在筆者的windows主機上,RAND_MAX值僅為32767
而在筆者的Linux環境中,這個值為2147483647
據資料顯示,rand最大可能值為2,147,483,647
因此,只需要生成最多20億個rand值,將其依次帶入ossn_generate_site_secret計算出對應的site_key值,這些site_key值即為所有的site_key值可能值。如果運氣好,目標主機是一台windows主機,這樣的操作僅僅重復3萬多次即可,因為windows主機下rand產生的最大值僅為32767。
在分析了弱密鑰是如何生成之后,我們需要一種方法來識別生成的密鑰是否有效。在臨時圖片文件被上傳到服務器時,會被存儲於ossn_data/tmp/photos文件夾中,見下圖:
因此上文中的加密數據成功解碼后,其字符串中一定會包含tmp/photos字符串。我們這里用我們的密鑰解一下上文中的編碼,看一下這個推論是否正確,結果如下圖:
可見成功解開的文件路徑中的確存在tmp/photos字符串
因此,暴力破解的思路很明朗了
1、攻擊者在評論里上傳一個圖片,不點擊發送,查看此時圖片臨時預覽鏈接,獲取鏈接中image參數值。例如:http://192.167.30.119/comment/staticimage?image=UiszT0RJYStoQll2N2g5cHhmQW9PRHlCNVgrSWFKVzFQRHE4eTJqSWthVUVjUFBIb3pxME1FNUJFdk5ER2pONXI4V2pyeXJSMm9VPQ==中的UiszT0RJYStoQll2N2g5cHhmQW9PRHlCNVgrSWFKVzFQRHE4eTJqSWthVUVjUFBIb3pxME1FNUJFdk5ER2pONXI4V2pyeXJSMm9VPQ==>
2、將數字0-2147483647依次帶入ossn_generate_site_secret中計算出對應的site_key
3、依次將site_key與image值帶入ossn_string_decrypt中,獲取解密后的明文
4、如果明文中含有tmp/photos字符串,解密成功,此時的site_key即為正確的site_key值
漏洞利用
在獲取site_key值后,可以通過ossn_string_encrypt方法,對想要讀取的文件進行加密,通過http://192.167.30.119/comment/staticimage?image=接口進行讀取即可
上文所涉及的工具如下:
site_key計算工具
https://github.com/LucidUnicorn/CVE-2020-10560-Key-Recovery
加密解密工具