[本文出自天外歸雲的博客園]
介紹
Mitmproxy是一款支持HTTP(S)的中間人代理工具。不同於Fiddler2,burpsuite等類似功能工具,mitmproxy可在終端下運行,並且支持編寫腳本來批量處理請求。Mitmproxy使用Python開發,是輔助web開發&測試,移動端調試,滲透測試的工具。你不要在Windows上安裝它,因為用不了,Windows的命令行不支持mitmproxy的界面顯示。
安裝與啟用
1. 在終端安裝(安裝后會提示安裝路徑用來啟動mitmproxy),以下命令適合python2(注意brew和pip安裝的mitmproxy版本要一致):
brew install mitmproxy sudo pip install "mitmproxy==0.17.1"
2. 在終端啟動(指定本機ip和運行端口號):
/usr/local/Cellar/mitmproxy/0.17.1/bin/mitmproxy -b 10.235.3.70 -p 8888
抓https的包需要在移動端安裝證書,在啟動mitmproxy之后在手機瀏覽器輸入並訪問“mitm.it”進行安裝證書,然后就可以抓手機端發送的https包了。
在主界面用鼠標點擊具體的請求可以進入請求界面。
常用命令
1. 清屏:“shift+c”
2. 切換“Request/Response”欄:“tab”
3. 返回上一級(包括退出):“q”
4. 在具體請求的“Response”欄界面以不同格式查看返回結果:“m+高亮的字母”進行選擇要編輯的部分
5. 在主界面刪除指定請求:用小黃箭頭指定要刪除的請求然后按“d”
6. 攔截請求:在主界面按“i+要攔截的字符串,例如:api.win”進行攔截包含指定字符串的請求
7. 在請求界面編輯請求或響應:e+“高亮的字母”進行選擇要編輯的部分
8. 在主界面發送指定的請求:用小黃箭頭指定要發送的請求然后按兩下“a”
腳本編寫
腳本編寫如下,將返回結果批量改成“666”:
#coding=utf-8 def request(context,flow): #print "This is a request." pass def response(context,flow): #print dir(flow.response) if "100" in flow.response.content: try: flow.response.content = "666" except Exception as e: pass
運行腳本方式(在終端里腳本所在路徑下運行如下命令,這里的腳本叫“test_mit.py”):
mitmproxy -s test_mit.py -p 8888
運行以后在終端里可以看到mitmproxy的主界面,按“e”可以查看腳本的輸出信息以及腳本報錯的信息。
例如我隨便訪問一款手機上的app,這里拿“一元樂購”為例。在mitmproxy的主界面可以看到抓包信息,隨便點進去一個,查看它的“Response”欄,可以看到返回結果變成了“666”。而對應的在手機上我也無法打開這款app了,殺掉進程后重新進入app就會發生閃退。這種修改接口返回值然后查看客戶端是否能夠正確處理的測試就是app專項測試中的接口容錯測試。
我們可以用mitmproxy的filter請求攔截器或者通過編寫腳本的方式來進行接口的容錯測試。
實戰
以“一元樂購”這個app為例,測試不同用戶到新的商品詳情頁后檢查各自可用的紅包列表,我們需要模擬不同的用戶來訪問這個頁面,如果來回退出登錄app訪問這個頁面的話過程是非常繁瑣的。通過mitmproxy可以完美的進行請求數據篡改,在不切換登錄用戶的前提下模擬不同用戶訪問商品詳情頁面。腳本代碼如下:
#coding=utf-8 import json import requests accountId = "" pwd = "" def getSessionId(session,accountId,pwd): url = "https://hygtest.ms.netease.com/winyyg/scripts" data = { "username":accountId, "password":pwd, "tag":"winyylg_login" } r = json.loads(session.post(url,data).text) return r[0][1] def request(context,flow): if "new_product_detail" in flow.request.url: form_urlencoded = flow.request.get_form_urlencoded() form_urlencoded["accountId"] = [accountId] s = requests.Session() sessionId = getSessionId(s,accountId,pwd) form_urlencoded["sessionId"] = [sessionId] flow.request.set_form_urlencoded(form_urlencoded)
編寫腳本的過程中,對於不知道是什么類型的變量:
print type(xxx)
對於不知道包含什么方法和成員的變量:
print dir(xxx)
對於不知道怎么用的方法,google之。
以上代碼中accountId和pwd變量為待模擬用戶的用戶名和密碼,我們在通過這個腳本啟動了mitmproxy之后,在無需重啟mitmproxy的情況下修改腳本中的內容就可以實現對請求數據的篡改,從而達到我們模擬不同用戶登錄訪問商品詳情頁的目的!保存好修改的腳本之后要做的就是手動刷新app內的商品詳情頁面了,從可用紅包列表處可以看到訪問商品詳情頁的用戶已經成功變為了腳本中指定的用戶。2017.3.13的晚上,又錯過了晚飯。我和大師兄朱勃在網易大廈的六樓一起研究,終於搞定了通過編寫mitmproxy腳本的方式來模擬不同用戶訪問app內頁面。
