0
6月21日,一則刑事判決書出現(xiàn)在大眾眼里,其中幾位被告人用爬蟲抓取服務(wù)器內(nèi)容,一審判決認(rèn)為他們觸犯了《刑法》第 285 條”非法獲取計(jì)算機(jī)信息系統(tǒng)數(shù)據(jù)罪”,判處有期徒刑和罰金XXX。(點(diǎn)這里)
底下的圍觀群眾炸了:
網(wǎng)友甲:剛學(xué)爬蟲沒多久,是不是要棄坑了?
網(wǎng)友乙:怎么辦,跑嗎?
網(wǎng)友丙:做爬蟲的我瑟瑟發(fā)抖.jpg
網(wǎng)友?。号老x工程師這個(gè)崗位是不是要涼?
不過也有比較理智的群眾,比如說:離職員工利用對(duì)系統(tǒng)的熟悉,或者也許是自己留的后門,偽造特定 UA 抓取內(nèi)容被老東家告了。
還比如:大家不要恐慌,有看到v2有知情人說其實(shí)不是爬蟲,是在內(nèi)部服務(wù)器偷數(shù)據(jù)。
總之爬蟲技術(shù)這個(gè)明星詞匯又進(jìn)入了大眾眼中,有緣的是,就在不久前由阿里云主辦的先知大會(huì)上,雷鋒網(wǎng)宅客頻道也聽到一個(gè)有關(guān)爬蟲的議題。
演講者是阿里云高級(jí)安全專家豬豬俠,長(zhǎng)期從事自動(dòng)化安全測(cè)試工作,熟悉多種開發(fā)技術(shù),擅長(zhǎng)滲透測(cè)試與數(shù)據(jù)挖掘。
豬豬俠介紹了如何基于歷史經(jīng)驗(yàn)和已知場(chǎng)景,構(gòu)造并實(shí)現(xiàn)一個(gè)動(dòng)態(tài)爬蟲。通過瀏覽器提供的Headless調(diào)試模式,來(lái)遍歷一個(gè)網(wǎng)頁(yè)的所有動(dòng)態(tài)對(duì)象,自動(dòng)填充輸入表單的參數(shù)值,并觸發(fā)對(duì)象上的綁定的事件,有效解決安全測(cè)試過程中的攻擊面挖掘。
以下為豬豬俠演講內(nèi)容,雷鋒網(wǎng)整理。
在講爬蟲技術(shù)之前,先思考一個(gè)問題:我們?yōu)槭裁葱枰粋€(gè)掃描器爬蟲?
據(jù)大量調(diào)查分析顯示,國(guó)內(nèi)多數(shù)企業(yè)做安全測(cè)試時(shí)還停留在人肉過程中。自動(dòng)化測(cè)試程度相對(duì)較低,且企業(yè)在日常安全測(cè)試過程中,投入了大量人力成本在重復(fù)性工作上。
人畢竟是血肉之軀,有時(shí)候會(huì)累,也有時(shí)候情緒激動(dòng)??赡苣彻緶y(cè)試人員在心情不好時(shí)候做測(cè)試,最后的安全測(cè)試結(jié)果就是看心情,只有攻擊面和測(cè)試準(zhǔn)備充分的時(shí)候才能夠得到保障。同時(shí)Web2.0框架很活躍,導(dǎo)致非常多的是失效的,他們的爬蟲無(wú)法識(shí)別出整個(gè)網(wǎng)頁(yè)的鏈接結(jié)構(gòu)。
這個(gè)時(shí)候我們需要一個(gè)爬蟲幫助我們提升整個(gè)安全測(cè)試的效率。
首先,業(yè)界同行和安全工程師是怎么實(shí)現(xiàn)爬蟲的?先舉一個(gè)例子,之前微信群有個(gè)朋友說,他使用下圖這串代碼爬取seebug沒有爬到結(jié)果。這是因?yàn)閟eebug網(wǎng)站利用了代碼混淆的技術(shù),并一直頻繁更新,最終導(dǎo)致以前純靜態(tài)性的爬蟲完全失效。
怎樣解決靜態(tài)爬蟲的缺陷?
只需要引入一點(diǎn)新的技術(shù),比如說帶GS引擎的爬蟲就能夠解決這個(gè)問題,你用PIP安裝一個(gè)安裝包,使用左邊的代碼就能夠完整的爬到seebug的鏈接信息了。
這個(gè)項(xiàng)目是繼承谷歌的無(wú)界面瀏覽器開發(fā)的。無(wú)界面建成為healless瀏覽器,現(xiàn)在有四種,它們?nèi)秉c(diǎn)是使用諸多第三方庫(kù)非常不穩(wěn)定。后來(lái)phantomjs出現(xiàn),但phantomjs有很多無(wú)法修復(fù)的問題,作者之后宣布不再對(duì)其進(jìn)行維護(hù),只能選擇谷歌的無(wú)界面瀏覽器。
為什么使用谷歌的phantomjs進(jìn)行爬蟲,主要有三點(diǎn)。第一有谷歌大廠支持,谷歌瀏覽器世界占有率第一,穩(wěn)定率高,幾小時(shí)一個(gè)版本更新。另外谷歌對(duì)W3C標(biāo)準(zhǔn)組織的支持度在全球所有瀏覽器中是最高的,兼容性也較好。
回到今天的主題,什么是啟發(fā)式爬蟲?
簡(jiǎn)而言之啟發(fā)式爬蟲是基于所有歷史經(jīng)驗(yàn)及曾經(jīng)看到過的已知場(chǎng)景,通過分析這些場(chǎng)景和利用已知的經(jīng)驗(yàn)構(gòu)建并實(shí)現(xiàn)規(guī)則的爬蟲。
接下來(lái)我們來(lái)看看整體的啟發(fā)式爬蟲最佳實(shí)踐流程。首先可以把爬蟲看作一個(gè)工廠流水線系統(tǒng),流水線系統(tǒng)一定會(huì)有一個(gè)總隊(duì)長(zhǎng)負(fù)責(zé)各條生產(chǎn)線任務(wù)調(diào)度,在這里ROP就是總隊(duì)長(zhǎng)。流程明確后,每個(gè)步驟都各司其職實(shí)現(xiàn)各自的功能。
爬蟲總隊(duì)長(zhǎng)這個(gè)管理器的功能負(fù)責(zé)任務(wù)調(diào)度和事件管理。在做掃描器爬蟲的第一步先將URL傳給任務(wù)調(diào)度器總隊(duì)長(zhǎng),總隊(duì)長(zhǎng)把這個(gè)任務(wù)傳給下面,之后打開頁(yè)面進(jìn)入到加載狀態(tài)。頁(yè)面加載后需要判斷當(dāng)前頁(yè)面是否完全,比如有時(shí)候某些網(wǎng)頁(yè)服務(wù)器網(wǎng)絡(luò)性差,或是遇到GS報(bào)錯(cuò)、網(wǎng)站超時(shí)某些資源顯示不全,這時(shí)候可以通過下圖標(biāo)注的三個(gè)狀態(tài)來(lái)確定整個(gè)網(wǎng)頁(yè)的結(jié)構(gòu)是否加載完成,整個(gè)頁(yè)面是否打開完成。
完成后把整個(gè)瀏覽器page頁(yè)面鎖定不做任何動(dòng)作,讓它打開另外一個(gè)新網(wǎng)頁(yè),或者跳轉(zhuǎn)其他網(wǎng)頁(yè)上去。
當(dāng)整個(gè)網(wǎng)頁(yè)加載好之后,把整個(gè)網(wǎng)頁(yè)跳轉(zhuǎn)鎖定后就可以進(jìn)入到函數(shù)劫持階段。隨后開始注入一個(gè)監(jiān)聽器,監(jiān)聽所有事件的變動(dòng)和事件觸發(fā)的信息。當(dāng)文件加載、函數(shù)劫持、監(jiān)聽都完成之后,可以編譯出任何輸入框綁定的事件,對(duì)某個(gè)輸入?yún)?shù)值進(jìn)行常規(guī)判斷的一些信息。
當(dāng)我們發(fā)現(xiàn)頁(yè)面存在表單的時(shí)候,可以通過分析表單的輸入類型以及表單名稱,進(jìn)行一些參數(shù)填充。上面所有流程結(jié)束后,會(huì)得到當(dāng)前頁(yè)面所有信息的結(jié)果題。此時(shí)可以通過去蟲過濾之后,返回給事件管理器,重復(fù)執(zhí)行整個(gè)流程。
確定總體流程之后回到剛才的第一步,頁(yè)面加載,錄入實(shí)現(xiàn)。
當(dāng)一個(gè)頁(yè)面加載完成之后,應(yīng)該在什么時(shí)候注入我們的劫持代碼,這里邊有狀態(tài)可以選擇。第一個(gè)在page load之后;第二個(gè)是等待頁(yè)面加載完成之后,也就是當(dāng)前網(wǎng)絡(luò)狀態(tài)全部空閑的時(shí)候,整個(gè)爬蟲執(zhí)行流再繼續(xù)執(zhí)行;或者判斷整個(gè)網(wǎng)頁(yè)的DOM樹是否被加載并解析完成。
再看請(qǐng)求連接部分,下圖三個(gè)問題是Web2.0爬蟲界和Web1.0都受到關(guān)注的問題。當(dāng)你爬取一個(gè)網(wǎng)頁(yè)之后,某些代碼就把你的頁(yè)面跳走了,甚至可能規(guī)則還沒有加載完成頁(yè)面就被人轉(zhuǎn)走了。
大家針對(duì)這個(gè)問題給出的解法不同,有的人建議自己把原碼重新編譯。其實(shí)除此之外還有一個(gè)解法,就是插件機(jī)制,能夠?qū)崿F(xiàn)在另外一層對(duì)瀏覽器的控制。如下圖,為每個(gè)瀏覽器插件提供一個(gè)對(duì)象,當(dāng)整個(gè)瀏覽器發(fā)起請(qǐng)求之前,可以在事件觸發(fā)一瞬間,網(wǎng)頁(yè)開啟前在這里添加一個(gè)函數(shù)進(jìn)去。
比如當(dāng)上面的123要發(fā)生時(shí),可以通過增加一個(gè)監(jiān)聽事件,把當(dāng)前所有頁(yè)面Web請(qǐng)求從逆向到鏈接上實(shí)現(xiàn)網(wǎng)頁(yè)鎖定,當(dāng)爬取一個(gè)頁(yè)面的時(shí)候就再也沒有任何函數(shù)把頁(yè)面跳轉(zhuǎn)走,這樣可以確定整個(gè)頁(yè)面的完整性。我猜測(cè)那些屏蔽視頻廣告的插件,也是利用了這個(gè)函數(shù)實(shí)現(xiàn)的這一功能。
另一個(gè)困擾我們的問題是各種不斷彈出的彈窗,甚至?xí)龅揭恍O端的開發(fā),在網(wǎng)頁(yè)中加一些參數(shù)和地址刷新的函數(shù)。如果要確保我們創(chuàng)造的爬蟲能夠流暢的爬取整個(gè)頁(yè)面不被瀏覽器奇奇怪怪坑住,需要直接將已知的能夠制造網(wǎng)頁(yè)阻塞的函數(shù)進(jìn)行劫持。
頁(yè)面加載的時(shí)候,可以監(jiān)聽所有彈窗的事件,只要彈出一個(gè)窗,之后結(jié)束把這些都改掉。關(guān)于超時(shí)函數(shù),我們制定一個(gè)原生函數(shù),在調(diào)用這一函數(shù)時(shí)候把時(shí)間永久設(shè)置成是0,后面執(zhí)行也是通過此方法,調(diào)用對(duì)時(shí)間控制的任何函數(shù),都把生命周期設(shè)成0,這樣就不會(huì)因?yàn)殚_發(fā)的一些代碼導(dǎo)致整個(gè)網(wǎng)頁(yè)被框住。
還有一個(gè)爬蟲界非常關(guān)心的是如何獲取AJAX請(qǐng)求信息。
有兩種方法,一個(gè)使用攔截的功能,類似于被動(dòng)掃描器的代理,瀏覽器提供這個(gè)API所有的資源,只要網(wǎng)絡(luò)請(qǐng)求信息都可以通過這一方法攔截記錄下來(lái)。
第二種簡(jiǎn)單粗暴的方法是直接可以用自己的函數(shù)把原生函數(shù)劫持起來(lái),把請(qǐng)求信息記錄下來(lái),這里只需要劫持這些方法可以掃描器爬蟲所需要的所有功能。
當(dāng)函數(shù)劫持過程完成后,開始分析整個(gè)網(wǎng)頁(yè)下面所有節(jié)點(diǎn)信息以及表單信息,具體的實(shí)踐方式有兩種。比如可以通過使用循環(huán)DOM所有節(jié)點(diǎn)信息。另外我們可以使用DOM提供的強(qiáng)大工具,通過自定義規(guī)則過濾文檔中節(jié)點(diǎn),來(lái)生成新的節(jié)點(diǎn)信息。我們可以提前定義好想要捕獲節(jié)點(diǎn)信息的相關(guān)規(guī)則,比如說我們把SRC只要是DOM任意節(jié)點(diǎn)上,跟所有相關(guān)的信息監(jiān)聽起來(lái),只要網(wǎng)頁(yè)上任何一個(gè)連接信息,或者一個(gè)圖片的地址發(fā)生改變,都能夠通過這個(gè)方法來(lái)捕捉到。
當(dāng)通過DOM獲取所有信息之后,并不是所有事件信息都需要觸發(fā)一遍,我們往往建議針對(duì)特定的場(chǎng)景,去匹配執(zhí)行。比如在瀏覽一些新聞網(wǎng)站時(shí)候,需要通過滾動(dòng)屏幕刷新刷出更多的新聞,背后用到的技術(shù)就是監(jiān)聽翻頁(yè)的方法實(shí)現(xiàn)。比如使用一些模態(tài)框的時(shí)候,需要在一個(gè)網(wǎng)頁(yè)中點(diǎn)一個(gè)按紐,這是已綁定好的事件,點(diǎn)一下會(huì)彈出模態(tài)框輸入信息。比如像社區(qū)型知乎和雪球網(wǎng)站,他們?yōu)榱藢?shí)現(xiàn)消息的實(shí)時(shí)配送,背后有歷史任務(wù)在運(yùn)行。
當(dāng)拿到整個(gè)節(jié)點(diǎn)信息和綁定信息之后,可以選擇觸發(fā)這些事件信息。觸發(fā)事件信息有兩種,如下圖代碼,上面有一個(gè)事件,事件的名稱是click,可以直接通過代碼聲明一個(gè)事件直接觸發(fā),這兩行代碼執(zhí)行時(shí)瀏覽器會(huì)彈出一個(gè)click的彈窗。另外一種簡(jiǎn)單粗暴的方法是找到事件背后的值,事件綁定背后的值就是一個(gè)代碼,可以調(diào)用EVAL直接執(zhí)行。
當(dāng)然我們可以模擬任何事件,我們?cè)O(shè)計(jì)爬蟲的目的是為了做安全測(cè)試,在安全測(cè)試過程中,發(fā)現(xiàn)攻擊面的多少?zèng)Q定整個(gè)安全測(cè)試效果。在Web場(chǎng)景中表單十分重要。比如我登錄頁(yè)面,搜索頁(yè)面在整個(gè)開發(fā)過程中,涉及數(shù)據(jù)庫(kù)的增加修改查詢都和表單有關(guān)。遍歷表單的方式也有非常多,但這里還有另一個(gè)更加方便的方法,直接使用原生的對(duì)象,通過循環(huán)把整個(gè)當(dāng)前表單登錄框里邊有哪些內(nèi)容進(jìn)行查找。
建立完表單之后,參數(shù)類型自動(dòng)獲取到表單里邊輸入框的字符長(zhǎng)度,為每個(gè)參數(shù)生成合適的值,同時(shí)可以調(diào)用節(jié)點(diǎn)的方法,給表單設(shè)計(jì)一個(gè)值,或者可以通過這個(gè)方法幫助按紐點(diǎn)上選項(xiàng)。當(dāng)我們有表單的時(shí)候,就可以實(shí)現(xiàn)自動(dòng)填充。比如爬蟲發(fā)現(xiàn)一個(gè)頁(yè)面是一個(gè)登錄接口可以通過判斷它的輸入框的名稱,是不是包含這些內(nèi)容,如果是的話就通過下面定義好的規(guī)則,直接從這里邊挑一個(gè)名,填充過去。當(dāng)我們發(fā)現(xiàn)一個(gè)表單里邊是跟它相關(guān)的,我們就可以通過同我們規(guī)則里邊拿到英文的名,然后在再等等一個(gè)@,然后再把下來(lái)DOM的列表隨機(jī)挑一下得到一個(gè)郵箱就自動(dòng)填充。
整個(gè)流程介紹完后來(lái)看一個(gè)爬蟲DEMO,主要爬取一個(gè)網(wǎng)頁(yè),把網(wǎng)頁(yè)中所有的信息圖片、動(dòng)態(tài)攝入和元素都爬出來(lái)。
demo下載地址:https://github.com/ring04h/papers/blob/master/xianzhi_crawler_demo.mov
最后是總結(jié)的四個(gè)觀點(diǎn)。
當(dāng)我們發(fā)現(xiàn)URL中孤立出現(xiàn)的數(shù)字,90%的情況是動(dòng)態(tài)參數(shù)。
在爬取到一個(gè)頁(yè)面結(jié)果時(shí),發(fā)現(xiàn)非常多鏈接在pass,里邊存在長(zhǎng)度相似的一致性,且生成方式是通過其他方式生成的。我們可以判斷一下存在多少長(zhǎng)度一致的鏈接,如果這個(gè)數(shù)大于5或者10,應(yīng)該小心這里邊是一個(gè)動(dòng)態(tài)的參數(shù)。
我們解決偽靜態(tài)問題上,偽靜態(tài)百分之七八十情況下通過橫杠和反橫杠分析這個(gè)。比如第一個(gè)連接就是反斜杠偽靜態(tài),下面就是橫杠的偽靜態(tài)。我們將整個(gè)部分進(jìn)行分割,分割出來(lái)的值是什么類型,如果是整形就命中了第一個(gè)只要孤立數(shù)字出現(xiàn)在某個(gè)路徑下都可能是動(dòng)態(tài)參數(shù)。
另外我們通過HASH化去做去蟲,比如有同樣的鏈接他們?cè)?23456789,我們只需要把這個(gè)連接每個(gè)參數(shù)切割成括號(hào)進(jìn)行切割,最后看他們的出現(xiàn)的頻次,如果出現(xiàn)的次數(shù)非常多,代表著這個(gè)參數(shù)是一個(gè)常量,它是固定挾持的。如果背后的參數(shù)出現(xiàn)的次數(shù)非常散漫,只有1和2,那個(gè)路徑后面的參數(shù)有可能是動(dòng)態(tài)的參數(shù)。
以上內(nèi)容來(lái)自阿里先知大會(huì),雷鋒網(wǎng)編輯整理。
雷峰網(wǎng)原創(chuàng)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。