這是一篇嚴(yán)肅的技術(shù)分享文章,旨在向大家介紹一些網(wǎng)絡(luò)安全方面的知識,及相關(guān)工具的使用。閑話少說,直接進(jìn)入正題。
實(shí)現(xiàn)目標(biāo)
知乎上經(jīng)常有各種爆照及釣魚貼,類似「胸大是一種什么樣的體驗(yàn)?」, 「女生有翹臀是什么樣的體驗(yàn)?」等。其實(shí)大家關(guān)心的只有照片,是不是?
我們的目標(biāo)是在終端輸入:
./get.sh胸大
就能從知乎將胸大(或者其他關(guān)鍵詞)相關(guān)的話題回答中的圖片,一鍵下載到本地的文件夾中。我試著跑了下腳本,有好多讓人看了就臉紅??的照片:

真的是來自知乎。。
著急的同學(xué)可以直接在我的公眾號(MrPeakTech)回復(fù)z,獲取可運(yùn)行的腳本。
準(zhǔn)備工作
技術(shù)手段:中間人攻擊,replay attack。
工具:Mac,裝有知乎App的iPhone手機(jī),mitmproxy,mitmdump,grep,wget。
知識儲備:http協(xié)議,python腳本,基礎(chǔ)的安全知識。
實(shí)現(xiàn)思路
第一步:使用mitmdump記錄知乎App的搜索request,和進(jìn)入回答的request。
第二步:replay搜索request,hook請求,修改request參數(shù)。
第三步:獲取搜索結(jié)果后,replay回答的request,hook請求,修改request參數(shù)。
第四步:使用正則提取回答response中的圖片url。
第五步:使用wget將圖片下載到指定文件夾。
動手
這次我們的主角是mitmproxy和mitmdump。之前我寫過一篇文章介紹如何使用mitmproxy做https抓包。這次要使用到更高階一點(diǎn)的功能:replay attack。建議先看下我之前那篇文章。
安裝mitmproxy
沒有安裝mitmproxy的同學(xué)可以先通過brew安裝下:
brewinstallmitmproxy
安裝好之后,在終端啟動mitmproxy:
mitmproxy
接下來需要在iPhone上設(shè)置http代理:

IP地址填你Mac系統(tǒng)當(dāng)前的IP,端口默認(rèn)8080,記住iPhone要和我們的Mac處于同一個(gè)局域網(wǎng)中。
如果是第一次使用mitmproxy,需要在iPhone上安裝CA證書,打開iPhone Safari,輸入地址:mitm.it,在下圖中點(diǎn)擊Apple安裝證書。

這樣就配置完畢了,下面我們來記錄知乎App的request。
記錄App Request
首先我們先打開知乎App,進(jìn)入搜索界面:

接著啟動mitmdump,來記錄手機(jī)端的https請求,在終端輸入:
mitmdump-wraw
回車之后,手機(jī)端的請求就都會寫進(jìn)raw文件了。
下面在App端輸入關(guān)鍵字「胸大」,點(diǎn)擊搜索,翻頁(想要結(jié)果多點(diǎn),可以多翻幾頁)。
這樣我們在終端可以看到如下三個(gè)被捕捉請求。

有時(shí)候我們會捕捉到多余的請求,需要手動刪除下,可以先退出mitmdump,然后再終端輸入:
mitmproxy-rraw
進(jìn)入請求的編輯界面,按d可以刪除我們不想要的請求,編輯完之后,按w會提示保持到文件,我將請求保持到searchReq文件:

在重復(fù)上面的操作,在App端點(diǎn)擊進(jìn)入回答的操作,將單個(gè)回答的request保存到文件detailReq。
到這里我們就記錄完畢原始請求了!
Replay Attack
經(jīng)過之前的操作,我們有了兩個(gè)原始請求文件:searchReq,detailReq。
接下來回放search請求,回放的時(shí)候我們還需要hook一個(gè)python腳本來修改請求參數(shù)。先看下search請求的格式,通過mitmproxy可以查看詳情:
GEThttps://api.zhihu.com/search?excerpt_len=75&q=%E8%83%B8%E5%A4%A7&t=content
這是個(gè)非常簡單的GET請求,參數(shù)格式也一目了然。而且幸運(yùn)的是知乎的后臺即沒有做參數(shù)的簽名,也沒有加時(shí)間戳來防replay attack??瓷先ノ覀冎恍枰鎿Qq=xxx這個(gè)參數(shù)值即可。所以寫段簡單的python腳本來替換吧:
classReplacer:def__init__(self,dst):self.dst=dstdefrequest(self,flow):flow.request.path=flow.request.path.replace("%25E8%2583%25B8%25E5%25A4%25A7",urllib.quote_plus(urllib.quote_plus(self.dst)))flow.request.path=flow.request.path.replace("%E8%83%B8%E5%A4%A7",urllib.quote_plus(self.dst))defstart():parser=argparse.ArgumentParser()parser.add_argument("dst",type=str)args=parser.parse_args()returnReplacer(args.dst)
腳本很簡單,就是將我們輸入的關(guān)鍵字urlencode下,再替換原先的參數(shù)。
我的系統(tǒng)是python 2.xx,3.xx的encode方法調(diào)用有些差別,要注意。
這里有點(diǎn)奇怪的是知乎搜索翻頁的接口,將關(guān)鍵字連續(xù)urlencode了兩次,不知道有神馬講究在里面。不過不管啦,我們繼續(xù)。
寫好腳本(replace_query.py)之后,再寫個(gè)bash腳本來實(shí)施replay attack。這個(gè)腳本也是我們的關(guān)鍵執(zhí)行腳本get.sh:
#!/bin/bash
#replay attackmitmdump-dd-s"./replace_query.py $1"-zncsearchReq-wsearchRsp
參數(shù)我就不一一解釋啦,大家自己看mitmproxy的官方文檔,總之這段腳本會回放存在searchReq當(dāng)中的搜索請求,并執(zhí)行replace_query.py當(dāng)中的替換方法,最后將請求的結(jié)果存放在searchRsp文件當(dāng)中。
大家可以先執(zhí)行這段腳本,看看searchRsp有沒有我們想要的請求結(jié)果。
chmod+xget.sh./get.sh胸大
如果一切正常,我們會看到一段格式規(guī)范,結(jié)構(gòu)清晰的json串。類似:
{"data":[{"content":{"excerpt":"也要表現(xiàn)出來(基本上胸大的人.在大胸的對比下腰都是細(xì)的,腰圍和胸圍一樣大的大胸……那種應(yīng)該不是大胸吧.只是大胸圍而已)很多大胸妹子的誤區(qū)都是喜歡穿寬松的上衣.配合含胸.以為自己","url":"https://api.zhihu.com/answers/61382005"},
肉眼掃描下就可以發(fā)現(xiàn)我們的目標(biāo)是https://api.zhihu.com/answers/61382005。這種url是我們進(jìn)入回答頁面的url,61382005應(yīng)該就是我們的detail ID號。
接下來我們需要使用grep,寫個(gè)簡單的正則提取出這些ID號。走你:
#extract answer urlcatsearchRsp|grep-aoE'https[^"]*(answers)[^"]*'|sed's/\\//g' | grep -oE '[0-9]+'? > answers
很簡單的正則,上面的腳本就將我們的ID號統(tǒng)統(tǒng)提取出來,并寫進(jìn)answers文件。執(zhí)行下打開answers文件,看看ID有木有。
Replay Answer Request
接下來我們按同樣的步驟回放下進(jìn)入回答的請求。
先看下請求的格式:
GET https://api.zhihu.com/answers/61382005
也是個(gè)光禿禿的url,替換ID號就OK拉。上腳本(replace_url.py):
importmitmproxyimportargparseclassReplacer:def__init__(self,dst):self.dst=dstdefrequest(self,flow):flow.request.path=flow.request.path.replace("61382005",self.dst)defstart():parser=argparse.ArgumentParser()parser.add_argument("dst",type=str)args=parser.parse_args()returnReplacer(args.dst)
很簡單的GET請求,替換ID號即可。
接著實(shí)施replay attack:
#replay attackwhileIFS=read-rp;do#echo "$p"mitmdump-dd-s"./replace_url.py $p"-zncdetailReq-wdetailRsp|grep-aoE'http[^"]*.jpg' | xargs wget -P ./magicdone < answers
這段bash腳本將之前保存在answers文件中的ID號,一行行讀取出來,再通過mitmdump進(jìn)行replay,并通過replace_url.py替換ID號,最后將結(jié)果經(jīng)過grep過濾,xargs傳遞給wget來下載,最后文件都會下載到magic目錄下。
沒有下載wget的同學(xué),可以先通過brew安裝下:
brewinstallwget
到這里所有的工作就完成啦,所以我們有了最后的get.sh:
#!/bin/bash
#replay attackmitmdump-dd-s"./replace_query.py $1"-zncsearchReq-wsearchRsp#extract answer urlcatsearchRsp|grep-aoE'https[^"]*(answers)[^"]*'|sed's/\\//g' | grep -oE '[0-9]+'? > answers#replay attackwhileIFS=read-rp;do#echo "$p"mitmdump-dd-s"./replace_url.py $p"-zncdetailReq-wdetailRsp|grep-aoE'http[^"]*.jpg' | xargs wget -P ./magicdone < answers
趕緊運(yùn)行腳本,發(fā)揮想象力,感受下知乎愛的供養(yǎng)吧。
安全知識總結(jié):
這里只是給大家提供個(gè)思路,我相信還有很多App都有類似的問題,在安全方面投入太少。
這個(gè)小工具之所以能成功,是由于:
知乎App的客戶端沒有做ssl pinning,所以可以通過中間人攻擊分析請求。
知乎Server端也沒有針對replay attack做任何防范。
大家做App還是要多注意下安全方面的東西,即使上了https,也要做多做一層加密保護(hù)。安全方面的工作,做得再多也為過。
我這個(gè)腳本對應(yīng)的賬號有可能會被停了,如果失效,可以照著上面的步驟自己做一個(gè):)
最后,溫馨提示:在公眾號恢復(fù)消息z,可以下載腳本。使用方式:
chmod+xget.sh./get.sh好好學(xué)習(xí)
歡迎關(guān)注公眾號:MrPeakTech