BurpGuard 的使用案例

声明

本文版权归原作者所有,未经允许禁止转载。

前言

越来越多的师傅正在针对渗透中前端加解密生成解决方案,例如 Galaxy:https://github.com/outlaws-bai/Galaxy,而 BurpGuard 是依赖于 mitmproxy 的开发的一个简易代理框架,可以一键启动上下游代理,并编写 Python 代码对请求和响应进行自定义修改。

阅读本文前建议读者先掌握一些 Python 的基础语法,并前往项目地址,阅读项目的使用帮助。

项目地址:https://github.com/yinsel/BurpGuard

靶场项目:https://github.com/0ctDay/encrypt-decrypt-vuls/

在线练习地址:http://39.98.108.20:8085/(非本人搭建,由先知师傅搭建,轻点测)

在线靶场来源:https://xz.aliyun.com/t/15252

JS 逆向

JS 逆向的话不是特别难,可以参考先知师傅的,讲的很详细。

https://xz.aliyun.com/t/15252

下面介绍下逆向的结果。

加密

加密采用 AES CBC 模式,PKCS 7 填充模式以及 Base 64 。

签名

根据当前日期生成时间戳 timestamp,以及 32 位的 id(通过 uuid 生成),最终通过以下公式生成 sign 值:

# data是原始请求数据
sign = data + id + timestamp

编写脚本并调试

以下 Demo 可直接贴在 ClientProxyHandler.py 或者是 BurpProxyHandler.py 的最下方直接运行。

解密请求数据 Demo

# 加密的数据
data = "viaGravie+m/oW4EuPkeHhloK+IDv3tzkvO3+gMNIDX2bNwDOSVxYZ84Z/c6JGWDamAmfPaulWDT8cASPYbRrg=="
 
data = b64decode(data.encode())
print(AES.decrypt(data,AES.CBC,b"1234567891234567",b"1234567891234567"))

结果:

b'{"password":"123456","username":"admin","validCode":"e65a"}'

生成签名 Demo

data = '{"password":"123456","username":"admin","validCode":"e65a"}'
 
def md5(data: str):
    return hashlib.md5(data.encode()).hexdigest()
    
def get_sign(data: str, id: str, timestamp: str):
    sign = md5(data + id + timestamp)
    return sign
 
timestamp = str(int(time.time() * 1000))
id = uuid.uuid4().hex
sign = get_sign(data,id,timestamp)
 
print("timestamp:",timestamp)
print("RequestId:",id)
print("sign:",sign)

原始:

结果:

timestamp: 1723698310909
RequestId: af5abbb088674543acab0d4b44568680
sign: 91b68d873cee0a714ba584cb96caf491

复制新的签名到 Burp 中:

加密请求数据

# 原始数据
data = '{"password":"123456","username":"admin","validCode":"e65a"}'
 
data = AES.encrypt(data.encode(),AES.CBC,b"1234567891234567",b"1234567891234567")
print(b64encode(data).decode())

结果:

viaGravie+m/oW4EuPkeHhloK+IDv3tzkvO3+gMNIDX2bNwDOSVxYZ84Z/c6JGWDamAmfPaulWDT8cASPYbRrg==

解密响应:

# 加密的数据
data = "0uMDI+g2bagWZ6+wlwBGQYjPFu1pJ8oA39/HzrpZT7m90oXkbw2BYHkVaDSemjsXmDg3TomBk3caiSxIlLkgKkJch+VD0Utg/L0NdMbH+of1ffTgHmYmHIM/1ysStaI8cGDrZsxBsM+Ha5ATgGq/lrLEXF7LOOGxJDIPYO+HZBLHfK3uyi+oetEP8FUUrMLpU/iAeWwx2c9BaN/01mwLb7PV0HzY3/2ulZoe+jxZz3TBD1RBci5dP6Cqr+vNQ7D8eToVuC1H/0YZiRcxIWKtBgmOhHNrndDTRyb4jMwPHXFwRqJajAVWUuceQqHjOnqhyZOnUQ1krX7Bpz/h7maJ4p1lGVn0crljtoG0ZMfaKEvKSN/ErQLjDvEoBwGD9ScU"
 
data = b64decode(data.encode())
print(AES.decrypt(data,AES.CBC,b"1234567891234567",b"1234567891234567").decode())

结果:

{"code":"0","msg":"成功","data":{"id":15,"username":"admin","nickName":"test","sex":"
男","address":"test223","phone":"11111111111","token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIxNSIsImV4cCI6MTcyMzc4NTExNH0.pJyORDB6akJHwLOqmEznXOSR_wOHNZx-xO4ag0qUYMs","role":2}}

最终成品

ClientProxyHandler.py

from mitmproxy import http
from Utils.Crypto import *
import httpx
from base64 import b64encode,b64decode
from urllib.parse import quote,unquote
import json
import traceback
import time
import hashlib
import uuid
 
    
 
class ClientProxyHandler:
    def __init__(self) -> None:
        self.client = httpx.Client(timeout=None,verify=False)
        
   # 处理来自客户端的请求,通常在这里对请求进行解密
    def request(self,flow: http.HTTPFlow):
        try:
            req = flow.request
            # 解密请求数据
            if req.method == "POST" and f"{req.host}:{req.port}" == "39.98.108.20:8085":
                data = req.text
                data = b64decode(data.encode())
                data = AES.decrypt(data,AES.CBC,b"1234567891234567",b"1234567891234567")
                req.content = data
        except Exception as e:
            traceback.print_exception(e)
        return flow
 
    # 处理返回给客户端的响应,通常在这里对响应进行加密
    def response(self,flow: http.HTTPFlow):
        try:
            rsp = flow.response
            req = flow.request
            # 加密响应数据
            if f"{req.host}:{req.port}" == "39.98.108.20:8085" and rsp.content:
                data = rsp.content
                data = AES.encrypt(data,AES.CBC,b"1234567891234567",b"1234567891234567")
                data = b64encode(data)
                rsp.content = data
        except Exception as e:
            traceback.print_exception(e)
        return flow
    
addons = [ClientProxyHandler()]

BurpProxyHandler.py

from mitmproxy import http
from Utils.Crypto import *
import httpx
from base64 import b64encode,b64decode
from urllib.parse import quote,unquote
import json
import traceback
import time
import hashlib
import uuid
 
def md5(data: str):
    return hashlib.md5(data.encode()).hexdigest()
def get_sign(data: str, id: str, timestamp: str):
    sign = md5(data + id + timestamp)
    return sign
 
class BurpProxyHandler:
    def __init__(self) -> None:
        self.client = httpx.Client(timeout=None,verify=False)
        
    # 处理来自Burp的请求,通常在这里对请求进行加密
    def request(self,flow: http.HTTPFlow):
        try:
            req = flow.request
            if req.method == "POST" and f"{req.host}:{req.port}" == "39.98.108.20:8085":
                data = req.text
                # 生成签名
                timestamp = str(int(time.time() * 1000))
                id = uuid.uuid4().hex
                sign = get_sign(data,id,timestamp)
                req.headers["sign"] = sign
                req.headers["requestId"] = id
                req.headers["timestamp"] = timestamp
                # 加密请求数据
                data = AES.encrypt(data.encode(),AES.CBC,b"1234567891234567",b"1234567891234567")
                data = b64encode(data).decode()
                req.text = data
        except Exception as e:
            traceback.print_exception(e)
        finally:
            return flow
 
    # 处理返回给客户端的响应,通常在这里对响应进行解密
    def response(self,flow: http.HTTPFlow):
        try:
            req = flow.request
            rsp = flow.response
            # 解密响应数据
            if f"{req.host}:{req.port}" == "39.98.108.20:8085" and rsp.content:
                data = rsp.text
                data = b64decode(data.encode())
                data = AES.decrypt(data,AES.CBC,b"1234567891234567",b"1234567891234567")
                rsp.content = data    
        except Exception as e:
            traceback.print_exception(e)
        finally:
            return flow
        
addons = [BurpProxyHandler()]

效果: