Burp Suite 里的 Intruder,我几乎每天都要碰。不管你是把一个登录接口丢进去做弱口令验证,还是想把某个业务参数遍历一遍看有没有越权,本质上都在用 Intruder 的同一套机制:手动标记位置、配置 payload 生成规则、批量发送、对比响应。但这个模块里最容易让人迷糊的,不是攻击类型,而是 Payload 类型那一长串选项。
我见过不少人,用了好几个月 Intruder,始终只在 Simple list 里导入字典,剩下那些 Custom iterator、Character blocks、Recursive grep 基本没碰过。这不怪大家,因为大多数人把 Intruder 当成“爆破工具”来用,没把它当成“请求生成引擎”来理解。这篇文章我就把 Intruder 里所有 Payload 类型完整拆一遍:底层在做什么、适合什么场景、参数怎么配、有哪些坑。最后用三个实战场景把完整配置过程走一遍。适合已经在用 Burp Suite 做接口测试和安全评估、但想真正吃透 Intruder 的朋友。
1. Intruder 的运作逻辑与 Payload 类型的选型思路
1.1 先说清楚 Intruder 到底在做什么
Intruder 本质上是一个“自动修改并重放请求”的工具。你在 Proxy 里抓到一条请求,把其中想要变化的部分标记成 §,比如登录接口里的用户名和密码,或者某个订单号。Intruder 就按你指定的规则,不断生成新值填进这些位置,发出去,然后把响应收回来给你对比。
这个定位很重要。很多人把 Intruder 当成“密码爆破器”,其实它做的事远不止这一件。它能做目录枚举、参数模糊测试、业务数据遍历、并发条件竞争、会话固定探测、甚至用 Null payloads 做定时重放。你理解得越深,越会发现它其实就是个可编程的 HTTP 客户端,只是 Burp 帮你把“生成请求”这件事做得非常顺。
理解了这个逻辑,再回头看 Payload 类型就轻松了。你标记的位置只是“洞”,Payload 类型决定的是“往洞里塞什么”。Simple list 是塞字典,Numbers 是塞递增序列,Custom iterator 是塞多组内容的组合。每一种类型都有自己的生成引擎,而不是简单地从某个文件里读字符串。
1.2 攻击类型是骨架,Payload 类型才是灵魂
在 Intruder 配置页,除了 Payload 类型,还有一个绕不开的选项叫攻击类型(Attack type)。攻击类型决定的是:当你标记了多个位置时,这些位置怎么共享 payload。它和 Payload 类型是两套东西,但很多人把两者混在一起理解,导致配置出来结果完全不对。
Burp 一共提供四种攻击类型:
- Sniper:同一时间只填充一个位置,用整个 payload 列表逐个跑。如果你标记了两个位置,它会先用 payload 列表跑第一个位置(第二个保持原始值),再用同一个列表跑第二个位置。效率最低,但匹配“一次只测一个变量”的场景。
- Battering ram:所有位置同时填同一个 payload。适合你想让两个参数保持一致的情况,比如参数名和参数值一样。
- Pitchfork:多个 payload 列表按索引并行。第一个请求用所有列表的第 1 个值,第二个请求用所有列表的第 2 个值,数量以最短列表为准。
- Cluster bomb:多个 payload 列表做笛卡尔积。比如用户名列表有 5 个、密码列表有 10 个,它会生成 50 个请求。这是最常用、也最容易把数量撑爆的攻击类型。
攻击类型只解决“怎么安排位置”,真正决定“生成什么内容的”还是 Payload 类型。比如说,你想做纯数字的验证码爆破,攻击类型选 Sniper,Payload 类型就必须选 Numbers 或者 Brute force,你选 Simple list 的话还得手工造一个数字字典。两者配合,才能把 Intruder 用明白。
1.3 Payload 类型怎么选:先想清楚你要“生成”什么
拿到一个测试目标时,第一件事不是打开 Intruder,而是先问自己:我要往这个位置塞什么规律的值?是固定字典、数字序列、字符组合,还是从上一次响应里提取的内容?想清楚这个,Payload 类型基本就定了。
下面这张表是我日常使用时的选型习惯,直接抄作业就可以:
| 测试需求 | 推荐 Payload 类型 | 推荐攻击类型 |
|---|---|---|
| 常规用户名字典测试 | Simple list | Sniper |
| 密码字典测试 | Simple list | Sniper |
| 用户名+密码组合测试 | Simple list(两组) | Cluster bomb |
| 遍历数字 ID 或订单号 | Numbers | Sniper |
| 生成“前缀+序号+后缀”格式 | Custom iterator | Sniper |
| 固定字符集的验证码爆破 | Brute force | Sniper |
| 构造超长输入做边界测试 | Character blocks | Sniper |
| 对字典做大小写变体 | Simple list + Case modification | Sniper |
| 从响应中提取动态 token 继续请求 | Recursive grep | Sniper |
| 测试会话保持/定时重放 | Null payloads | 任意 |
| 验证后端对畸形编码的处理 | Illegal Unicode | Sniper |
这张表的重点是,Payload 类型的选择一定建立在“你想生成什么数据形态”上,而不是“你有什么字典”。把字典文件导入 Simple list 是最简单的一步,但学会用 Numbers、Custom iterator、Recursive grep 这些类型,你的测试效率会明显提升。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 逐项拆解:所有内置 Payload 类型的使用要点
2.1 最常用也最容易忽略细节的三个:Simple list、Runtime file、Numbers
Simple list 是大多数人最早接触的类型。它维护一个字符串列表,可以手输、粘贴、从文件加载、也能从 Burp 内置的字典里选。这些内置字典内容很实用,比如常见用户名、密码、目录、文件名、Session ID 特征值等,测试时可以直接用。
有几个细节容易被忽略。第一个是“Remove duplicates”选项,默认没勾选。当你从多个文件合并字典时,重复项会真实地发出去,白白浪费请求量。第二个是文件编码。字典文件如果带 BOM,第一个 payload 可能混入不可见字符,后端接收后永远匹配不上。我习惯把字典文件统一转成 UTF-8 无 BOM 再导入。第三个是“从列表中添加”时,每行一个 payload,空行也会被当成空字符串发出去,有时候会触发非预期响应。
Runtime file 和 Simple list 从文件加载看起来很像,但机制完全不同。Runtime file 是在请求发送过程中实时读取文件内容,而不是在攻击开始时一次性读入。这意味着你可以一边跑 Intruder 一边改字典文件,保存后下一个请求就会用新内容。这个特性在前期调试时很香:先放 10 条数据试跑,看响应格式对不对,然后补充字典继续跑,不用重启任务。它的另一个优势是内存占用低,不需要把几十万条数据全部加载到内存。
Numbers 是纯数学生成器,参数包括起始值、结束值、步长、进制和位数。别小看这个类型,很多业务数据都是数字序列,比如订单号、用户 ID、流水号、时间戳。它有一堆小选项值得关注:Min digits 可以补零,比如 from=1、min digits=6 时会生成 000001;Max digits 可以限制长度;进制可以选十六进制,用来遍历某些小写十六进制编号。步长的作用也很大,想采样时把 step 设成 10 或 100,能快速摸清服务端对某个范围内的 ID 处理是否一致。
2.2 组合生成三兄弟:Custom iterator、Brute force、Character blocks
Custom iterator 是我最喜欢、但身边人用得最少的一个类型。它可以配置最多 8 个候选列表,输出是这些列表的笛卡尔积。打个比方,位置 1 放前缀 “api”,位置 2 放数字 1 到 10,位置 3 放后缀 “v1”,最终生成的 payload 就是 api01v1、api02v1 这种格式。
它真正厉害的地方是模拟真实业务里的编号规则。很多系统账号是“部门代号+序号”,比如 FIN0001、HR0002,这时候用 Simple list 手工造一堆组合太蠢,用 Custom iterator 把前缀列表、数字范围、后缀列表分别配好,几十万个组合几分钟就生成完。还有一个常见妙用:三组列表做笛卡尔积时,你可以随时看到底部总数量提示,避免请求量失控。
Brute force 是纯字符集组合生成器。参数很简单:字符集(比如数字、小写字母、自定义字符)、最小长度、最大长度。它生成的也是笛卡尔积,所以数量会指数增长。典型场景是 4 位纯数字验证码,字符集选数字,最小长度和最大长度都设 4,就是 0000 到 9999 共一万个请求。它和 Numbers 的区别是:Brute force 更自由,可以混合字母和数字;Numbers 更适合纯数字且带步长的情况。用 Brute force 时一定要设最大长度,我见过有人忘了设,结果从 1 位到 6 位全跑,直接把目标接口打成异常。
Character blocks 算是最被冷落的类型。它生成的是固定长度的字符块,有三个关键参数:块高度(每个 payload 占几行)、块长度(每行几个字符)、数据类型(随机字节还是指定字符集)。用途主要集中在模糊测试和边界测试。比如某个参数接收 JSON,你想验证超长字符串会不会导致解析异常,可以用 Character blocks 生成 100KB 的连续字符塞进去。这个类型不需要很精确,关键是能批量生成任意长度的畸形输入,比手工复制粘贴高效多了。
2.3 变换型 Payload:Case modification、Character substitution、Illegal Unicode
这三个类型的共同点是:它们不是凭空生成 payload,而是对已有列表做变换。Case modification 最简单,对 payload 做大小写处理,选项包括全小写、全大写、交替大小写、按单词首字母大写。用途很实际:有些接口的某些参数是大小写不敏感的,但日志、风控规则、CDN 缓存可能对大小写敏感。比如你拿 admin123 这个字典去测,可以同时跑 admin123、ADMIN123、Admin123 三个变体,观察服务端是否返回不同结果,从而判断后端的匹配逻辑。
Character substitution 是“字符替换”,配置多组替换规则,比如把 a 替换为 @、把 o 替换为 0。这是模拟真实用户设置弱口令习惯的有效手段。把 password 变形成 p@ssw0rd 并不只是好玩,很多真实环境里的账号确实就是这么设置的。配置时要注意替换规则的数量和组合,规则越多,生成的变体数量增长越快,结果集会迅速膨胀。我习惯先用一条规则小批量验证一下格式,再逐步增加规则。
Illegal Unicode 很多人没试过。它会把输入字符串编码成各种非标准 Unicode 表示形式。不要看到“非法”两个字就害怕,在处理用户输入的时候,后端解析器对畸形 Unicode 的处理差异经常会导致逻辑绕过或解析错误。比如某个接口对参数做了关键字过滤,但对某些特殊编码形式处理不严格,用 Illegal Unicode 生成的内容就可能绕过过滤到达业务层。这个类型对测试人员来说是个探路人而不是主武器,通常配合 Simple list 使用,重点看哪些畸形编码能被服务端接受。
2.4 动态 Payload:Recursive grep 与 Null payloads
Recursive grep 是这几个类型里功能最强大、也最不好上手的。它的机制是:从上一个响应里提取一段文本,把这段文本作为下一个请求的 payload。这样 Intruder 就不再是“死板地按列表生成值”,而是能够模拟真实的业务流转。
举个例子。某个业务接口会在响应中返回一个临时 token,下一次请求必须带上新 token。普通做法是你手工复制 token、进 Repeater 改请求、再发出去,慢得要命。用 Recursive grep 就可以把这个过程自动化:先在响应里选中 token 文本,在 Grep - Extract 中定义提取规则,然后在 Intruder 里标记 token 参数位置,Payload 类型选 Recursive grep。每次请求后 Burp 都从响应中提取新值填进下一次请求,循环往复。
配置 Recursive grep 有个比较隐蔽的门槛:你必须在第一次请求后从响应里选一段文本作为提取模板,而不是像配置正则一样直接写规则。选的时候要保证这段文本在后续响应中都有明确的边界和唯一性,否则提取不准确,整个循环就会中断或发错值。如果提取失败,Intruder 会停止当前线程,所以在正式跑之前,先用少量请求验证两三轮。
Null payloads 的功能简单,但用途很反直觉:它不生成任何实际内容,只是按固定次数或无限次发送原始请求。这对测试那些“只要请求到达就会被处理”的接口很有用。比如你想观察一个带状态变更的接口在连续访问下会不会出现幂等问题,或者想测接口在大量重放下是否产生重复订单。参数只有两个:Generate number of requests 和 Continue indefinitely。选固定次数时,你可以把它当定时器用;选无限时,适合做长时间挂机监控,但记得随时能手动停止。
2.5 加工环节:Payload processing rules 与 Payload encoding
如果说前面那些类型是“食材”,Payload processing rules 和 Payload encoding 就是“烹饪方式”。这两个不是独立的 payload 生成类型,而是挂在 Payload 列表下面的加工配置,但它们直接影响最终发出的请求长什么样,必须一起讲。
Payload processing rules 让你对每个 payload 执行一串规则,规则按添加顺序依次执行。常用规则包括 Add prefix、Add suffix、Encode、Hash、Regular expression replace、Skip etc。最典型的场景是密码 base64 传输:字典里放明文密码,添加一个 Encode -> Base64 规则,实际发出的请求就已经是 base64 后的内容了。另一个常见场景是给 payload 加前缀后缀:比如字典里放的是 ID 号,接口要求传 JSON 格式,可以加 Add prefix " 和 Add suffix ",把裸 ID 变成合法的 JSON 字符串。
这个环节最容易被忽略的是执行顺序。同一个 payload,如果先 Add suffix 再 URL encode,和先 URL encode 再 Add suffix,结果完全不同。前者是把“后缀字符”也一起编码了,后者是后缀字符保持原样。所以配置完以后,强烈建议先发一两个请求,到 Repeater 里看一眼最终发出去的包到底长什么样,再跑整体任务。
Payload encoding 在 Intruder 主配置页下方,默认 Burp 会对 payload 中的特殊字符做 URL 编码。这里有个常见的坑:很多 JSON 接口要求参数值里保留双引号和加号,如果你让 Burp 默认编码," 会变成 %22,+ 会变成 %2B,后端解析出来就不是你要的意思。解决办法是在 Payload encoding 里手动清理不需要编码的字符,或者干脆选 Don't URL-encode。另外,某些接口是后端自己先做一次 URL 解码再传给你处理,这时候你可能反而需要做双重 URL 编码,这个可以通过 processing rules 里的 URL encode 规则实现。
3. 实战配置:三个典型场景的完整过程
3.1 场景一:登录接口弱口令测试(Cluster bomb + Simple list)
假设你抓到了一个登录请求:
http复制POST /api/login HTTP/1.1
Host: target.example
Content-Type: application/json
{"username":"admin","password":"123456"}
先想清楚要测什么。这里有两个变量:用户名和密码,两个变量之间是组合关系,所以攻击类型选 Cluster bomb。标记位置时,把 username 的值和 password 的值分别标记,比如 {"username":"§admin§","password":"§123456§"}。
接下来配置两组 payload。Payload set 1 放用户名列表,最简单的方式是从 Burp 内置字典里选一份常见用户名,再手工加上 few 自定义项;Payload set 2 放密码列表,同样选择一份常见弱口令字典。这里有个建议:先把两组列表都精简到 10 条以内,跑一遍看响应格式和状态码是否符合预期,再放开到完整字典。否则一次性跑几万条请求,请求发出去后才发现接口参数格式不对,纯属浪费时间。
响应判断可以提前在 Options -> Grep - Match 里配置关键词,比如 success、token、failed、Invalid username 等。这样 Intruder 结果列表会自动把这些关键词在对应响应里是否出现标记出来,你只需要按关键词列快速过滤。我还会额外看响应长度,如果某个请求的响应长度明显比其他的长,八成是登录成功或者返回了不同的业务信息。当然,这只是弱口令测试的常规套路,务必确认你在授权范围内操作,别拿未授权的目标开刀。
3.2 场景二:遍历业务 ID 探测越权(Numbers + Sniper + Grep-Extract)
假设有一个查询用户详情的接口:
http复制GET /api/user/info?id=100001 HTTP/1.1
Host: target.example
Cookie: session=xxxxxxxx
你怀疑这个接口存在越权风险,id 参数可控。先把 id 的值标记为位置,攻击类型选 Sniper,Payload 类型选 Numbers。配置时从 100000、到 100200、步长 1。由于接口返回的 ID 是 6 位格式,把 Min digits 设为 6,这样发出的是 100001 而不是 1。
这个场景的关键在响应判断。直接在结果列表里看长度和状态码效率太低,建议在 Options -> Grep - Extract 里配置提取规则,把响应中的 user name、phone 等业务字段提取出来。跑完后在结果列表上方加一列 Extract 字段,你能直接看到每个 ID 返回了哪个用户的资料。如果发现多个不同的 id 都返回了敏感字段,而当前会话并不是管理员,这基本就坐实了越权问题。
跑这种遍历时还有两个点要注意。一是请求频率,ID 范围只有 200 个时可以忽略,但如果范围上万,一定要控制速度,最好建一个 Resource pool 设置最大并发,避免打爆目标接口。二是观察响应内容中是否包含“当前用户的权限标识”,如果所有请求都不带权限限制,这个接口就更危险了。测试完记得把数据整理清楚,方便后面写报告时引用具体请求和响应证据。
3.3 场景三:从响应中自动提取 token 持续跟进(Recursive grep)
这个场景模拟的是一个真实业务流。假设你访问了一个分页接口,响应里返回了下一页专用的 token:
json复制{
"data": {...},
"next_page_token": "a1b2c3d4e5"
}
下一次请求必须带上这个 token 才能拿到下一页数据。手工一页一页翻太累了,用 Recursive grep 让它自动翻页。
操作过程是这样:先在 Burp 里手动发一次正常请求,然后在响应里选中 a1b2c3d4e5 这段文本,右键选择 Add to grep - extract(不同版本菜单名称略有差异,本质是把这个文本作为提取模板保存下来)。接着在 Intruder 里打开这个请求,把 URL 中 token 参数的值标记成位置,例如 /api/page?token=§a1b2c3d4e5§。攻击类型选 Sniper,Payload 类型选 Recursive grep。
Burp 会先发一个初始请求,从响应中提取出 a1b2c3d4e5,把它作为第一个 paylaod 发送;再对下一个响应提取新的 token,作为第二个 payload。整个过程只要 token 不断返回,Intruder 就会一直翻页。如果某次响应里没有 token,提取会失败,线程会停下来,这时候你就要复查提取模板是否符合该页面的返回规律。这个功能在做长链路业务测试、爬取分页数据、重放需要动态会话参数的操作时,效率翻倍。
4. 常见问题与排查技巧实录
4.1 请求发不出、没有响应,先查这四件事
排在第一位的一定是请求本身能不能在 Repeater 里复现。如果同样的请求在 Repeater 里能正常响应,那问题出在 Intruder 配置;如果 Repeater 也失败,那就是抓包、会话、目标服务的问题。别在 Intruder 里反复调参数,先把基线确认了。
第二个常见原因是 Burp 的代理范围。Intruder 会把请求发送到目标服务器,但如果你所在网络需要走上游代理,或者目标只允许特定出口 IP,Intruder 里的请求可能因为没配 upstream proxy 而超时。这个配置在 User Options -> Connections 里,和浏览器代理配置是两套。第三个原因是 TLS 客户端证书,某些接口要求双向 TLS,Intruder 默认不加载客户端证书,需要去 Project Options -> TLS 里配置。第四个原因是 Burp 的 Session handling rules 把自己的请求拦截或修改了,尤其是你配了自动添加 header、自动替换 cookie 等规则时,会在 Intruder 场景下生效,导致请求内容走样。
排查时先看 Intruder 结果列表下方的 Errors 和 Status 列,Network error 会直接写原因。这个信息比盲目调参有用得多。
4.2 Payload 被 URL 编码或转义搞坏
这个坑我踩过很多次。最典型的就是参数值里的双引号,接口要求 JSON 格式,比如 {"keyword":"hello"},你标记 keyword 的值为 §hello§,然后 Burp 默认把某些字符做 URL 编码,最后发出的请求可能变成 {"keyword":"hello"} 本身没问题,但如果你字典里带双引号,双引号被编码成 %22,整个 JSON 就坏了。
解决办法无非两个方向:一个是把所有 payload 都提前处理好,保证字典里的内容就是接口期望的最终内容,然后在 Payload encoding 里选择 Don't URL-encode;另一个是让 processing rules 来负责编码,你控制得更精细。还有一个经常被忽略的点是 POST body 里的加号。application/x-www-form-urlencoded 的请求体里,加号会被服务端理解为空格。如果你的 payload 里有 base64 内容,里面大概率带加号,Burp 默认可能不编码它,你就得手动在 Payload encoding 里把加号加进需要编码的字符列表。
调完以后,第一时间到攻击日志或者 Repeater 里确认最终请求体,不要凭感觉认为配置对了。
4.3 速度、并发与资源池
Intruder 的默认并发行为经常被人吐槽慢。实际上它慢是有原因的,默认所有 Intruder 任务共享一个资源池,而且默认最大并发数很低,为了不影响 Burp 自身的其他操作。想提速的话,在 Intruder 的 Resource pool 标签里新建一个 pool,设置 Max concurrent requests,比如 10 或 20,请求速度会肉眼可见地提升。
但提速之前一定要想清楚后果。并发太高,轻则触发目标的风控策略,重则把测试环境打挂。我自己的习惯是:能跑 1 个并发就不跑 5 个,除非目标接口明确支持并发。还有一个容易被忽略的点:Resource pool 里可以设置 Delay between requests,相当于限速。做遍历或爆破时,如果你发现目标服务响应明显变慢,立即降低并发或加延时,别把测试做成事故。
4.4 结果太多,怎么快速定位有效请求
当一次任务跑了几万条请求,直接从结果列表里往下翻是灾难。这时要善用结果表上方的 Filter 栏和 Columns 配置。Filter 可以按状态码、响应长度范围、是否包含特定关键词来过滤。Columns 里可以勾选 Status、Length、Comment、Extract 字段等,用长度排序是最常用的手法——响应长度出现明显异常,往往代表业务逻辑不同。
我还会在跑大规模任务前,先在 Grep - Match 里配置几个关键词,比如 success、错误、warning、token 等,这样结果列表里直接显示这些关键词是否命中,一眼就能看出哪些请求值得人工复核。如果数据量实在太大,导出 CSV 后用脚本按响应长度聚类、按关键词过滤,比在 GUI 里点来点去高效得多。这个流程基本上是我做接口安全评估的标配:先小批量验证格式,再全量跑,最后按异常特征聚类分析。
最后说一个我自己的习惯。无论任务多急,Intruder 配置完成后我总会先跑 3 到 5 个请求做冒烟测试,特意看一眼最终发出的请求包和响应。这一步看起来费时间,实际上能帮你避免百分之八十的低级错误。Burp Intruder 的 Payload 类型虽然多,但核心逻辑就一句话:你想生成什么数据形态,就选对应的生成引擎;剩下的细节,都是在这个大方向上的打磨。
