尋找阿登高地——爬蟲(chóng)工程師如何繞過(guò)驗(yàn)證碼
馬奇諾防線是二戰(zhàn)前法國(guó)耗時(shí)十余年修建的防御工事,十分堅(jiān)固,但是由于造價(jià)昂貴,僅修建了法德邊境部分,綿延數(shù)百公里,而法比邊界的阿登高地地形崎嶇,不易運(yùn)動(dòng)作戰(zhàn),且比利時(shí)反對(duì)在該邊界修建防線,固法軍再次并沒(méi)過(guò)多防備,滿心期望能夠依靠堅(jiān)固的馬奇諾防線來(lái)阻擋德軍的攻勢(shì)。沒(méi)想到后來(lái)德軍避開(kāi)德法邊境正面,通過(guò)阿登高地從防線左翼迂回,繞過(guò)了馬奇諾防線,然后就是英法聯(lián)軍的敦克爾克大撤退了。
網(wǎng)站驗(yàn)證碼就如同馬奇諾防線一樣,阻擋了爬蟲(chóng)工程師的正面進(jìn)攻。
隨著爬蟲(chóng)和反爬蟲(chóng)雙方圍繞驗(yàn)證碼的不斷較量,最終導(dǎo)致了驗(yàn)證碼識(shí)別難度的不斷上升。現(xiàn)在復(fù)雜的驗(yàn)證碼長(zhǎng)這樣:
面硬剛驗(yàn)證碼,想要識(shí)別它,是件挺復(fù)雜的事,涉及到圖像處理技術(shù):二值化,降噪,切割,字符識(shí)別算法:KNN(K鄰近算法)和SVM (支持向量機(jī)算法),再?gòu)?fù)雜點(diǎn)還要借助CNN(卷積神經(jīng)網(wǎng)絡(luò)),還有什么機(jī)器學(xué)習(xí)啥的。
雖然現(xiàn)在有打碼平臺(tái)可以解決絕大多數(shù)的驗(yàn)證碼問(wèn)題,但如果爬取的數(shù)量特別龐大,單純依賴(lài)打碼平臺(tái)也是不大行得通的,除了成本因素,還有打碼平臺(tái)也解決不了的驗(yàn)證碼因素,比如滑動(dòng)驗(yàn)證碼:
既然正面進(jìn)攻費(fèi)事費(fèi)力,那能不能找到爬蟲(chóng)工程師眼中的阿登高地繞過(guò)驗(yàn)證碼呢?
本文以各地工商網(wǎng)站為例,對(duì)常見(jiàn)的驗(yàn)證碼繞過(guò)技巧做一個(gè)小總結(jié),順便解密下如何不借助模擬js拖動(dòng)來(lái)繞過(guò)滑動(dòng)驗(yàn)證碼。
各地工商網(wǎng)站(全稱(chēng)國(guó)家企業(yè)信用信息公示系統(tǒng))因?yàn)榘罅科髽I(yè)真實(shí)信息,金融貸款征信等都用得到,天然吸引了很大部分來(lái)自爬蟲(chóng)的火力,因此反爬蟲(chóng)措施格外嚴(yán)格。一般的網(wǎng)站僅在登錄注冊(cè)等環(huán)節(jié),或者訪問(wèn)頻繁后才彈出驗(yàn)證碼,而工商網(wǎng)站查詢(xún)無(wú)需登錄,每查一次關(guān)鍵字就需要一次驗(yàn)證碼。同時(shí)各地工商網(wǎng)站由于各自獨(dú)立開(kāi)發(fā),自主采用了各種不同的驗(yàn)證碼機(jī)制,更是給全量爬取的爬蟲(chóng)增加了更多的障礙。因此,工商網(wǎng)站的驗(yàn)證碼特別具有代表性。
首先,從最簡(jiǎn)單的分頁(yè)角度入手。
分頁(yè)的處理可以放在前端也可以放在后端,如果只放在后端,每次點(diǎn)擊頁(yè)碼就需要發(fā)送一次查詢(xún)請(qǐng)求,而一次驗(yàn)證碼通常只能服務(wù)于一次請(qǐng)求,再次請(qǐng)求需要獲取新的驗(yàn)證碼,直接觀察翻頁(yè)操作是否彈出驗(yàn)證碼輸入框即可判斷是否可以繞過(guò)。
如何判斷分頁(yè)處理放在前端還是后端的呢?很簡(jiǎn)單,F(xiàn)12打開(kāi)瀏覽器開(kāi)發(fā)者工具,頁(yè)面點(diǎn)下一頁(yè),有新的請(qǐng)求就說(shuō)明放在后端,反之就是前端。
實(shí)踐發(fā)現(xiàn),四川和上海的工商網(wǎng)站翻頁(yè)都放在后端,且翻頁(yè)沒(méi)有驗(yàn)證碼輸入框。說(shuō)明這里的驗(yàn)證碼可以繞過(guò),但是繞過(guò)的原理卻有些不同:
對(duì)比四川工商網(wǎng)站翻頁(yè)前后請(qǐng)求的參數(shù),除了頁(yè)碼參數(shù)外,多了一項(xiàng):yzmYesOrNo=no。從變量名也猜得到,后端根據(jù)該參數(shù)的值判斷是否需要檢查驗(yàn)證碼。
而上海工商網(wǎng)站的對(duì)比結(jié)果發(fā)現(xiàn),除了頁(yè)碼參數(shù)外,少了驗(yàn)證碼字段,因此我們可以大膽猜測(cè):驗(yàn)證碼的校驗(yàn)僅放在了前端,后端沒(méi)有做二次校驗(yàn),從頁(yè)面上操作是繞不過(guò)的,但是不帶驗(yàn)證碼字段直接向后端發(fā)送請(qǐng)求,數(shù)據(jù)就拿到了。
嚴(yán)格來(lái)說(shuō),上海工商網(wǎng)站這種算是漏洞,對(duì)待這種這種漏洞,爬蟲(chóng)工程師應(yīng)有的態(tài)度是:悄悄的進(jìn)村,打槍的不要。不過(guò)也不要利用的太狠了,筆者實(shí)驗(yàn)時(shí)沒(méi)加限制,爬了十萬(wàn)數(shù)據(jù)后,ip被封了。很長(zhǎng)時(shí)間后才解封,同時(shí)頁(yè)面改版并修復(fù)了漏洞。
其次,觀察目標(biāo)網(wǎng)站是否有多套驗(yàn)證碼。
有些網(wǎng)站不知道出于什么樣的考慮,會(huì)在不同的頁(yè)面使用不同的驗(yàn)證碼。一旦遇到這種情況,我們可就要撿軟柿子捏了–從簡(jiǎn)單的驗(yàn)證碼入手,移花接木,將識(shí)別的結(jié)果作為參數(shù)來(lái)向后端發(fā)送請(qǐng)求,從而達(dá)到繞過(guò)復(fù)雜驗(yàn)證碼的目的。
舉例來(lái)說(shuō),湖北工商的查詢(xún)頁(yè)面驗(yàn)證碼是類(lèi)似下圖的九宮格驗(yàn)證碼:
而電子營(yíng)業(yè)執(zhí)照登陸界面的驗(yàn)證碼是這樣的:
即便要識(shí)別,也明顯是后者的驗(yàn)證碼要容易些,實(shí)例代碼如下:
再者,可以考慮從數(shù)據(jù)的存儲(chǔ)id入手
專(zhuān)門(mén)針對(duì)移動(dòng)端開(kāi)發(fā)的wap頁(yè)面限制一般要少得多。以北京工商網(wǎng)站來(lái)說(shuō),wap界面不帶驗(yàn)證碼參數(shù)直接發(fā)送請(qǐng)求就可以得到數(shù)據(jù)的,原理類(lèi)似于上海工商網(wǎng)站,但是其對(duì)單個(gè)ip日訪問(wèn)次數(shù)做了嚴(yán)格限制,因此該方式可以用但不好用。
繼續(xù)觀察,以搜索“山水集團(tuán)”為例,從搜索頁(yè)到列表頁(yè)時(shí),需要輸入驗(yàn)證碼,而從列表頁(yè)進(jìn)入詳情頁(yè)的時(shí)候,是不需要驗(yàn)證碼的。最終詳情頁(yè)如圖:
通常沒(méi)人記得住各地工商網(wǎng)站的網(wǎng)址,我們會(huì)去搜索引擎里搜。當(dāng)搜北京企業(yè)信用信息時(shí),發(fā)現(xiàn)兩個(gè)有價(jià)值的結(jié)果,除了國(guó)家企業(yè)信用信息公示系統(tǒng)外,還有個(gè)北京市企業(yè)信用信息信息網(wǎng)。進(jìn)后者再操作一番可以得到下面的詳情頁(yè):
觀察發(fā)現(xiàn),企業(yè)id都是相同的,嘿嘿,這不是“兩塊牌子,一套班子”嘛!后者的訪問(wèn)量要小一些,雖有驗(yàn)證碼,但是可以采用上海工商一樣的方式繞過(guò),只是返回的結(jié)果字段不太符合我們的要求。不過(guò),我們可以去企業(yè)信息網(wǎng)獲得企業(yè)id,再次采用移花接木的方式,去信息公示系統(tǒng)構(gòu)造鏈接獲得最終的詳情頁(yè)嘛!
用過(guò)數(shù)據(jù)庫(kù)同學(xué)都曉得,數(shù)據(jù)庫(kù)里的數(shù)據(jù)id,默認(rèn)是自增的。如果有個(gè)網(wǎng)站引用的數(shù)據(jù)是xxx.com?id=1234567, 那我們很容易猜得到構(gòu)造類(lèi)似1234568這樣的id去嘗試!通常,使用這種id規(guī)律能夠輕易猜出來(lái)的網(wǎng)站并不多,但不代表沒(méi)有。比如甘肅省工商網(wǎng)站,結(jié)果頁(yè)是拿企業(yè)注冊(cè)號(hào)來(lái)查詢(xún)的。
***,談?wù)劵瑒?dòng)驗(yàn)證碼。
目前,工商網(wǎng)站已經(jīng)全面改版,全部采用了滑動(dòng)驗(yàn)證碼,上面絕大多數(shù)思路都失效了。對(duì)于滑動(dòng)驗(yàn)證碼,網(wǎng)上能搜到的解決方案基本都是下載圖片,還原圖片,算出滑動(dòng)距離,然后模擬js來(lái)進(jìn)行拖動(dòng)解決,我們來(lái)看下能否不模擬拖動(dòng)來(lái)解決這個(gè)問(wèn)題。
以云南工商網(wǎng)站為例,首先抓包看過(guò)程。
1. http://yn.gsxt.gov.cn/notice/pc-geetest/register?t=147991678609,response:
2. 下載驗(yàn)證碼圖片
3. http://yn.gsxt.gov.cn/notice/pc-geetest/validate, post如下數(shù)據(jù):
4. http://yn.gsxt.gov.cn/notice/search/ent_info_list,post如下數(shù)據(jù):
仔細(xì)分析,我們發(fā)現(xiàn)兩處疑點(diǎn):
1. ***步并沒(méi)有返回需要下載的圖片地址,那么前端怎么知道要下載哪些圖片?
2. 第三步驗(yàn)證時(shí),并沒(méi)有告知后端下載了那些圖片,后端是怎么驗(yàn)證post過(guò)去的數(shù)據(jù)是有效性的?
仔細(xì)閱讀前端混淆的js代碼,我們發(fā)現(xiàn)前端數(shù)據(jù)處理過(guò)程是這樣的:
1. 從0到6(不含)中取隨機(jī)整數(shù),賦值給d, d=5;
2. 從0到300(不含)中取隨機(jī)整數(shù),賦值給e, e=293;
3. 將d轉(zhuǎn)化為字符串并作MD5加密,加密字符串取前9位賦值給f, f=’e4da3b7fb’;
4. 將e轉(zhuǎn)化為字符串并作MD5加密,加密字符串從第11位開(kāi)始取9位賦值給g, g=’43be4f209’;
5. 取f的偶數(shù)位和g的奇數(shù)位組成新的9位字符串給h, h=’e3de3f70b’;
6. 取h的后4位與200做MOD運(yùn)算,其結(jié)果小于40,則取40,否則取其本身賦值給x,x=51;
7. 取[x-3, x+3]以?xún)?nèi)隨機(jī)數(shù)賦值給c,c=51;
8. 分別取c,d,e跟challenge做t加密(t(c,challenge), t(d, challenge), t(e,challenge))并用(_)拼接即為geetest_validate, ‘9ccccc997288_999c9ccaa83_999cc9c9999990d’
這里f, g參數(shù)決定了下載圖片地址:
而x為滑塊拖動(dòng)的橫向偏移量,至此解答了疑問(wèn)1中圖片下載地址怎么來(lái)的問(wèn)題。
前邊提到的t加密過(guò)程是這樣的:
t(a,b),此處以a=51演示
1. challenge為34位16進(jìn)制字符串,取前32位賦值給prefix,后2位賦值給suffix,prefix=’34173cb38f07f89ddbebc2ac9128303f’, suffix=’a8′
2. prefix去重并保持原順序,得到列表 [‘3’, ‘4’, ‘1’, ‘7’, ‘c’, ‘b’, ‘8’, ‘f’, ‘0’, ‘9’, ‘d’, ‘e’, ‘2’, ‘a’]
3. 將2中列表循環(huán)順序放入包含5個(gè)子列表的列表中,得到random_key_list: [[‘3’, ‘b’, ‘d’], [‘4’, ‘8’, ‘e’], [‘1’, ‘f’, ‘2’], [‘7’, ‘0’, ‘a’], [‘c’, ‘9’]]
4. 將suffix字符串(16進(jìn)制)逐位轉(zhuǎn)化為10進(jìn)制,得到[10, 8]
6. 將4中列表逐位與[36,0]做乘法和運(yùn)算并與a的四舍五入結(jié)果相加, n= 51 + 36*10 + 0*8=419
7. q=[1,2,5,10,50], 用q對(duì)n做分解(n=50*13+10*0+5*1+2*1+1*1),將其因數(shù)倒序賦值給p,p=[0,2,1,1,8]
8. 從random_key_list右側(cè)開(kāi)始隨機(jī)取值,次數(shù)為p中數(shù)值,拼成字符串sub_key,sub_key=’9ccccc997288′
至此,我們完成了整個(gè)分析過(guò)程,我們又有了新發(fā)現(xiàn):
1. 按照前邊的抓***程,其實(shí)不需要真的下載圖片,只需執(zhí)行1、3、4步就可以得到目標(biāo)數(shù)據(jù)了。步驟1也可以不要,只需3、4即可,但是少了步驟1, 我們還需要額外請(qǐng)求一次cookie,所以還是保留1, 這樣也偽裝的像一點(diǎn)嘛。
2. 相同的challenge,每次運(yùn)算都可以得出不同的validate和seccode,那么問(wèn)題來(lái)了:到底服務(wù)端是怎么根據(jù)challenge驗(yàn)證其他數(shù)據(jù)是否有效呢?
總結(jié)一下,對(duì)于驗(yàn)證碼,本文只是提供了一種新的思路,利用了網(wǎng)站開(kāi)發(fā)過(guò)程中的一點(diǎn)小疏漏,而***的滑動(dòng)驗(yàn)證碼也只是分析了offline模式的驗(yàn)證方法。不要指望所有驗(yàn)證碼都可以能繞過(guò),沒(méi)有阿登高地,二戰(zhàn)德國(guó)就不打法國(guó)了么?只要覺(jué)得有價(jià)值,即使正面面對(duì)驗(yàn)證碼,作為爬蟲(chóng)工程師建議也就一句話:不要慫,就是干!