mitmproxy 就是用于 MITM 的 代理(proxy), 而MITM,也就是(Man-in-the-middle attack)中间人攻击,指的就是通过各种技术手段将入侵者的一台计算机(或服务器)虚拟放置在网络连接的两台计算机之间。(SMB会话劫持、DNS欺骗等)计算机相互通信的请求响应过程均可以被拦截获取,在中间人攻击中,攻击者将自己伪装成每一个参与会话的终端,且不被其他终端识破,攻击者可以拦截通讯双方的通话并插入新的内容。
### 1.3 代理服务器
中间人攻击可以通过代理服务器实现,由HTTP、SMTP、POP3和FTP等发展到SSL、SOCK4/5代理以及其他未知的代理类型,相当于包裹交换一个中转站。而mitmproxy就是通过代理的方式实现信息拦截的
mitmproxy相比于Charles和Fiddler,它可以以命令行或者脚本方式hook,也可以定制化抓取数据,实现像Charles一样的改装请求。
pip install pipx
pip install mitmproxy
# 或者直接用pip install mitmproxy 命令安装
windows安装完后,需要手动配置mitmproxy到环境变量中(注:我这里使用的是anconda环境,直接将bin目录下的所有可执行文件放入环境变量即可)
windows安装好后,可在IDE或者cmd中输入mitmweb查看是否安装成功
在windows环境下,mitmproxy接口并不支持
mitmweb 是mitmproxy的web化界面工具,在上面我们可以看到完整的请求响应流以及对应的头和身体
此时,还没有安装成功,我们发现还不能拦截到数据,这是因为我们没有安装证书和打开对应的监听窗口, 这里主要的雷区就是,windows平台的证书其实在我们装mitmproxy的时候系统已经自动给你下载了
安装路径在我们的usr\13386(用户名).mitmproxy 下,p12结尾的证书就是windows平台下的。
双击mitmproxy-ca.p12,进入证书导入向导。
傻瓜式安装,下一步就行
注意这里的密码填空就行了。
下一步将证书放入下列存储选项中,选择受信任的根证书颁发机构
点击完成,证书就导入到当前用户\计算机的根证书存储里面了
接下来就是打开代理,win10平台可以直接在设置中搜索代理就可以定位到手动代理设置这一栏。也可以在chrome/Firefox下的高级设置中找到代理设置,打开代理,并且端口号为Proxy监听的端口号8080(手机端的安装配置与其类似),这时候重启mitmweb,可以看到下图所示,抓到本机发出的请求flow(流)了。其使用方法与Charles类似,这里不再赘述。
brew install mitmproxy
如果是Mac,命令安装完后,会自动添加好环境变量。由于博主主要使用的是win的平台,对mac不太熟悉,要想参考麻烦移步其它文章 (奥力给~)
mitmdump是mitmprox的核心,它是mitmproxy 的命令行版本。将 tcpdump 用于 HTTP
近似于 charles 的命令行版本
import mitmproxy.http
from mitmproxy import ctx
import traceback, os
filter_host = "web.bit.edu.cn"
url_path = "web.bit.edu.cn/https/77726476706e69737468656265737421e7e056d2223e6f59700d8cbe915b24239d8e8349f501643293dc/search/results"
class catch_cookies(object):
'''
利用mitmproxy模拟一个完整的HTTP通信周期获取\修改数据
'''
def __init__(self):
self.cookie = ""
self.num = 0
# 与服务器建立代理连接,仅仅是client与proxy连接,不会触发request,response以及其他http事件
def http_conn(self, flow: mitmproxy.http.HTTPFlow):
pass
# 来自client的 HTTP 请求的头部被成功读取, body还是空的
def request_headers(self, flow: mitmproxy.http.HTTPFlow):
pass
# 来自client的 HTTP 请求被成功完整读取(包括请求头cookie以及body)
def request(self, flow: mitmproxy.http.HTTPFlow):
global filter_host, url_path
if (flow.request.host != filter_host) and (url_path not in str(flow.request.url)):
return
self.num += 1
if self.num > 1:
pass
else:
ctx.log.info(u"处理第 %d 个请求" % self.num)
print("处理第 %d 个请求" % self.num)
try:
for key, value in flow.request.cookies.items():
# if "wengine__ticket" not in key:
# pass
# else:
coo = "{}={}; ".format(key, value)
self.cookie += coo
# self.cookie += flow.request.cookies[i]
print("cookie", self.cookie)
# 将cookie写进文本里,再写一个程序读取,直接在此模块导入redis会报没有redis模块(未解决)
with open(r'./cookies_ei_bit.txt', 'w', encoding="utf-8") as file:
file.write(self.cookie)
print("cookie写入成功\033[0m")
except:
print(traceback.print_exc())
# 来自server的 HTTP的响应头部被成功读取, body还是空的
def response_headers(self, flow: mitmproxy.http.HTTPFlow):
pass
# 来自server的 HTTP 响应被成功完整读取
def response(self, flow: mitmproxy.http.HTTPFlow):
pass
# 处理响应异常, HTTP错误
def error(self, flow: mitmproxy.http.HTTPFlow):
pass
addons = [
catch_cookies()
]
if __name__ == '__main__':
from mitmproxy.tools.main import mitmweb
mitmweb()