靜態掃描就是不執行程式,透過掃描原始碼的方式檢查漏洞,常見的方法也有多種,如把原始碼生成 AST(抽象語法樹)後對 AST 進行分析,找出使用者可控變數的使用過程是否流入到了危險函式,從而定位出漏洞;或者透過正則規則來匹配原始碼,根據平常容易產生漏洞的程式碼定製出規則,把這些規則代入到程式碼中進行驗證來定位漏洞。當然靜態掃描由於不執行程式也有好多事情處理不了,如程式透過運算得到的一個結果後,就沒辦法分析這個結果了,所以需要動態執行程式來解決這個問題,也就是動態掃描,動態掃描可以透過單元測試或人工掃描等方式,下麵分別介紹一下 AST 掃描 與 正則匹配兩種常見靜態掃描方式。
AST(抽象語法樹)掃描
此方式把原始碼生成 AST(抽象語法樹),找出使用者可控的 source (如 location.href
,document.url
,document.documentURI
) 是否流入到了敏感的 sink (如 evil
,new function
,setTImeout
,setInterval
) 中,常見的 source 與 sink 可參考這個檔案:
https://docs.google.com/spreadsheets/d/1Mnuqkbs9L-s3QpQtUrOkPx6t5dR3QyQo24kCVYQy7YY/edit#gid=0。
掃描程式負責把所有的 source 與 sink 查找出來,並找出 source 已流入到了 sink 中的程式碼已及行號,並存入到結果中,舉個例子:
document.getElement(‘girl’).innerHTML = location.href.split(#)[1]
這句程式碼命中了 source 流入到了敏感 sink 中,從而產生了漏洞,也很明顯能看出產生了 domXss,不過在實際情況中更加複雜,如把 source 當成了函式引數,經過了多個函式處理,掃描程式就需要跟蹤這些這種流入到不同的函式中的情況。
正則匹配
這種方式比較簡單,就是匹配程式中是否出現了哪些敏感字元,如 bodyParse()
或者敏感程式碼,當函式中的程式碼命中了設定的規則,則就產生了漏洞,舉個例子
(.readFile()(.{0,40000})(req.|req.query|req.body|req.param)
上面是一條正則規則,當函式中有一行程式碼為 fs.readFile('/etc/'+req.param.path)
,則命中了規則並報出有漏洞。
Javascript 掃描工具介紹
下麵分別介紹兩款工具,jsprime
和 NodeJSScan
的介紹與實現原理,其中 jsprime
是透過分析 AST 掃描,NodeJSScan
是透過正則運算式掃描。
jsprime
效果圖,左邊是原始碼,右邊是分析結果
jsprime 是一個靜態程式碼分析工具,其核心是基於 Esprima ECMAScript 生成 AST 進行掃描,此工具有在 blackhat 上演講過,他的主要功能有:
https://www.slideshare.net/nishantdp/jsprime-bhusa13new
1、JS 庫 source 與 sink 識別
2、JQuery 及 YUI 框架識別
3、變數與函式追蹤(這項功能作為我們程式碼流分析演演算法的組成部分)。
4、變數與函式內容識別分析(這項功能作為我們程式碼流分析演演算法的組成部分)。
5、已知過濾器功能識別。
6、遵循面向物件程式與原型設計合規標準。
7、最大程度降低誤報機率。
8、支援 JavaScript 程式碼精簡。
9、極高執行速度。
10、只需點選即可操作.
JSPrime 是怎麼工作的?
1、把原始碼喂給 Esprime,Esprime 負責把程式碼生成 AST。
2、接下來就是解析 JSON AST(Esprime 會生成 JSON 格式的 AST)。
3、找出所有的 sources(包括 物件,原型) ,同時跟蹤 sources 的作用範圍。
4、找出 sources 別名,也就是把 soruce 值賦值給了另一變數,同時跟蹤 sources 的作用範圍。
5、找出 sinks 和 sinks 別名,同時跟蹤他們的作用範圍。
6、找出 sources 被哪些函式當成引數使用,包括閉包函式、匿名函式,同時跟蹤他們的傳回值。
7、當所有的 sources 和 source 別名被收集,檢查其中的 source 有過濾函式處理了的,則放棄。
8、剩下的 source 當被賦值給 sinks 或被傳遞為引數操作後到達 sinks 的,則跟蹤這些 source。
9、以同樣的流程,按照反向重覆一次,以確認我們可以反向到達同一個 source。
10、一旦確認 source 流入到了 sink 中,則取出行號和陳述句,然後以不同顏色輸出到報表中。
使用方法
1、下載原始碼:
http://dpnishant.github.io/jsprime/
2、解壓進入到 jsprime-node 檔案夾
3、node server.js
4、開啟 http://localhost:8888
5、把程式碼貼到框中進行分析
6、有一些測試程式碼,可參考:
https://docs.google.com/document/d/17J2h43WbPX3sNTIjxr4GhzEGxKy6hvQJqedd3UQ11mY/edit
參考檔案
jsprime-blackhatusa13new:
https://www.slideshare.net/nishantdp/jsprime-bhusa13new
DOM XSS Sources & sinks:
https://docs.google.com/spreadsheets/d/1Mnuqkbs9L-s3QpQtUrOkPx6t5dR3QyQo24kCVYQy7YY/edit
ra2-dom-xss-scanner:
https://code.google.com/archive/p/ra2-dom-xss-scanner/
NodeJSScan
NodeJSScan 是一套用 python 實現的 node 應用程式碼掃描器,他的原理是透過正則運算式來匹配原始碼檔案中的每一行,每個正則運算式都代表一種漏洞掃描規則,如是否使用了 url 中的值當成 readFile 函式引數,把這些規則用來檢查程式碼中的每一行,一旦匹配則就說明有漏洞。
舉個例子:
(.readFile()(.{0,40000})(req.|req.query|req.body|req.param)
這是一條正則運算式,當程式碼中存在類似 readFile("/etc/"+req.param.path)
的程式碼就命中了上面的規則,從而報出有漏洞。
NodeJSSCan 實現原理
1、使用者把程式碼打包成一個 zip 包並上傳,服務端解壓這個包
2、迭代每一個檔案(有檔案夾則遞迴)把讀出檔案內容
3、檔案內容透過 jsbeautify 格式化,並把註釋去掉
4、迭代每一行,把程式碼代入設定的規則中(正則,或字串查詢),當匹配了,則記錄起來
6、把匹配規則的程式碼行按類別存放,如 rce,xss,ssrf,sqli
7、生成結果報