剛畢業(yè)時(shí)進(jìn)了一家技術(shù)團(tuán)隊(duì)有200多人的公司,第一周熟悉代碼時(shí),順便做了下審計(jì),然后發(fā)現(xiàn)了4個(gè)高危漏洞,說一說當(dāng)時(shí)的一些經(jīng)驗(yàn)
前期準(zhǔn)備(踩點(diǎn))
看文檔
要審計(jì)一個(gè)應(yīng)用,起碼要熟悉這個(gè)應(yīng)用的功能模塊以及底層實(shí)現(xiàn),有現(xiàn)成文檔的話是最快的,作為開發(fā)人員,應(yīng)該第一時(shí)間把項(xiàng)目文檔和依賴的框架文檔都過一遍,這個(gè)對(duì)審計(jì)帶來的收益是持續(xù)的
看提交歷史
提交歷史直接反映了項(xiàng)目近期的狀況,根據(jù)近期代碼提交來觀察是否每一個(gè)開發(fā)都遵循了編碼規(guī)范,編碼規(guī)范不好的人,寫出來的代碼bug數(shù)也會(huì)很高
還可以搜索,比如按fix/修復(fù)/修正/解決等關(guān)鍵字搜索commit message,看下都修復(fù)過那些問題,以及修復(fù)的手法,可以對(duì)該項(xiàng)目的健康程度以及開發(fā)人員水平有一個(gè)了解
搭建項(xiàng)目并用掃描器掃一遍
這樣可以對(duì)這個(gè)項(xiàng)目的目錄結(jié)構(gòu)和安全性等有一個(gè)大致的了解,該花精力著重審計(jì)的功能模塊和優(yōu)先級(jí)心里也有數(shù)了
開始審計(jì)
搜索原始而落后的代碼
我對(duì)原始而落后的代碼的定義,就是明明框架都封裝好的函數(shù)不去用,非要自己用最原始的方式去調(diào)用,或者造了個(gè)渣輪子
比如一個(gè)PHP框架,如CodeIgniter,已經(jīng)對(duì)獲取GET或者POST過來的變量有封裝如:
$this->input->post()
$this->input->get()
如果仍然出現(xiàn)直接取$_GET,$_POST,$_REQUEST這幾個(gè)全局變量的代碼,就證明開發(fā)人員不講規(guī)范,不講規(guī)范的原因是開發(fā)水平低,水平低就容易寫出漏洞,可以從這些位置開始分析
像CodeIgniter這個(gè)框架的
$this->input->post()
$this->input->get()
函數(shù),
第二個(gè)參數(shù)是可選的,用于過濾xss,但是默認(rèn)是false,也就是不過濾...所以寫個(gè)正則去找一下這些代碼的第二個(gè)參數(shù)不填或者是 false 的,然后去追蹤看后續(xù)有沒有進(jìn)行防御過濾,以此類推
搜索sql語句
當(dāng)一個(gè)項(xiàng)目用了框架之后,一般都會(huì)用框架提供的api去操作數(shù)據(jù)庫,不會(huì)直接拼接sql語句,如果代碼里有sql語句,那么很可能是不講規(guī)范的人員寫出來的,同理,不講規(guī)范的人員水平通常不行,當(dāng)然很容易忘記過濾
而且大部分開發(fā)人員如果要手工拼接sql語句了,變量名通常會(huì)叫sql,或者XXXsql
所以搜索的區(qū)域是業(yè)務(wù)代碼里包含sql字樣的代碼,去回溯這些sql拼接的部分是不是用參數(shù)化查詢,如果不是的話是不是用戶可控的,有沒有進(jìn)行防御過濾
尋找富文本輸入框
富文本過濾,無論是經(jīng)驗(yàn)多豐富的程序員,總會(huì)百密一疏,從富文本中可以挖掘的漏洞太多了,如界面劫持
針對(duì)富文本的過濾,PHP里做得屌的是HTML Purifier,其它語言的富文本過濾,可以看本站提交漏洞時(shí)勾選XSS漏洞類型時(shí)的修復(fù)建議
如果一個(gè)PHP程序,有富文本輸入框,而且是提供給前臺(tái)用戶的,又沒有引入HTML Purifier進(jìn)行過濾,而是選擇自己寫一套,或者從其它安全性不高的框架里抄一份過來,那么出漏洞的概率非常高
檢查api語義和規(guī)范
根據(jù)語義以及約定俗成的規(guī)范,讀操作的接口都是用GET請(qǐng)求的,寫操作都是用POST請(qǐng)求的
而市面上成熟的框架,都會(huì)帶有全局的csrf防御,不過一般只針對(duì)POST操作
如果分析出有寫操作的接口,但是對(duì)應(yīng)的是POST請(qǐng)求,肯定是不看規(guī)范的人寫的,這類接口通常就會(huì)有csrf以及其它的問題
復(fù)雜的功能先無腦改http數(shù)據(jù)包,再看代碼
業(yè)務(wù)復(fù)雜的功能,通常交互步驟也多,代碼也很復(fù)雜,直接看的話很容易頭暈,還不如把所有提交的參數(shù)和返回值都改一編,看看有無報(bào)錯(cuò)等信息,一切正常的話再去看代碼
其實(shí)這類功能,邏輯問題是最多的,比如越權(quán)
危險(xiǎn)函數(shù)
這個(gè)先要看自身對(duì)項(xiàng)目所用語言的了解程度,項(xiàng)目的整體架構(gòu),項(xiàng)目的規(guī)模,危險(xiǎn)函數(shù)出現(xiàn)的位置。函數(shù)放在那里就是讓人用的,但是你用的位置不對(duì),還是用戶輸入可控,那就是問題了
就拿系統(tǒng)命令執(zhí)行來說,不是不能用,但是如果一個(gè)電商的搶購功能,用的又是傳統(tǒng)的Web框架,你跟我說在里面加個(gè)exec開定時(shí)任務(wù)之類的,不說別的,我肯定讓你滾回去重做
要知道開啟新進(jìn)程的開銷很大,并發(fā)一上來cpu占用就夠你喝一壺.而且能用這種方案的,連阻塞是什么都不懂,而且執(zhí)行系統(tǒng)命令默認(rèn)在很多語言環(huán)境下都是阻塞的,影響系統(tǒng)性能,如果開多線程去處理,又要涉及到線程池,因?yàn)榫€程不是你想開多少就能開多少的
一般危險(xiǎn)函數(shù)是針對(duì)PHP而言的,因?yàn)镻HP的函數(shù)行為太豐富,特性太多,但是現(xiàn)在PHP的份額在減少,就不多說了
檢查依賴的組件是否已經(jīng)升級(jí)到最新版
沒什么好說的,最怕是線上依賴的版本和測試環(huán)境的不一致,或者線上不是所有的服務(wù)器依賴的都一致,但是你只是審計(jì)而已,已經(jīng)盡力了...
與開發(fā)人員進(jìn)行交流,看看深淺
其實(shí)這不在代碼審計(jì)的范圍,但是如果你知道了開發(fā)人員的深淺,那么根據(jù)他的弱點(diǎn)去審計(jì)他負(fù)責(zé)的代碼,也算是一個(gè)精準(zhǔn)打擊
比如
并下并發(fā)場景下,如何保證商品庫存的一致性
Mysql的鎖機(jī)制是怎么樣的
Redis你都用了哪些特性
項(xiàng)目用了哪些隊(duì)列組件,在什么場景下用的
一個(gè)不懂鎖機(jī)制,不知道隊(duì)列的人,寫出來的代碼的并發(fā)性肯定有問題,如果讓他開發(fā)什么[搶][領(lǐng)][限]這種有次數(shù)限制的寫操作場景功能,絕逼會(huì)有臟讀或者臟寫的漏洞,導(dǎo)致一個(gè)人可以[領(lǐng)多次][搶多次]的漏洞