Burp Suite 实战:代理、重放与扫描¶
Burp 的真正价值不是"能抓包",而是把一次手工验证变成可复现的实验:改一个变量、发一次请求、对比响应。下面按"装好 → 抓到 → 改对 → 批量 → 复现"的顺序写,每一步都带真实报错和排查路径。
一、装好:证书是 80% 问题的根源¶
1.1 基本配置¶
- Proxy → Options → 新建 listener
127.0.0.1:8080(只绑本机,别开0.0.0.0)。 - 浏览器代理指向
127.0.0.1:8080,或者用 SwitchyOmega / FoxyProxy 做规则代理。 - 访问
http://burp,下载 CA Certificate(DER 格式)。 - 导入信任库。
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 的正确用法¶
- Burp 装 Autorize(BApp Store)。
- 在 Autorize 面板填入低权限账号的 Cookie/Header(Detector)。
- 用高权限账号正常浏览一遍所有功能。
- Autorize 自动用低权限凭证重放每个请求,并三色标记:
| 颜色 | 含义 | 说明 |
|---|---|---|
| 绿色 | 被拦截 | 返回 401/403 或跳登录,正常 |
| 红色 | 绕过成功 | 返回 200 且内容与高权限一致 → 越权 |
| 黄色 | 需人工确认 | 返回 200 但内容不同,可能是空列表 |
黄色最容易漏判。判断方法:对比"低权限返回的 JSON 里是否有真实业务数据"。空数组 {"data":[]} 通常是正常;{"data":[{"phone":"138..."}]} 就是越权。
七、盲打:Collaborator 与 DNSLog¶
没有回显的 SSRF、盲注、XXE、命令注入,都要靠带外通道确认。
- Burp Pro 右键 →
Insert Collaborator payload,拿到唯一子域名。 - 把子域名塞进参数:
url=http://xxxx.oastify.com、file=http://xxxx.oastify.com/a.dtd。 - 在 Collaborator 面板轮询 DNS/HTTP 交互。
自建替代方案:
判定注意:DNS 有解析 ≠ 漏洞成立。有些环境会对所有域名做预解析。要看 HTTP 请求是否真的到达,以及请求里的 UA、路径是否与你的 payload 一致。
八、扫描:能自动化的与不能自动化的¶
- 主动扫描(Pro):爬虫 + 被动/主动检测。扫描前务必确认 Scope,否则会扫到第三方 CDN、支付回调域名,直接违反授权范围。
- 被动扫描:只分析已抓流量,风险低,适合生产环境只读测试。
- 扫描结果必须手工复验:误报率高,尤其是 XSS 和 CSRF。复验标准是"能给出可复现的最小请求"。
扫描时的频率控制:
九、保存与复盘¶
- Save project file:
.burp项目文件保存全部 history、Repeater 标签、扫描结果。报告取证时这是原始证据。 - 大量流量时 Burp 会吃内存,改
BurpSuitePro.vmoptions:
- 导出报告后,把关键请求以
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、目录爆破的高并发)。 - 所有测试文件、测试账号、测试订单在结束后清理,并在报告里列出清理记录。