好久沒分享東西了,今天分享個實用程式碼審計技巧
使用grep,玩轉程式碼審計,適用於linux/mac,windows需要另行安裝grep:
使用場景如下:快速尋找專案中所有的Sink,快速尋找符合適配條件的所有程式碼檔案
常規的idea,已經不能滿足我們的需求,又要全量Sink,又需要符合適配條件
以java業務程式碼審計為例:
首先列出部分敏感函式:exec(,command(:
使用grep全域性搜尋:
grep -rn "exec(" --include="*.java" ./
這樣我們就可以發現Sink和對應的對應的行數,非常的方便
這個用法,我在程式碼審計中經常用,有個弊端就是,當Sink關鍵字變多了,一次又一次grep,又顯得很浪費時間:
我寫了一個小指令碼:
其中sink.txt是我們的Sink關鍵字:
現在我們使用grep可以批量找sink了,真的令人開心.
但是這不是完美的,不知道大家程式碼審計是否遇到過這種情況,我在程式碼審計中,經常遇到如下場景:
以php某工程程式碼為例子:
一段不需要登入的程式碼:
$PAGE->set_url('/help_ajax.php'); $PAGE->set_context(context_system::instance()); $data = get_formatted_help_string($identifier, $component, true); echo json_encode($data);
訪問/help_ajax.php,響應200,沒有跳轉
一段需要登入的程式碼:
$PAGE->set_url('/admin/dataformats.php'); $PAGE->set_context($syscontext); require_login();
訪問/admin/dataformats.php,響應302跳轉主頁登陸
更多的時候,我們要挖掘前臺的安全漏洞,前臺的rce漏洞比後臺rce價值更大更高,這時候有個需求,也是很多人的需求,獲取所有前臺程式碼檔案:
這裡的兩個特徵:
1.包含set_url(
2.不需要的附加依賴,不包含require_login(,甚至還有別的不需要的附加依賴
一般審計php專案,我都是用vs code,vs code全域性搜尋也很香,我覺得比idea全家桶好用
一個坑:全域性搜尋set_url(,發現存在require_login(,看得很累,工程專案一旦很大,一個個看過去,非常的累
使用正則匹配精準定位:
嘗試過的正則如下:
(1)[^require_login\(\)\;].*set_url\(.*\).*[^require_login\(\)\;].* (2)[^require_login()\;]*|set_url\( (3)(?!require_login).*set_url\(.*\).*(?!require_login).* (4)[require_login();]{0}.*set_url\(.*\)\;.*[require_login();]{0} (5)[require_login();]{0}.*set_url\( (6)[require_login();]{0}set_url\( .....
自己的能力真的是有限的,這些正則,vs code基於正則搜尋,grep -E 基於正則搜尋,均不能得到完全符合規則的程式碼檔案,終究有好幾個不符合條件
這裡,退一步海闊天空:
(1)使用findSink/grep,拿到所有包含set_url(的程式碼檔案:
這兩種方法都可以
(1)find . -name '*.php' | xargs grep 'set_url' (2)grep -r "set_url" --include="*.php" ./
這兩種方法都可以:
拿到所有符合條件的程式碼檔案後:
簡單的處理下:
使用編輯器自帶的正則替換功能:
把:後面的都替換成空
效果如下:
現在我們拿到了所有的檔案
這裡非常感謝rr師傅提供的思路:grep -L
首先單個檔案舉例子:
如果程式碼檔案中包含了require_login關鍵字的,就會返回空,反之,如果不包含require_login關鍵字的程式碼檔案,就會原樣返回:
檔案工程專案很大,一個個grep -L非常的累,這裡我又寫了一個輔助指令碼:
演示效果:
執行程式碼:
現在拿到的所有檔案都是前臺可以訪問檔案:
如果再後續看程式碼中,又發現一些附屬不必要的依賴,同樣可以使用這種方法去篩選,非常的方便快捷!