跳到主要内容

BurpGuard 的使用案例

· 阅读需 5 分钟
声明

本文版权归原作者所有,转载请注明出处。

前言

越来越多的师傅正在针对渗透中前端加解密生成解决方案,例如 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()]

效果: