20240922-mitmproxy-burpsuite-aes-encrypt-decrypt

mitmproxy-burp-mitmproxy-client encrypt/decrypt

使用mitmproxy对加密流量进行解密/加密,使得burp中可见流量为明文,可重放、爆破.
mitmproxy与burpsuite联动做流量解密。

  • 解密/加密流程图

    mitmproxy-burp-mitmproxy-client encrypt/decrypt model

    起两个mitmproxy 服务分别对进入/离开burp的流量的req/res做修改(加/解密);

  • mitmproxy 使用

    mitmproxy 下载地址;

  • mitmproxy安装/证书安装

    设置mitmproxy 监听,并且设置浏览器连接mitmproxy代理,访问http://mitm.it/,下载对应版本证书,安装为系统根证书。

    1
    2
    # 监听8999端口
    mitmproxy -p 8999
  • 启动burpsuite

    启动burpsuite,监听9001端口,并设置upstream proxy rule:针对目标host192.168.22.5,使用上游代理点127.0.0.1:8888.
    upstream proxy

  • 设置近client侧mitmproxy监听服务

    1
    2
    3
    4
    # 监听端口:9999
    # 上游代理(burp): 127.0.0.1:9001
    # 启动脚本 001-encrypt.py
    mitmproxy -p 9999 --mode upstream:http://127.0.0.1:9001 -s ./001-client-side.py
  • 设置近server侧mitmproxy监听服务

    1
    2
    3
    # 监听端口:8888
    # 启动脚本 002-decrypt
    mitmproxy -p 8888 -s ./002-server-side.py
  • mitmproxy 脚本

    其中 001-client-side.py002-server-side.py脚本中放置对近client侧,近server侧req/res修改的操作。 AES-256/CBC/Pkcs7Padding 的001-client-side.py 代码模板002-server-side.py 代码模板

    001-client-side代码样例如下:

    001-client-side.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    #start
    from cryptography.hazmat.backends import default_backend
    from cryptography.hazmat.primitives import padding
    from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
    from mitmproxy import http
    import base64

    #
    # AES/256/CBC/Pkcs7Padding
    #
    # template
    #

    # Base64 解码密钥和 IV
    secret_key_base64 = "dGVzdF9zZWNyZXRfa2V5"
    # iv 长度是16位,多余的会被舍弃
    iv_base64 = "dGVzdF9pdg=="

    secret_key = base64.b64decode(secret_key_base64)
    # iv 长度是16位,多余的会被舍弃
    iv = base64.b64decode(iv_base64)[:16]

    # AES加解密函数
    def encrypt_aes(data, key, iv):
    # Pkcs7 padding
    padder = padding.PKCS7(algorithms.AES.block_size).padder()
    padded_data = padder.update(data) + padder.finalize()

    # AES-CBC 加密
    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
    encryptor = cipher.encryptor()
    encrypted_data = encryptor.update(padded_data) + encryptor.finalize()
    return encrypted_data

    def decrypt_aes(data, key, iv):
    # AES-CBC 解密
    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
    decryptor = cipher.decryptor()
    decrypted_data = decryptor.update(data) + decryptor.finalize()

    # 去除 Pkcs7 padding
    unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
    unpadded_data = unpadder.update(decrypted_data) + unpadder.finalize()
    return unpadded_data

    # 处理 response 流量
    def response(flow: http.HTTPFlow):
    # 获取 Content-Type
    content_type = flow.response.headers.get("Content-Type", "")

    # 只处理 JSON 响应体,检查 Content-Type 是否为 application/json
    if "application/json" in content_type:

    # 进行加密
    try:
    # 解码 JSON 响应体
    original_body = flow.response.content

    # 加密响应体
    new_encrypted_body = encrypt_aes(original_body, secret_key, iv)

    # Base64 编码加密后的数据
    flow.response.content = base64.b64encode(new_encrypted_body)

    # 如果需要修改 Content-Type,可以设置合适的加密格式标识
    # flow.response.headers["Content-Type"] = "application/octet-stream"
    except Exception as e:
    print(f"Error during encryption: {e}")
    else:
    # 静态资源如JS、PNG等,跳过加密
    print(f"Skipping encryption for Content-Type: {content_type}")
    #end

    002-server-side代码样例如下:

    002-server-side.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    #start
    from cryptography.hazmat.backends import default_backend
    from cryptography.hazmat.primitives import padding
    from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
    from mitmproxy import http
    import base64

    #
    # AES/256/CBC/Pkcs7Padding
    #
    # template
    #

    # Base64 解码密钥和 IV
    secret_key_base64 = "dGVzdF9zZWNyZXRfa2V5"
    # iv 长度是16位,多余的会被舍弃
    iv_base64 = "dGVzdF9pdg=="

    secret_key = base64.b64decode(secret_key_base64)
    # iv 长度是16位,多余的会被舍弃
    iv = base64.b64decode(iv_base64)[:16]

    # 流式 AES 加密
    def encrypt_aes_stream(data, key, iv):
    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
    encryptor = cipher.encryptor()

    # Pkcs7 padding
    padder = padding.PKCS7(algorithms.AES.block_size).padder()
    padded_data = padder.update(data) + padder.finalize()

    # 分块加密
    encrypted_data = encryptor.update(padded_data) + encryptor.finalize()
    return encrypted_data

    # 流式 AES 解密
    def decrypt_aes_stream(data, key, iv):
    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
    decryptor = cipher.decryptor()

    # 分块解密
    decrypted_data = decryptor.update(data) + decryptor.finalize()

    # 去除 Pkcs7 padding
    unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
    unpadded_data = unpadder.update(decrypted_data) + unpadder.finalize()
    return unpadded_data

    # 处理 response 流量
    def response(flow: http.HTTPFlow):
    # 只处理有 body 的 response
    if flow.response.content:
    content_type = flow.response.headers.get("Content-Type", "")

    # 只对 JSON 响应体进行解密处理
    if "application/json" in content_type:
    try:
    # 解密响应体
    encrypted_body = flow.response.content
    decoded_encrypted_body = base64.b64decode(encrypted_body)

    # 流式解密
    decrypted_body = decrypt_aes_stream(decoded_encrypted_body, secret_key, iv)

    flow.response.content = decrypted_body

    # 更新 Content-Type
    # flow.response.headers["Content-Type"] = "application/json"
    except Exception as e:
    print(f"Error during decryption: {e}")
    #end