跳转至

Burp Suite 实战:代理、重放与扫描

Burp 的真正价值不是"能抓包",而是把一次手工验证变成可复现的实验:改一个变量、发一次请求、对比响应。下面按"装好 → 抓到 → 改对 → 批量 → 复现"的顺序写,每一步都带真实报错和排查路径。

一、装好:证书是 80% 问题的根源

1.1 基本配置

  1. Proxy → Options → 新建 listener 127.0.0.1:8080(只绑本机,别开 0.0.0.0)。
  2. 浏览器代理指向 127.0.0.1:8080,或者用 SwitchyOmega / FoxyProxy 做规则代理。
  3. 访问 http://burp,下载 CA Certificate(DER 格式)。
  4. 导入信任库。

1.2 各端导入方式

# 转 PEM 并查看是否带 SAN(Chrome 58+ 强制要求 SAN)
openssl x509 -inform DER -in cacert.der -out cacert.pem
openssl x509 -in cacert.pem -noout -text | grep -A1 "Subject Alternative Name"
  • Firefox:设置 → 隐私与安全 → 证书 → 查看证书 → 导入,勾选"信任由此 CA 标识的网站"。
  • Chrome / Edge:走系统信任库。Windows 用 certlm.msc → 受信任的根证书颁发机构 → 导入。
  • macOS:钥匙串访问 → 系统 → 导入 → 双击设为"始终信任"。
  • curl / python-requests:--cacert cacert.pem / verify="cacert.pem"。
  • Java 应用:keytool -importcert -alias burp -file cacert.pem -keystore $JAVA_HOME/lib/security/cacerts -storepass changeit。

1.3 常见抓包失败与定位

现象 根因 处理
NET::ERR_CERT_AUTHORITY_INVALID 证书没进信任库 重新导入到"受信任根"
NET::ERR_CERT_COMMON_NAME_INVALID 老版 Burp CA 无 SAN 升级 Burp;或给 CA 加 SAN 后重签
浏览器能上网但 Burp 无记录 代理没生效 / 走了 PAC 关 PAC,直接用系统代理
HTTPS 站点全部失败,HTTP 正常 客户端不信任 CA 查证书链
App 抓不到,浏览器正常 SSL Pinning 或用了原生网络库 见第四节
只有部分请求缺失 WebSocket / HTTP2 / QUIC 开 HTTP/2 支持;关 QUIC(--disable-quic)
413 服务端限流/限体积 不是 Burp 问题,看服务端日志

二、抓到:Scope 与 History 的组织方式

先划范围,再谈效率。Target → Scope 里只填目标域名,并勾选 Exclude 掉静态资源:

Include: ^https?://(www\.)?target\.com/.*
Exclude: .*\.(js|css|png|jpg|jpeg|gif|woff2?|svg|ico)(\?.*)?$
Exclude: ^https?://(www\.)?target\.com/(static|assets|cdn)/

History 的过滤比翻页有用得多:

  • 按 MIME type 找 JSON → 直接锁定接口
  • 按 Status code 找 302 → 找跳转逻辑
  • 按 Response size 排序 → 异常大的响应往往是数据泄露
  • 搜索 token、secret、password、accessKey → 找硬编码

抓包时养成习惯:先浏览一遍完整业务流程(注册→登录→下单→退款→后台),再回头分析。缺流程会导致越权、状态机类漏洞完全测不到。

三、改对:Repeater 的对照实验法

Repeater 的核心用法是"一次只改一个变量"。

POST /api/order/detail HTTP/1.1
Host: api.target.com
Authorization: Bearer eyJhbGciOi...
Content-Type: application/json

{"orderId": 10086}

对照实验设计:

实验 改什么 观察什么 结论
A orderId 换他人 ID 200 + 数据 水平越权
B 删掉 Authorization 200 + 数据 鉴权缺失
C 换成低权限 token 200 + 数据 权限校验缺失
D orderId 加 ' 500 / SQL 报错 注入可疑
E orderId 改为 10086 OR 1=1 返回多条 注入确认
F 加 X-Forwarded-For: 127.0.0.1 返回内网数据 信任代理头

Repeater 里两个提高效率的功能常被忽略:

  • Send group in sequence (single connection):验证竞态、状态机、一次性 token 时必须用同一连接顺序发送。
  • Response diff(Comparer):把两次响应丢进 Comparer,按 word/byte 级别比,比肉眼看长度可靠。

四、App 抓包:Android 7+ 的证书信任变化

从 Android 7(API 24)开始,用户安装的 CA 不再被 App 默认信任,只信任系统 CA。这就是"浏览器能抓、App 抓不到"的头号原因。

4.1 方案一:把 CA 装进系统证书(需 root)

# 1. 计算 subject_hash_old,得到文件名
openssl x509 -inform DER -in cacert.der -out cacert.pem
openssl x509 -inform PEM -subject_hash_old -in cacert.pem | head -1
# 输出类似 9a5ba575

# 2. 改名并推入系统证书目录
adb root
adb remount
adb push cacert.pem /system/etc/security/cacerts/9a5ba575.0
adb shell chmod 644 /system/etc/security/cacerts/9a5ba575.0
adb reboot

Android 10+ 分区只读,需要 adb remount 或 Magisk 模块(如 MagiskTrustUserCerts)把用户证书挂进系统目录。

4.2 方案二:改 App 的 network security config(需可重打包)

res/xml/network_security_config.xml:

<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system" />
            <certificates src="user" />
        </trust-anchors>
    </base-config>
</network-security-config>

重打包后用 apksigner 重签。适合自有 App 的安全测试,不适合第三方。

4.3 方案三:Frida 绕过 SSL Pinning

Java.perform(function () {
    var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
    var SSLContext = Java.use('javax.net.ssl.SSLContext');

    var TrustAll = Java.registerClass({
        name: 'com.qalab.TrustAll',
        implements: [X509TrustManager],
        methods: {
            checkClientTrusted: function (chain, authType) {},
            checkServerTrusted: function (chain, authType) {},
            getAcceptedIssuers: function () { return []; }
        }
    });

    var init = SSLContext.init.overload(
        '[Ljavax.net.ssl.KeyManager;',
        '[Ljavax.net.ssl.TrustManager;',
        'java.security.SecureRandom');
    init.implementation = function (km, tm, sr) {
        init.call(this, km, [TrustAll.$new()], sr);
    };

    // OkHttp 证书固定(3.x / 4.x 方法名不同)
    try {
        var Pinner = Java.use('okhttp3.CertificatePinner');
        Pinner.check.overload('java.lang.String', 'java.util.List')
            .implementation = function () {};
        Pinner.check$okhttp.overload('java.lang.String', 'kotlin.jvm.functions.Function0')
            .implementation = function () {};
    } catch (e) { console.log('CertificatePinner not found: ' + e); }
});

启动:frida -U -f com.target.app -l unpin.js --no-pause

排错:

  • Failed to spawn: unable to find process → 包名错,用 frida-ps -U 查。
  • java.lang.ClassNotFoundException → 加固/混淆导致类名不同,需要先脱壳。
  • 仍然抓不到 → 可能用了 Cronet/QUIC 或双向证书(mTLS),看客户端是否要求客户端证书。

五、批量:Intruder 与 Turbo Intruder

5.1 Intruder 四种模式

模式 语义 典型场景
Sniper 一个 payload 集,逐个位置替换 单参数 fuzz
Battering ram 所有位置用同一个值 同名参数、批量 ID
Pitchfork 多个 payload 集并行对齐 账号密码、ID+token 对
Cluster bomb 多集合笛卡尔积 用户名 × 密码

实战配置要点:

  • Payload 位置用 § 标记,JSON 里注意别把引号也框进去。
  • Resource Pool 限制并发(如 10 线程、100ms 间隔),避免把测试环境打挂——压测和生产事故往往就出在这一步。
  • Grep - Match 加成功关键字("code":0、success),比看长度准。
  • 结果列排序:先按 Status,再按 Length,最后看 Time(盲注/延时注入靠 Time 排序)。

社区版 Intruder 有人为速率限制,批量任务会很慢;有授权的大批量测试建议用 Pro 或 Turbo Intruder。

5.2 Turbo Intruder:高并发与竞态

def queueRequests(target, wordlists):
    engine = RequestEngine(endpoint=target.endpoint,
                           concurrentConnections=20,
                           requestsPerConnection=100,
                           pipeline=False)
    # 竞态测试:同一秒内发出 50 个"使用优惠券"请求
    for i in range(50):
        engine.queue(target.req, gate='race1')
    engine.openGate('race1')

def handleResponse(req, interesting):
    table.add(req)

gate 是关键:它把所有请求先积压在客户端,openGate 时一次性放出,这才是真正的并发,而不是"循环发 50 次"。

竞态类漏洞的判定:

  • 优惠券被用 2 次以上
  • 余额扣减后为负
  • 同一手机号注册出两个账号
  • 提现额度超过上限

六、越权:Autorize 的正确用法

  1. Burp 装 Autorize(BApp Store)。
  2. 在 Autorize 面板填入低权限账号的 Cookie/Header(Detector)。
  3. 用高权限账号正常浏览一遍所有功能。
  4. Autorize 自动用低权限凭证重放每个请求,并三色标记:
颜色 含义 说明
绿色 被拦截 返回 401/403 或跳登录,正常
红色 绕过成功 返回 200 且内容与高权限一致 → 越权
黄色 需人工确认 返回 200 但内容不同,可能是空列表

黄色最容易漏判。判断方法:对比"低权限返回的 JSON 里是否有真实业务数据"。空数组 {"data":[]} 通常是正常;{"data":[{"phone":"138..."}]} 就是越权。

七、盲打:Collaborator 与 DNSLog

没有回显的 SSRF、盲注、XXE、命令注入,都要靠带外通道确认。

  1. Burp Pro 右键 → Insert Collaborator payload,拿到唯一子域名。
  2. 把子域名塞进参数:url=http://xxxx.oastify.com、file=http://xxxx.oastify.com/a.dtd。
  3. 在 Collaborator 面板轮询 DNS/HTTP 交互。

自建替代方案:

# 用 interactsh 自建带外平台
interactsh-client -v
# 输出形如 c1a2b3.oast.pro,把它作为 payload 域名

判定注意:DNS 有解析 ≠ 漏洞成立。有些环境会对所有域名做预解析。要看 HTTP 请求是否真的到达,以及请求里的 UA、路径是否与你的 payload 一致。

八、扫描:能自动化的与不能自动化的

  • 主动扫描(Pro):爬虫 + 被动/主动检测。扫描前务必确认 Scope,否则会扫到第三方 CDN、支付回调域名,直接违反授权范围。
  • 被动扫描:只分析已抓流量,风险低,适合生产环境只读测试。
  • 扫描结果必须手工复验:误报率高,尤其是 XSS 和 CSRF。复验标准是"能给出可复现的最小请求"。

扫描时的频率控制:

Settings → Scan → Resource Pool: 最大并发 5,请求间隔 200ms

九、保存与复盘

  • Save project file:.burp 项目文件保存全部 history、Repeater 标签、扫描结果。报告取证时这是原始证据。
  • 大量流量时 Burp 会吃内存,改 BurpSuitePro.vmoptions:
-Xmx4g
-XX:+UseG1GC
  • 导出报告后,把关键请求以 curl 形式附在报告里,方便研发复现:
# Burp 右键 → Copy as curl command
curl -i -s -k -X POST 'https://api.target.com/api/order/detail' \
  -H 'Authorization: Bearer xxx' -H 'Content-Type: application/json' \
  --data-raw '{"orderId":10087}'

十、纪律

  • 只在授权域名与授权时间内测试。
  • 不批量下载真实用户数据;验证越权时取一条、截断、立即停止。
  • 不上传 webshell 到生产;必须验证时用无害文件(<?php echo "qalab";?>)并立即删除。
  • 不运行破坏性扫描(如 SQLMap 的 --risk=3、目录爆破的高并发)。
  • 所有测试文件、测试账号、测试订单在结束后清理,并在报告里列出清理记录。

相关阅读