免责声明:由于传播、利用本公众号李白你好所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,公众号李白你好及作者不为此承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除并致歉。谢谢!
1►
mitmdump
最近好几次众测遇到前端js加密,除了需要进行前端加密算法分析之外,还需要mitmdump配合burp进行自动化解密,因此这里就遇到了mitmdump的使用,之前遇到的加密站是朋友帮忙写的,我本想着在此基础上修修改改但是在修改的过程中遇到了很多问题,本质上是对上下游代理的转发不是很熟悉,于是自己在本地进行手动调试做了详细的记录。
2►
上下游代理
在此之前我们先了解一下代理,平时我们正常渗透一般是在浏览器挂代理,将流量转发给burp,在转发给服务器。同时服务器响应先返回给burp,burp在返回给客户端。
那么我们结合mitmdump的时候具体的请求如下:
下游代理
下游代理主要是接收客户端的加密请求密文,进行解密将解密结果发送到burp,burp将解密的数据呈现给我们。同时将burp传递的明文加密然后返回给客户端。
上游代理
上游代理主要是处理burp传递的请求进行加密返回给服务端。同时接收服务端的加密响应密文,进行解密将解密结果发送到burp,burp将解密结果呈现给我们。
burp
burp的主要作用其实就是将解密结果呈现给我们,在一个就是可以使用repeter重发。
3►
mitmproxy
上下游代理均需要使用函数去处理请求和响应。
from mitmproxy import flowfilter,ctxfrom mitmproxy.http import HTTPFlowfrom mitmproxy import flowfilterfrom mitmproxy.http import HTTPFlowclass Mimit():def request(self,flow):def response(self,flow):addons = [Mimit(),]
上游代理:
request函数:处理burp发送的请求,编写函数进行加密并将结果发送给服务端。因为上游的request请求是处理burp中的数据的,在burp中无法看到处理之后的请求。这里通过控制台演示一下
response函数:处理服务端返回的响应,编写函数进行解密将结果发送给burp。
下游代理:
request函数:处理客户端发送的请求,编写函数进行解密并将结果返回给burp。
response函数:处理burp接收到的明文响应,编写函数进行加密并将结果返回给客户端。
为了方便理解,这里单独对上、下游代理进行调试,梳理一下处理流程。这里我使用GPT简单写了一个客户端和服务端。
主要逻辑就是客户端对数据base64加密,然后服务端解密继续base64加密并将结果返回。
前端代码
<!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('1.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>
后端代码
<?phpheader('Content-Type: application/json');// 获取 POST 参数$postData = json_decode(file_get_contents("php://input"), true);// 检查是否接收到有效数据if (isset($postData['encodedData'])) {// 获取 Base64 编码的数据$encodedData = $postData['encodedData'];// 判断是否以等号("=")结尾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);}?>
正常请求,如图:可以看到正常的请求就是加密处理的,这里我们就需要使用mitmproxy对请求和响应加解密方便我们进行渗透测试。
4►
下游代理调试
下游处理函数
from mitmproxy import flowfilter,ctxfrom mitmproxy.http import HTTPFlowfrom mitmproxy import flowfilterfrom mitmproxy.http import HTTPFlowimport base64class Mimit():def request(self,flow):if flow.request.host=="192.168.0.101":req = json.loads(flow.request.get_text())ctx.log.info("浏览器请求数据 => "+req['encodedData'])data = base64.b64decode(str(req['encodedData']).encode()).decode()req['encodedData'] = datactx.log.info("下游代理解密请求数据 => " + req['encodedData'])flow.request.set_text((json.dumps(req)))def response(self,flow):if flow.request.host=="192.168.0.101":rep = json.loads(flow.response.get_text())ctx.log.info("响应数据 => "+rep['decodedData'])data = base64.b64encode(str(rep['decodedData']).encode()).decode()ctx.log.info("响应数据 => " + data)rep['decodedData'] = dataflow.response.set_text(json.dumps(rep))addons = [Mimit(),]
命令行启动下游代理并将上游代理设置为burp。
mitmdump -p 7070 -s dec.py --mode upstream:http://127.0.0.1:8080 --ssl-insecure在浏览器中设置下游代理。
此时的流程为
配置好之后发起请求,此时我们查看命令行和burp中的数据
可以看到,没有挂上游代理不会对响应数据进行解密,只是下游代理将客户端的请求解密在burp中呈现,因此请求包是明文,返回包是密文。
下游代理会加密burp传递的参数,也就是服务端传递的bWl0bXByb3h5,最终得到结果YldsMGJYQnliM2g1。因为这里没有上游代理,返回包没有被解密,所以会二次base64加密嘛。
5►
上游代理调试
上游处理函数
from mitmproxy import flowfilter,ctxfrom mitmproxy.http import HTTPFlowfrom mitmproxy import flowfilterfrom mitmproxy.http import HTTPFlowimport base64class Mimit():def request(self,flow):if flow.request.host=="192.168.0.101":req = json.loads(flow.request.get_text())ctx.log.info("浏览器请求数据 => "+req['encodedData'])data = base64.b64decode(str(req['encodedData']).encode()).decode()req['encodedData'] = datactx.log.info("下游代理解密请求数据 => " + req['encodedData'])flow.request.set_text((json.dumps(req)))def response(self,flow):if flow.request.host=="192.168.0.101":rep = json.loads(flow.response.get_text())ctx.log.info("响应数据 => "+rep['decodedData'])data = base64.b64encode(str(rep['decodedData']).encode()).decode()ctx.log.info("响应数据 => " + data)rep['decodedData'] = dataflow.response.set_text(json.dumps(rep))
命令行启动上游代理。
mitmdump -p 9091 -s enc.py --ssl-insecureburp挂上游代理
此时流程为
配置好之后发起请求,此时我们查看命令行和burp中的数据。注意因为我们没有下游代理不会对客户端发送的请求解密,然而上游代理会进行加密,因此进行了二次base64加密。此时为了方便岩石,服务端也需要二次解密。所以修改一下代码。
// 判断是否以等号("=")结尾if (substr($encodedData, -1) === '=') {// 如果以等号结尾,解码并再次进行加密传递给客户端$decodedData = base64_decode($encodedData);$decodedData = base64_decode($decodedData);$decodedData = base64_encode($decodedData);} else {// 如果不是 Base64 编码,直接对原始数据进行 Base64 编码$decodedData = base64_encode($encodedData);}
可以看到上游代理对服务端返回的数据进行解密,呈现给客户端。
此时并没有下游代理对数据进行加密,因此客户端接收的是明文。
6►
上下游代理调试
最后我们上、下游代理同时挂起进行调试。
下游代理
mitmdump -p 7070 -s dec.py --mode upstream:http://127.0.0.1:8080 --ssl-insecure上游代理
mitmdump -p 9091 -s enc.py --ssl-insecure最终burp呈现数据如下
客户端也可以正常接收请求
7►
Debug
平时在测试的时候,编写脚本可能需要debug,在上游代理可以使用以下脚本进行debug
import sysimport osfrom mitmproxy.tools.main import mitmdumpsys.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)])
此时在enc.py中下断点就行。
下游代理同理
import sysimport osfrom mitmproxy.tools.main import mitmdumpsys.path.append(os.path.dirname(os.path.abspath(__file__)))print(os.path.dirname(os.path.abspath(__file__)))# 启动 mitmdumpmitmdump(['-s', 'dec.py','-p', str(7071), '--mode', "upstream:http://127.0.0.1:8080"])
在dec.py下断点即可
文章作者:先知社区(暮秋初九)
文章来源:https://xz.aliyun.com/t/13218
8►
关注我们
云安全-Docker容器逃逸总结
渗透必备:使用Proxifier玩转代理