使用grep命令,玩轉程式碼審計尋找Sink

飄渺紅塵✨發表於2021-11-11

  好久沒分享東西了,今天分享個實用程式碼審計技巧  

  使用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非常的累,這裡我又寫了一個輔助指令碼:

  

  演示效果:

 

  

 

   執行程式碼:

  現在拿到的所有檔案都是前臺可以訪問檔案:

  

 

   如果再後續看程式碼中,又發現一些附屬不必要的依賴,同樣可以使用這種方法去篩選,非常的方便快捷!

   相關程式已傳到git:https://github.com/maniacs1/findSink/releases

相關文章