mitmproxy前端加解密测试基础(windows为例)
环境安装
所需的环境:mitmproxy / yakit /phpstudy / python
1,mitmproxy 下载:https://mitmproxy.org/ (windows)
下载后选择目录安装好,然后直接双击运行mitmweb.exe,运行起mitmproxy:
浏览器挂上mitmproxy代理后(默认启动后是运行在8080端口,web界面是运行在8081端口),然后访问:http://mitm.it/ ,下载mitmproxy证书
下载好证书后,直接双击证书安装证书:
密码直接留空,下一步:
将证书存储在“受信任的根证书颁发机构”,然后直到安装完成即可。
接着运行pip install mitmproxy给python安装mitmproxy模块就可以了。
测试基础
这里直接借用了先知大牛的文章,跟着做一遍复现即可,主要体会其中过程,理解上下游代理是如何运转以及其中的原理。
上下游代理
一般上下游代理是数据传输从服务端到客户端而言,也就是说服务端为 上游,客户端为 下游,而 burp/yakit 则是位于服务端和客户端之间的代理,因此burp的流量走向上,上边就是上游代理,下边,就是下游代理。
上游代理:服务器-> 上游代理 -> burp/yakit -> 客户端
下游代理:服务器 -> burp/yakit -> 下游代理 -> 客户端
我们今天要实现的效果:服务器 -> 上游代理 -> burp/yakit -> 下游代理 -> 客户端
为啥要上 上下游代理 ,因为如果说 服务器和客户端 两端传输的数据都是加密的话,一般客户端这边是JS代码解密,而我们直接使用burp/yakit 抓包的话,看到的都是加密数据,无从下手,因此需要上下游代理,实现传输中的加解密,实现burp/yakit上抓到的数据是解密后的结果,而传输到服务器和客户端又正好是加密后的结果,保证正常“走数据包”的同时又能对数据包进行测试分析。
前后端测试环境搭建
搭建的话,就用phpstudy起一个web网站就行了,这个是最基本的了,在此不赘述。
前后端代码文件:index.html
-
<!DOCTYPE html>
-
<html lang="en">
-
<head>
-
<meta charset="UTF-8">
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
-
<title>Base64编码示例</title>
-
</head>
-
<body>
-
<form id="myForm">
-
<label for="userInput">输入文本:</label>
-
<input type="text" id="userInput" name="userInput" required>
-
<button type="button" onclick="encodeAndSend()">提交</button>
-
</form>
-
<!-- 添加用于显示服务端返回的数据的元素 -->
-
<div id="responseDataContainer"></div>
-
<script>
-
function encodeAndSend() {
-
var userInput = document.getElementById("userInput").value;
-
var encodedData = btoa(userInput);
-
var jsonData = {
-
encodedData: encodedData
-
};
-
fetch('d.php', {
-
method: 'POST',
-
headers: {
-
'Content-Type': 'application/json'
-
},
-
body: JSON.stringify(jsonData)
-
})
-
.then(response => response.text()) // 修改部分:使用 response.text() 获取字符串
-
.then(data => {
-
// 修改部分:将服务端返回的字符串显示在页面上
-
var responseDataContainer = document.getElementById("responseDataContainer");
-
responseDataContainer.innerHTML = '服务端返回的数据:' + data;
-
})
-
.catch(error => {
-
console.error('Error:', error);
-
});
-
}
-
</script>
-
</body>
-
</html>
后端代码文件:d.php
-
<?php
-
header('Content-Type: application/json');
-
// 获取 POST 参数
-
$postData = json_decode(file_get_contents("php://input"), true);
-
// 检查是否接收到有效数据
-
if (isset($postData['encodedData'])) {
-
// 获取 Base64 编码的数据
-
$encodedData = $postData['encodedData'];
-
// 判断是否以等号("=")结尾,以此判断传过来的数据是否做了base64加密
-
if (substr($encodedData, -1) === '=') {
-
// 如果以等号结尾,解码并再次进行加密传递给客户端
-
$decodedData = base64_decode($encodedData);
-
$decodedData = base64_encode($decodedData);
-
} else {
-
// 如果不是 Base64 编码,直接对原始数据进行 Base64 编码
-
$decodedData = base64_encode($encodedData);
-
}
-
// 返回继续加密后的数据
-
$response = array('reencodedData' => $decodedData);
-
echo json_encode($response);
-
} else {
-
// 返回错误信息
-
$errorResponse = array('error' => 'Invalid data received');
-
echo json_encode($errorResponse);
-
}
-
?>
访问后,加密aaadsdsada1 yakit抓包效果
代码简介:输入数据,如果数据不是以 = 结尾,则加密一次base64后,再加密一次base64后返回加密数据,如果以 = 号结尾,则直接返回base64结果(这里应该问题不大,只要找一串加密后带等于号的字符串测试即可)。
上下游代理测试
实际上在调试的时候,感觉容易搞混乱,后面想清楚了,我们要沿着一个思路主线去进行:那就是,将原本yakit上抓的 请求/响应 中的加密数据,最终呈现效果为 请求/响应 中的数据被解密以明文的方式展示出来!
处理请求和响应基本的python代码框架如下:
-
from mitmproxy import flowfilter,ctx
-
from mitmproxy.http import HTTPFlow
-
from mitmproxy import flowfilter
-
from mitmproxy.http import HTTPFlow
-
class Mimit():
-
def request(self,flow):
-
def response(self,flow):
-
addons = [Mimit(),]
下游代理调试
downstrem.py
-
from mitmproxy import flowfilter,ctx
-
from mitmproxy.http import HTTPFlow
-
from mitmproxy import flowfilter
-
from mitmproxy.http import HTTPFlow
-
import base64
-
import json
-
class Mimit():
-
def request(self,flow):
-
if flow.request.host=="192.168.10.32":
-
req = json.loads(flow.request.get_text())
-
ctx.log.info("浏览器请求数据 => "+req['encodedData'])
-
data = base64.b64decode(str(req['encodedData']).encode()).decode()
-
req['encodedData'] = data
-
ctx.log.info("下游代理解密请求数据 => " + req['encodedData'])
-
flow.request.set_text((json.dumps(req)))
-
def response(self,flow):
-
if flow.request.host=="192.168.10.32":
-
rep = json.loads(flow.response.get_text())
-
ctx.log.info("响应数据 => "+rep['reencodedData'])
-
data = base64.b64encode(str(rep['reencodedData']).encode()).decode()
-
rep['reencodedData'] = data
-
ctx.log.info("下游代理加密响应数据 => " + rep['reencodedData'])
-
flow.response.set_text(json.dumps(rep))
-
addons = [Mimit(),]
流量走向:服务器 -> burp/yakit -> 下游代理(mitmproxy - downstream.py) -> 客户端
启动mitmproxy,打开cmd窗口,输入命令:将mitmproxy设置为yakit的上游代理,8083是我yakit的代理端口
-
mitmdump -p 7070 -s downstream.py --mode upstream:http://127.0.0.1:8083 --ssl-insecure
浏览器挂7070端口mitmproxy代理,将流量转发到mitmproxy上面。
此时,因为只设置了下游代理,下游代理会对客户端给到的加密数据进行解密,然后再丢给yakit,因此yakit中抓的包中,请求包中的数据是明文的,然后yakit 将带有明文的请求包丢给服务器,因为这时还没有设置上游代理,因此服务端拿到的数据是:aaadsdsada1
,然后对 aaadsdsada1
进行base64加密,返回结果YWFhZHNkc2FkYTE=
丢给yakit,因此yakit中响应包中的内容是密文YWFhZHNkc2FkYTE=
,yakit再将密文丢给mimtproxy,因为如果按正常逻辑来说,客户端也要接收到的是密文嘛,因此在下游代理脚本里面要写一个加密逻辑,将数据加密后返回,又因为从yakit那里接收到的是经过一次编码的密文,加密逻辑又会对密文再加密base64编码一次,因此客户端最终得到的结果就是 WVdGaFpITmtjMkZrWVRFPQ==。
上游代理调试(burp演示)
下面把yakit换成burp,没用习惯,不知道在哪设置yakit的上游代理… …
upstream.py
-
from mitmproxy import flowfilter,ctx
-
from mitmproxy.http import HTTPFlow
-
from mitmproxy import flowfilter
-
from mitmproxy.http import HTTPFlow
-
import base64
-
import json
-
class Mimit():
-
def request(self,flow):
-
if flow.request.host=="192.168.10.32":
-
req = json.loads(flow.request.get_text())
-
ctx.log.info("浏览器请求数据 => "+req['encodedData'])
-
data = base64.b64encode(str(req['encodedData']).encode()).decode()
-
req['encodedData'] = data
-
ctx.log.info("上游代理加密请求数据 => " + req['encodedData'])
-
flow.request.set_text((json.dumps(req)))
-
def response(self,flow):
-
if flow.request.host=="192.168.10.32":
-
rep = json.loads(flow.response.get_text())
-
ctx.log.info("响应数据 => "+rep['reencodedData'])
-
data = base64.b64decode(str(rep['reencodedData']).encode()).decode()
-
rep['reencodedData'] = data
-
ctx.log.info("上游代理解密响应数据 => " + rep['reencodedData'])
-
flow.response.set_text(json.dumps(rep))
-
addons = [Mimit(),]
流量走向:服务器 -> 上游代理(mitmproxy - upstream.py) ->burp/yakit -> 客户端
burp设置上游代理
mitmproxy命令:
-
mitmdump -p 9091 -s upstream.py --ssl-insecure
这个的过程直接看图即可,文字描述就有点多了:
上下游代理联动
流量走向:服务器 -> mitmproxy上游代理(upstream.py) -> burp/yakit -> mitmproxy下游代理(downstream.py) -> 客户端
-
上游代理:mitmdump -p 9091 -s upstream.py --ssl-insecure
-
下游代理:mitmdump -p 7070 -s downstream.py --mode upstream:http://127.0.0.1:8083 --ssl-insecure
图解如下:
上下游代理debug
上游脚本
-
import sys
-
import os
-
from mitmproxy.tools.main import mitmdump
-
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
-
print(os.path.dirname(os.path.abspath(__file__)))
-
# 使用 mitmdump 启动并指定端口
-
mitmdump(['-s', 'enc.py', '-p', str(9091)])
下游脚本
-
import sys
-
import os
-
from mitmproxy.tools.main import mitmdump
-
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
-
print(os.path.dirname(os.path.abspath(__file__)))
-
# 启动 mitmdump
-
mitmdump(['-s', 'dec.py','-p', str(7071), '--mode', "upstream:http://127.0.0.1:8080"])
这里就不作演示了,用到的时候调试即可。
参考资料
https://cn-sec.com/archives/2595620.html
https://xz.aliyun.com/news/12664
https://docs.mitmproxy.org/stable/#features
https://learn.microsoft.com/en-us/windows/wsl/install(可安装可不安装,只是改善界面显示用的)