Mitmproxy 常规功能介绍
背景
MITMProxy是一种用于中间人攻击(Man-in-the-middle attack)的代理工具。它的作用是在正常的代理功能基础上,截获、记录或篡改数据,并自定义特定的行为。与其他抓包工具(如Fiddler或Wireshark)不同的是,MITMProxy不仅可以查看和分析截获的请求,还可以通过自定义脚本进行二次开发。例如,可以截获浏览器对特定URL的请求,将返回内容置空并存储真实的返回内容到数据库,并在出现异常时发送邮件通知。与Fiddler类似的需求无法实现高度定制化,而MITMProxy可通过载入自定义Python脚本轻松实现。
需要注意的是,MITMProxy并不会真的对无辜的人发起中间人攻击。由于MITMProxy工作在HTTP层,当前HTTPS的普及使得客户端具备检测和规避中间人攻击的能力。因此,要使MITMProxy正常工作,客户端(如APP或浏览器)必须信任MITMProxy的SSL证书或忽略证书异常。这意味着APP或浏览器是由开发者自己控制的,这一点很显而易见,说明MITMProxy的使用并非用于黑产,而是用于开发或测试目的。
那么,这样的工具有什么实际意义呢?据我所知,目前广泛应用的一种情况是进行仿真爬虫。通过使用手机模拟器或无头浏览器来模拟用户行为,MITMProxy作为代理可以拦截、存储爬虫获取到的数据,或修改数据以调整爬虫的行为。
除了正向代理模式,MITMProxy还可以通过调整配置工作在透明代理、反向代理、上游代理、SOCKS代理等不同的模式下。然而,这些工作模式对于MITMProxy来说似乎并不常用,因此本文仅讨论正向代理模式。
安装
根据你的操作系统选择相应的安装方式。
在Linux中,打开终端并运行以下命令:
sudo pip3 install mitmproxy
在Windows中,以管理员身份打开命令提示符(cmd)或 PowerShell,并运行以下命令:
pip3 install mitmproxy
安装完成后,系统将拥有三个命令可用:mitmproxy、mitmdump和mitmweb。需要注意的是,mitmproxy命令在Windows系统中无法运行,但不用担心,我们可以使用mitmdump来测试安装是否成功。
在终端或命令提示符中执行以下命令验证安装是否成功:
mitmdump --version
运行
要启动 mitmproxy 用 mitmproxy、mitmdump、mitmweb 这三个命令中的任意一个即可,这三个命令功能一致,且都可以加载自定义脚本,唯一的区别是交互界面的不同。
- mitmproxy:提供命令行界面,使用命令行进行操作和监控。
- mitmweb:提供浏览器界面,通过Web界面进行操作和监控。
- mitmdump:提供简单的终端输出,适用于自动化和脚本化的使用场景。
由于 mitmproxy 命令的交互操作稍显繁杂且不支持 windows 系统,而我们主要的使用方式又是载入自定义脚本,并不需要交互,所以原则上说只需要 mitmdump 即可,但考虑到有交互界面可以更方便排查错误,所以这里以 mitmweb 命令为例。实际使用中可以根据情况选择任何一个命令。
使用mitmproxy可以通过mitmdump模块编写扩展脚本,从而提高工作效率。下面是一些可以使用mitmdump解决的问题示例:
- 模拟接口返回数据以验证客户端是否出现UI异常或兼容性问题。
- 模拟接口返回数据延迟,验证客户端对接口加载状态的处理。
- 录制接口数据信息,用于回归测试接口功能是否正常。
启动MITMProxy
-
输入以下命令启动mitmweb:
mitmweb
-
可见如下输出:
Web server listening at http://127.0.0.1:8081/ Proxy server listening at http://*:8080
MITMProxy绑定了
*:8080
作为代理端口,并在127.0.0.1:8081
提供了一个Web交互界面。
现在可以测试一下代理,让Chrome以MITMProxy为代理并忽略证书错误。为了不影响平时的正常使用,我们会通过命令行加参数的方式启动一个新的Chrome实例。如果你使用的不是Chrome而是其他浏览器,你可以搜索相应浏览器的启动参数,应该不会有太大差异。以下示例仅以Windows系统为例,因为那些使用Linux或Mac环境的开发者应该更熟悉命令行操作,应该可以自行推导出在自己环境中的操作方法。
由于Chrome会通过代理访问网页,为了方便继续在Web界面上与MITMProxy进行交互,我们委屈求全使用Edge或其他浏览器打开127.0.0.1:8081
。以下是解决方案,因为Edge有一个默认禁止访问回环地址的设置。
以下是解决Windows系统中Edge浏览器访问本地回环地址的限制的步骤:
以管理员权限打开命令提示符(cmd),在命令提示符中输入以下命令,解除Edge浏览器访问本地回环地址的限制:
CheckNetIsolation LoopbackExempt -a -n=Microsoft.MicrosoftEdge_8wekyb3d8bbwe
请注意,上述命令中的Microsoft.MicrosoftEdge_8wekyb3d8bbwe
是Edge浏览器的应用标识符,用于允许其访问本地回环地址。
接下来关闭所有 Chrome 窗口,否则命令行启动时的附加参数将失效。打开 cmd,执行:
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --proxy-server=127.0.0.1:8080 --ignore-certificate-errors
前面那一长串是 Chrome 的的安装路径,应当根据系统实际情况修改,后面两参数设置了代理地址并强制忽略掉证书错误。
mitmdump
mitmdump是mitmproxy的命令行版本,具有丰富的命令行参数,可以根据需求进行配置。可以使用以下命令查看参数选项:
mitmdump --help
录制与回放
mitmdump提供了录制和回放功能,可以通过规则将请求数据录制到二进制文件中,并使用回放功能对接口进行数据回放。
录制
使用以下命令进行录制,并将请求数据保存到文件中:
mitmdump -w filename
过滤
可以使用过滤规则对录制的数据进行过滤,只录制符合规则的数据:
mitmdump -nr filename -w filename2 "~s keyword"
上述命令将从filename中读取数据,过滤出包含关键字"keyword"的响应数据,并将过滤结果保存到filename2中。
回放
使用以下命令对录制的数据文件进行回放:
mitmdump -nC filename
参数说明
-s "script.py --bar"
:使用双引号命令执行脚本并传递参数。-n
:不启动代理,仅回放数据。-r
:读取文件内容。-w
:写入文件。~s
:过滤响应数据。~q
:过滤请求数据。
示例
下面是一些示例用法:
- 使用录制功能,本地开启8999端口代理并过滤响应数据"igetget",将结果保存到本地文件igetget.txt中:
mitmdump -p 8999 -w igetget.txt "~s igetget"
-
连接手机到代理端口8999,并操作手机应用程序。
-
录制结束后,注意igetget.txt是一个二进制文件,无法直接查看详细的接口信息。
-
使用回放功能,回放igetcool.txt文件中的接口数据:
mitmdump -nC igetcool.txt
在回放过程中,您将看到发送请求的信息与第一次录制的数据相同。
- 过滤录制的请求,仅保存包含"igetcool"关键字的数据:
mitmdump -nr igetcool.txt -w igetcool-test.txt "~s igetcool"
mitmdump 功能扩展
介绍
常用的 mitmdump 扩展功能,包括修改接口响应状态码、修改接口响应结果、加载本地数据和模拟接口响应延迟。
前提条件
首先,在本地创建 script.py
文件。
修改接口响应状态码
以下示例代码演示了如何使用 mitmdump 修改接口的响应状态码。
def response(flow: http.HTTPFlow):
if "igetcool-gateway.igetcool.com" in str(flow.request.pretty_url):
flow.response.status_code = 404
在上述示例中,我们在 response
函数中判断请求的 URL 是否满足特定条件,如果满足,则将响应状态码设置为 404。您可以根据需要修改过滤条件和状态码值。
修改接口响应结果
以下示例代码演示了如何使用 mitmdump 修改接口的响应结果。
import json
def response(flow: http.HTTPFlow):
if "https://igetcool-gateway.igetcool.com/app-api-user-server/white/app/head/config.json" in str(flow.request.pretty_url):
data = json.loads(flow.response.content)
data['data']['isShow'] = 2
flow.response.set_text(json.dumps(data))
在上述示例代码中,我们通过添加过滤条件来确定要修改响应结果的特定接口。然后,我们加载原始响应数据并进行修改。在示例中,我们修改了数据字段 data['data']['isShow']
的值为 2。最后,我们将修改后的数据重新设置为响应结果,以确保返回给客户端的数据已被修改。
加载本地数据(Map Local)
以下示例代码演示了如何使用 mitmdump 将指定的网络请求重定向到本地文件,以实现加载本地数据的目的。
import json
def response(flow: http.HTTPFlow):
if "igetcool" in str(flow.request.pretty_url):
with open("/Users/xinxi/Documents/zhihu/mitmproxyRecode/igetget.json", 'r') as f:
resp_info = json.loads(f.read())
flow.response.set_text(json.dumps(resp_info))
在上述示例代码中,我们使用一个过滤条件来匹配需要加载本地数据的网络请求。例如,在过滤条件中,我们检查请求 URL 中是否包含 "igetcool" 字符串。然后,我们打开本地文件并将文件中的内容加载为 JSON 格式的数据。最后,我们将本地数据作为响应结果返回。
请根据您自己的实际情况,修改文件路径以及过滤条件。
模拟接口响应延迟的方法
在 mitmdump 中没有直接设置接口延迟的方法,但我们可以使用 time.sleep()
函数来实现该效果。以下示例代码可以模拟接口响应延迟。
import time
import random
from mitmproxy import http
def response(flow: http.HTTPFlow):
if "igetcool" in str(flow.request.pretty_url):
random_time = random.randint(100, 1000)
time.sleep(random_time / 1000)
在上述示例代码中,我们添加了一个过滤条件,仅对特定请求进行延迟模拟。如果请求的 URL 中包含 "igetcool" 字符串,我们会生成一个介于 100 到 1000 之间的随机整数,表示延迟的毫秒数。然后,利用 time.sleep()
函数将程序暂停指定的毫秒数,模拟延迟。
- mitmproxy 官方文档:https://docs.mitmproxy.org/stable/
- mitmproxy 脚本示例:https://github.com/mitmproxy/mitmproxy/tree/master/examples
- 参考链接:https://blog.wolfogre.com/posts/usage-of-mitmproxy/#示例
本文来自博客园,作者:术科术,转载请注明原文链接:https://www.cnblogs.com/shukeshu/p/17529344.html