侧边栏壁纸
博主头像
胜星的博客博主等级

行动起来,活在当下

  • 累计撰写 23 篇文章
  • 累计创建 38 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

mitmproxy在微信小程序渗透测试中的应用

胜星
2024-07-05 / 0 评论 / 1 点赞 / 71 阅读 / 7301 字

mitmproxy在微信小程序渗透测试中的应用

微信小程序作为一种流行的轻量级应用平台,其安全性问题日益受到重视。小程序的网络请求往往涉及敏感信息传输,因此,对请求包的加解密处理尤为重要。然而,由于小程序的封闭性和加密性,对请求包的分析和测试存在一定难度。本文将探讨如何利用mitmproxy工具解决微信小程序渗透测试中的请求包加解密问题。

mitmproxy的作用

mitmproxy是一个功能强大的中间人代理工具,它能够拦截、分析、修改经过代理的HTTP(S)流量。通过mitmproxy,渗透测试人员可以解密HTTPS流量中经过算法加密的请求参数和响应包,查看和修改请求与响应数据,从而深入分析小程序的安全性,以下是请求流量的走向示意图:

image-20240705111026956

mitmproxy在实际案例中的使用

1.安装mitmproxy根证书

mitmproxy的安装过程不做记录,需要注意的点是安装mitmproxy根证书,安装好mitmproxy后,使用everything搜索到mitmproxy的证书存放目录,导入到计算机中

image-20240705105738603

2.编写mitmproxy下游加解密脚本

通过对数据包的分析发现,数据包的中的请求参数和响应参数中的bizContent字段是经过aes的加密,目前已知aes的密钥和加密模式为ECB

1.使用Proxifier代理微信小程序流量

设置代理端口

image-20240705111256855

设置代理的规则

image-20240705111320645

2.编写burp下游代理的解密脚本:

from mitmproxy import flowfilter, ctx  # 导入mitmproxy的模块,用于流量过滤和日志记录
from mitmproxy.http import HTTPFlow  # 导入HTTPFlow类,表示HTTP请求和响应的集合
from base64 import b64decode  # 导入base64库的解码功能
import base64  # 导入base64库用于编码
import json  # 导入json库用于处理JSON数据
from Crypto.Cipher import AES  # 导入AES加密模块
from Crypto.Util.Padding import unpad, pad  # 导入填充和去填充功能


# 定义使用AES ECB模式加密数据的函数
def aes_encrypt(ciphertext):
    key = b'xxxxxxxx'  # 定义16字节的密钥
    data_bytes = pad(ciphertext.encode('utf-8'), AES.block_size)  # 对数据进行填充
    cipher = AES.new(key, AES.MODE_ECB)  # 创建AES ECB模式的Cipher对象
    encrypted_data = cipher.encrypt(data_bytes)  # 加密数据
    encoded_encrypted_data = base64.b64encode(encrypted_data)  # 将加密数据转换为Base64编码
    return encoded_encrypted_data.decode('utf-8')  # 返回解码后的Base64字符串


# 定义使用AES ECB模式解密数据的函数
def aes_decrypt(ciphertext):
    key = 'xxxxxxxx'  # 密钥应该是字节串,这里应该直接提供字节串而不是字符串
    key_bytes = bytes(key, 'utf-8')  # 将密钥转换为字节串
    cipher_text_bytes = b64decode(ciphertext)  # 解码Base64编码的密文
    cipher = AES.new(key_bytes, AES.MODE_ECB)  # 创建AES ECB模式的解密器
    decrypted_text = cipher.decrypt(cipher_text_bytes)  # 解密数据
    try:
        plaintext = unpad(decrypted_text, AES.block_size)  # 移除PKCS7填充
        return plaintext.decode('utf-8')  # 返回解密后的字符串
    except ValueError as e:  # 捕获填充错误
        print(f"解密后无法移除填充: {e}")
        return None


class Mimit():
    def request(self, flow):
        # 在请求处理函数中,解析请求体为JSON格式
        req = json.loads(flow.request.get_text())
        # 检查'bizContent'字段是否存在且不为空
        if 'bizContent' in req and req['bizContent'] != '':
            data = aes_decrypt(req['bizContent'])  # 解密数据
            ctx.log.info("请求数据 => " + data)  # 记录解密后的数据
            req['bizContent'] = data  # 更新'bizContent'字段
            flow.request.set_text(json.dumps(req))  # 设置更新后的请求体

    def response(self, flow):
        # 在响应处理函数中,解析响应体为JSON格式
        rep = json.loads(flow.response.get_text())
        # 检查'bizContent'字段是否存在且不为空
        if 'bizContent' in rep and rep['bizContent'] != '':
            data = aes_encrypt(rep['bizContent'])  # 加密数据
            ctx.log.info("响应数据 => " + data)  # 记录加密后的数据
            rep['bizContent'] = data  # 更新'bizContent'字段
            flow.response.set_text(json.dumps(rep))  # 设置更新后的响应体


# 将插件实例化为一个列表,以便mitmproxy加载
addons = [Mimit()]

3.执行下游解密脚本

mitmdump -p 7070 -s dec.py  --mode upstream:http://127.0.0.1:8080 --ssl-insecure

image-20240705111546485

burp中的默认端口依然保持不变

image-20240705111528143

3.编写mitmproxys上游加解密脚本

1.编写burp上游加解密脚本

from mitmproxy import flowfilter, ctx  # 导入用于流量过滤和日志记录的模块
from mitmproxy.http import HTTPFlow  # 导入HTTPFlow模块,用于处理HTTP请求和响应

# 导入base64库用于编码和解码操作
from base64 import b64decode
import base64
# 导入json库用于解析和序列化JSON数据
import json
# 导入Crypto.Cipher.AES模块用于AES加密和解密
from Crypto.Cipher import AES
# 导入Crypto.Util.Padding模块用于数据的填充和去填充操作
from Crypto.Util.Padding import unpad, pad

# 定义使用AES ECB模式加密数据的函数
def aes_encrypt(ciphertext):
    key = b'xxxxxxxx'  # 定义16字节的密钥
    data_bytes = pad(ciphertext.encode('utf-8'), AES.block_size)  # 对数据进行PKCS7填充
    cipher = AES.new(key, AES.MODE_ECB)  # 创建AES ECB模式的Cipher对象
    encrypted_data = cipher.encrypt(data_bytes)  # 加密数据
    encoded_encrypted_data = base64.b64encode(encrypted_data)  # 将加密数据转换为Base64编码
    return encoded_encrypted_data.decode('utf-8')  # 返回Base64编码的字符串

# 定义使用AES ECB模式解密数据的函数
def aes_decrypt(ciphertext):
    key = 'xxxxxxxx'  # 密钥应该是字节串,这里直接提供字符串,将在函数内部转换
    cipher_text_bytes = b64decode(ciphertext)  # 解码Base64编码的密文
    key_bytes = bytes(key, 'utf-8')  # 将字符串形式的密钥转换为字节串
    cipher = AES.new(key_bytes, AES.MODE_ECB)  # 创建AES ECB模式的解密器
    decrypted_text = cipher.decrypt(cipher_text_bytes)  # 解密数据
    try:
        plaintext = unpad(decrypted_text, AES.block_size)  # 移除PKCS7填充
        return plaintext.decode('utf-8')  # 返回解密后的字符串
    except ValueError as e:  # 捕获并处理解密过程中可能出现的填充错误
        print(f"解密后无法移除填充: {e}")
        return None

# 定义Mimit类,用于处理HTTP请求和响应
class Mimit():
    def request(self, flow):
        # 在请求处理函数中,解析请求体为JSON格式
        req = json.loads(flow.request.get_text())
        # 检查'bizContent'字段是否存在且不为空
        if 'bizContent' in req and req['bizContent'] != '':
            data = aes_encrypt(req['bizContent'])  # 对'bizContent'字段进行AES加密
            ctx.log.info("请求数据 => " + data)  # 记录加密后的请求数据
            req['bizContent'] = data  # 更新JSON对象中的'bizContent'字段
            flow.request.set_text(json.dumps(req))  # 设置更新后的请求体

    def response(self, flow):
        # 在响应处理函数中,解析响应体为JSON格式
        rep = json.loads(flow.response.get_text())
        # 检查'bizContent'字段是否存在且不为空
        if 'bizContent' in rep and rep['bizContent'] != '':
            data = aes_decrypt(rep['bizContent'])  # 对'bizContent'字段进行AES解密
            ctx.log.info("响应数据 => " + data)  # 记录解密后的响应数据
            rep['bizContent'] = data  # 更新JSON对象中的'bizContent'字段
            flow.response.set_text(json.dumps(rep))  # 设置更新后的响应体

# 将Mimit类的实例添加到addons列表,以便mitmproxy加载
addons = [Mimit()]

2.设置burp中的上游代理端口

image-20240705112249655

3.执行上游加解密脚本

mitmdump -p 9090 -s enc.py --ssl-insecure

4.执行效果

image-20240705112601803

1

评论区