某logCMS的代碼審計:越權到後臺getshell

某logCMS的代碼審計:越權到後臺getshell

前言

​ 學習CTF這麼久還沒真正意義上審計過一款cms,這次決定花點時間去審計一款cms作為代碼審計提升的跳板。由於相關要求,這裡就省去cms全名了,主要分享一下學習思路。

代碼審計

安裝漏洞

​ 其實一般代碼審計都是從安裝文件開始審計,一般安裝腳本主要存在如下漏洞:

  • 無驗證功能,任意重裝覆蓋
  • 表單不做過濾寫入config.php導致getshell
  • $_GET['step']跳過限制步驟

漏洞文件:install.php

​ 首先我們直奔第一個點能否任意重裝,我們可以看到必須常量DEL_INSTALLER為1的時候才會觸發刪除install.php,那麼我們追蹤DEL_INSTALLER看看

某logCMS的代碼審計:越權到後臺getshell

​ 這裡可以看到DEL_INSTALLER默認值就是0,所以一般情況下這裡是可以任意重裝的,我們從黑盒的測試也可以印證這一點。同時表單也做了過濾所以這裡也沒有後面兩種情況。

某logCMS的代碼審計:越權到後臺getshell

越權漏洞

​ 在安裝完畢後打開config.php看到兩個比較奇怪的常量定義:AUTH_KEY和AUTH_COOKIE_NAME從名字來看這連個常量肯定是有一定聯繫的。如下圖:

某logCMS的代碼審計:越權到後臺getshell

​ 我們在抓包時候發現了AUTH_COOKIE_NAME這個常量,說明這是一個cookie名。我們繼續再代碼中追蹤這個常量。

某logCMS的代碼審計:越權到後臺getshell

​ 我們可以看到在登錄驗證cookie中使用了這個常量,我們追蹤一下cookie值是如何構造的

某logCMS的代碼審計:越權到後臺getshell

​ 這裡可以看到,調用了emHash這個類方法,並且這裡使用了AUTH_KEY這個常量,這裡說明這兩個常量是有聯繫的。我們在繼續追蹤hash_hmac()到底使用key做了什麼。

某logCMS的代碼審計:越權到後臺getshell

​ 這裡對傳入的$key也就是AUTH_KEY進行了md5加密到一個二進制字符串中而後分割為64個字節與一個字符*64次的字符串進行異或最後得到兩個字符串$ipad,$opad最後再將他們打包拼接用md5加密返回給上級調用。我們再回到上級。

某logCMS的代碼審計:越權到後臺getshell

​ 我們知道generateAuthCookie方法中的 $key、$hash是由AUTH_KEY加密而成。最終的cookie是由$user_login 、 $expiration $hash拼接而成,而$expiration是cookie的生存時間,$user_login是用戶名。這裡可以得知$key、$user_login、$expiration都是固定的那麼只要知道AUTH_KEY就有偽造cookie造成越權的可能。

​ 例如我們準備兩個靶機,一個靶機登陸,獲取這個靶機的cookie即可越權登陸另外一個靶機。前提是兩個靶機的AUTH_KEY得一致。這裡有點雞肋但是還是有利用的可能。我們將兩個靶機的cookie拿出來比較確實是一樣的。

某logCMS的代碼審計:越權到後臺getshell

後臺getshell(一)

​ 其實上訴兩個漏洞已經能夠讓我們進入後臺了,現在的任務就是如何Getshell了。這裡我隨便看了一下發現後臺有設置上傳附件後綴的功能。

某logCMS的代碼審計:越權到後臺getshell

​ 但是測試發現,加入php後綴你發現會將phpt替換為X,從源碼中可有很直觀看到這點。

某logCMS的代碼審計:越權到後臺getshell

​ 此時我注意到了備份功能,這個後綴是保存在數據庫中的,既然我不能直接將後綴寫入數據庫,那麼我能不能通過數據備份恢復的方法寫入數據庫呢。

​ 這裡直接備份所有表,下載下來然後找到寫入後綴的語句,加上php,如下

某logCMS的代碼審計:越權到後臺getshell

某logCMS的代碼審計:越權到後臺getshell

​ 導入備份後發現設置中的上傳後綴有php

某logCMS的代碼審計:越權到後臺getshell

​ 直接在文章發表出上傳PHP文件即可getshell

某logCMS的代碼審計:越權到後臺getshell

後臺getshell(二)

​ 我們還發現這個cms中上傳插件的地方可以上傳zip,這裡我們想如果在插件中插入一句話木馬是不是也能getshell?我們找到插件上傳的腳本,發現使用了一個叫emUnzip的函數。

某logCMS的代碼審計:越權到後臺getshell

​ 我們繼續追蹤這個函數,發現這個解壓函數是使用ZipArchive()類來實現解壓縮的。我們可以看到代碼755行中獲取了壓縮包的內部目錄/文件的名稱 ,並將其分割為數組將第一個元素賦值給了$dir,我們看到switch中plugin選項,這裡又將獲取的第一個文件夾名稱賦值給$plugin_name,使用getFromName方法獲取了壓縮包是否存在$dir . $plugin_name . '.php'這個文件。綜上這裡就是檢測壓縮包中文件夾裡面是否存在一個與文件夾名稱一致的PHP文件,最後在再壓。這裡也沒對文件進行其他校驗操作。因此我們只要再構造 文件夾名和文件名相同的內容的壓縮包,同時由上方代碼也可以知道,文件將會被解壓到 /content/plugins/a/a.php(文件夾名稱a)

某logCMS的代碼審計:越權到後臺getshell

構建壓縮包上傳插件:

某logCMS的代碼審計:越權到後臺getshell

總結

​ 這次代碼審計也是十分傳統地從安裝文件入手,黑盒結合白盒測試的方法進行審計。總的來說作者有一點安全意識在輸入時候對php進行過濾,但是如果服務器是iis可以解析asp但是這裡並沒有對asp進行過濾,並且如果服務器解析phtml這些後綴在附件上傳處同樣可以getshell。總的來說在開發時候上傳部分應當鎖死不應讓用戶可控。


分享到:


相關文章: