关于 burpsuite-project-parser
用于搜索和提取 Burp Suite 项目文件数据的技能,适合分析 HTTP 流量与审计发现。它通过 Burp Suite Professional 和解析器扩展工作,并强调验证空结果以避免误报。
主要功能
- 01按正则搜索请求与响应数据
- 02提取审计发现及其严重性
- 03查看代理历史和站点地图
- 04限制输出并截断响应正文
- 05验证解析器扩展是否正常工作
适用场景
- 01查找特定响应头或正文模式
- 02筛选高严重性审计发现
- 03检查项目中的代理流量
- 04确认空搜索结果是否可信
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ trailofbits/ skills --skill burpsuite-project-parser安装后在 Claude Code 中输入/burpsuite-project-parser确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlassets/trail-of-bits-mark.svgscripts/burp-search.sh详细介绍
Burp 项目解析器
使用 burpsuite-project-file-parser 扩展搜索并提取 Burp Suite 项目文件中的数据。
适用场景
- 使用正则表达式搜索响应标头或正文
- 从 Burp 项目中提取安全审计发现
- 导出代理历史记录或站点地图数据
- 分析 Burp 项目文件中捕获的 HTTP 流量
前置条件
此技能将解析工作委托给 Burp Suite Professional——不会直接解析 .burp 文件。
必需项:
- Burp Suite Professional——必须已安装(portswigger.net)
- burpsuite-project-file-parser 扩展——提供 CLI 功能
安装扩展:
- 从 github.com/BuffaloWill/burpsuite-project-file-parser 下载
- 在 Burp Suite 中:Extender → Extensions → Add
- 选择下载的 JAR 文件
快速参考
使用包装脚本:
{baseDir}/scripts/burp-search.sh /path/to/project.burp [FLAGS]
该脚本使用环境变量以兼容不同平台:
BURP_JAVA:Java 可执行文件的路径BURP_JAR:burpsuite_pro.jar 的路径
请检查退出代码。输出为空并不代表结果正常。 Burp 会忽略无法识别的标志,因此如果没有解析器扩展,它会正常启动并丢弃查询——这看起来和搜索没有匹配项完全一样。
| 退出代码 | 含义 | 操作 |
|---|---|---|
| 0 | 已生成输出 | 继续 |
| 1 | 用法错误,或缺少文件、Java 或 JAR | 阅读提示信息;修正路径 |
| 3 | 完全没有输出 | 不要将此结果报告为“未找到任何内容”。 空结果集和未加载扩展在这里无法区分。运行下面的对照查询以判断两者 |
| 4 | 输出不是 JSON | 扩展未加载,且 Burp 忽略了这些标志。请先安装扩展,再相信任何结果 |
任何非 0 退出代码都意味着搜索结果未经验证;仅凭该结果声称“没有匹配的流量”,属于将假阴性报告为正常结果。
解决退出码 3:控制查询
退出码 3 是最常见的情况——大多数范围很窄的正则表达式确实不会匹配任何内容——因此需要你自己执行解决步骤。你可以使用 Bash 和 Read;Burp 在此处以无头模式运行,因此没有可打开的 Extensions 选项卡,也没有可供检查的 GUI。再次运行同一查询只会再次返回 3。
改为运行控制查询:使用一个足够宽泛的选择器,如果解析器正常工作,就必须返回行;查询针对同一个项目文件。使用子组件筛选器,而不是裸选择器——控制查询仍然是查询,以上规则同样适用。
{baseDir}/scripts/burp-search.sh project.burp proxyHistory.request.headers | head -c 2000
proxyHistory.request.headers 正是合适的控制查询,因为它范围广但有界:涵盖项目中的每条记录,每条记录不到 1KB。裸 proxyHistory 也能回答同一个问题,但上面禁止使用它是有原因的——一条包含正文的记录就可能有数 MB,而 head -n 1 并不能阻止这种情况,它会完整输出其中一条记录。
| 控制查询结果 | 含义 | 操作 |
|---|---|---|
| 标准输出中有行 | 解析器正常工作 | 范围更窄的查询确实没有匹配到任何内容。将此作为结果报告 |
| 再次退出码 3 | 没有返回任何内容 | 要么扩展未加载,要么此项目不包含代理历史。确认指定的是正确的项目文件且文件非空,然后请用户确认 Burp Suite → Extensions 中是否有 burpsuite-project-file-parser |
| 退出码 4 | Burp 已启动,但忽略了这些标志 | 扩展未加载。说明这一点;不要报告流量情况 |
在得出任何关于项目流量的结论之前,先运行控制查询。 假设扩展已加载,正是未经验证的空结果被误认为一切正常的原因;如果控制查询无法得出结论,请用户检查 GUI 也是合理的做法。不要猜测。
通过管道运行时,退出码不是你能读取的。 管道报告的是最后一个命令的状态,而这里几乎所有示例都以 | jq、| head 或 | wc -cl 结尾——因此 $? 是 head 的 0,而不是脚本返回的 3。有两种可靠的判断方式:
- 标准错误,无论是否使用管道,你都能看到。
Error: the parser produced no output.或Error: Burp produced output, but not one JSON object就是答案;没有此类信息块则表示运行正常。 set -o pipefail,在需要获取退出码本身时使用;或者读取${PIPESTATUS[0]}:
set -o pipefail
{baseDir}/scripts/burp-search.sh project.burp auditItems | jq -c 'select(.severity == "High")'
echo "exit: $?"
非 JSON 输出永远不会进入标准输出,因此下游的 grep 或 jq 不会匹配到 Burp 启动横幅并将其误认为数据。
设置说明请参阅平台配置。
子组件筛选器(请使用这些筛选器)
始终使用子组件筛选器,而不是完整转储。 完整的 proxyHistory 或 siteMap 可能返回数 GB 的数据。子组件筛选器只返回所需内容。
可用筛选器
| 筛选器 | 返回内容 | 典型大小 |
|---|---|---|
proxyHistory.request.headers | 仅请求行和标头 | 小(每条记录 < 1KB) |
proxyHistory.request.body | 仅请求正文 | 不定 |
proxyHistory.response.headers | 仅状态和标头 | 小(每条记录 < 1KB) |
proxyHistory.response.body | 响应正文 | 很大——请避免 |
siteMap.request.headers | 网站地图中的同类内容 | 小 |
siteMap.request.body | 不定 | |
siteMap.response.headers | 小 | |
siteMap.response.body | 很大——请避免 |
默认方法
从标头开始,而不是正文:
# GOOD - headers only, safe to retrieve
{baseDir}/scripts/burp-search.sh project.burp proxyHistory.request.headers | head -c 50000
{baseDir}/scripts/burp-search.sh project.burp proxyHistory.response.headers | head -c 50000
# BAD - full records include bodies, can be gigabytes
{baseDir}/scripts/burp-search.sh project.burp proxyHistory # NEVER DO THIS
只有在检查标头后,才针对特定 URL 获取正文,并且始终要截断:
# 1. First, find interesting URLs from headers
{baseDir}/scripts/burp-search.sh project.burp proxyHistory.response.headers | \
jq -r 'select(.headers | test("text/html")) | .url' | head -n 20
# 2. Then search bodies with targeted regex - MUST truncate body to 1000 chars
{baseDir}/scripts/burp-search.sh project.burp "responseBody='.*specific-pattern.*'" | \
head -n 10 | jq -c '.body = (.body[:1000] + "...[TRUNCATED]")'
硬性规则:超过 1000 个字符的正文内容绝不能进入上下文。 如果用户需要完整的正文内容,必须在 Burp Suite 的 UI 中查看。
正则表达式搜索操作
搜索响应标头
responseHeader='.*regex.*'
搜索所有响应标头。输出:{"url":"...", "header":"..."}
示例——查找服务器特征标识:
responseHeader='.*(nginx|Apache|Servlet).*' | head -c 50000
搜索响应正文
responseBody='.*regex.*'
必须:正文内容始终截断至最多 1000 个字符。 每个响应正文都可能有数 MB。
# REQUIRED format - always truncate .body field
{baseDir}/scripts/burp-search.sh project.burp "responseBody='.*<form.*action.*'" | \
head -n 10 | jq -c '.body = (.body[:1000] + "...[TRUNCATED]")'
切勿检索完整正文内容。 如果需要查看某个特定响应的更多内容,请让用户在 Burp Suite 的 UI 中打开它。
其他操作
提取审计项
auditItems
返回所有安全发现。输出包括:名称、严重性、置信度、主机、端口、协议、URL。
注意: 审计项很小(不包含正文),使用 head -n 100 检索是安全的。
导出代理历史记录(避免)
proxyHistory
切勿直接使用此命令。 请改用子组件筛选器:
proxyHistory.request.headersproxyHistory.response.headers
导出站点地图(避免)
siteMap
切勿直接使用此命令。 请改用子组件筛选器。
输出限制(必需)
重要:检索数据前始终先检查结果大小。 宽泛的搜索可能返回数千条记录,每条都可能有数 MB。这会导致上下文窗口溢出。
第 1 步:始终先检查大小
执行任何搜索前,检查记录数和字节数:
# Check record count AND total bytes - never skip this step
{baseDir}/scripts/burp-search.sh project.burp proxyHistory | wc -cl
{baseDir}/scripts/burp-search.sh project.burp "responseHeader='.*Server.*'" | wc -cl
{baseDir}/scripts/burp-search.sh project.burp auditItems | wc -cl
wc -cl 的输出显示:<bytes> <lines>(例如,524288 42 表示 42 条记录共 512KB)。
解读结果——两项指标都必须达标:
| 指标 | 安全 | 缩小搜索范围 | 过于宽泛 | 停止 |
|---|---|---|---|---|
| 行数 | < 50 | 50-200 | 200+ | 1000+ |
| 字节数 | < 50KB | 50-200KB | 200KB+ | 1MB+ |
单个 10MB 响应若位于一行中,会显示较高的字节数,但行数只有 1——字节数检查可以发现这种情况。
wc -cl 输出 0 0 并不代表可以据此采取行动的大小——脚本以状态码 3 退出,且未验证任何内容。管道会隐藏这一情况,因此请单独重新运行查询,并读取退出码,然后再得出项目中没有匹配流量的结论。
第 2 步:缩小宽泛搜索的范围
如果记录数或大小过高:
-
使用子组件筛选器(见上表):
# Instead of: proxyHistory (gigabytes) # Use: proxyHistory.request.headers (kilobytes) -
缩小正则表达式模式的范围:
# Too broad (matches everything): responseHeader='.*' # Better - target specific headers: responseHeader='.*X-Frame-Options.*' responseHeader='.*Content-Security-Policy.*' -
检索前使用 jq 进行筛选:
# Get only specific content types {baseDir}/scripts/burp-search.sh project.burp proxyHistory.response.headers | \ jq -c 'select(.url | test("/api/"))' | head -n 50
第 3 步:始终截断输出
即使缩小了搜索范围,也始终通过截断来限制输出:
# ALWAYS use head -c to limit total bytes (max 50KB)
{baseDir}/scripts/burp-search.sh project.burp proxyHistory.request.headers | head -c 50000
# For body searches, truncate each JSON object's body field:
{baseDir}/scripts/burp-search.sh project.burp "responseBody='pattern'" | \
head -n 20 | jq -c '.body = (.body | if length > 1000 then .[:1000] + "...[TRUNCATED]" else . end)'
# Limit both record count AND byte size:
{baseDir}/scripts/burp-search.sh project.burp auditItems | head -n 50 | head -c 50000
必须执行的硬性限制:
- 对所有输出使用
head -c 50000(最多 50KB) - 将
.body字段截断至 1000 个字符——必须执行,无例外jq -c '.body = (.body[:1000] + "...[TRUNCATED]")'
未经计数且未截断时,切勿运行以下命令:
proxyHistory/siteMap(完整导出——始终使用子组件筛选器)responseBody='...'搜索(正文可能各有数 MB)- 任何宽泛的正则表达式,例如
.*或.+
调查工作流
-
确定范围——你要查找什么?(特定漏洞类型、端点、标头模式)
-
先搜索审计项——从 Burp 的发现开始:
{baseDir}/scripts/burp-search.sh project.burp auditItems | jq 'select(.severity == "High")' -
检查置信度分数——筛选出可采取行动的发现:
... | jq 'select(.confidence == "Certain" or .confidence == "Firm")' -
提取受影响的 URL——了解攻击面:
... | jq -r '.url' | sort -u -
搜索原始流量以了解上下文——检查实际请求和响应:
{baseDir}/scripts/burp-search.sh project.burp "responseBody='pattern'" -
手动验证——Burp 的发现只是线索,并非证据。请逐项验证。
理解结果
严重性与置信度
Burp 会同时报告严重性(高/中/低)和置信度(确定/可信/暂定)。进行分类处理时两者都要参考:
| 组合 | 含义 |
|---|---|
| 高 + 确定 | 很可能是真实漏洞,应优先调查 |
| 高 + 暂定 | 通常是误报,报告前请先验证 |
| 中 + 可信 | 值得调查,可能需要手动验证 |
“高严重性、暂定置信度”的发现通常是误报。不要仅根据严重性报告发现。
代理历史记录不完整时
代理历史记录仅包含 Burp 捕获的内容。以下情况可能会导致流量缺失:
- 范围筛选器排除了域名
- 拦截设置丢弃了请求
- 浏览器流量未经过 Burp 代理
如果未找到预期流量,请检查原始项目中的 Burp 范围和代理设置。
HTTP 正文编码
响应正文可能采用 gzip 压缩、分块传输,或使用非 UTF-8 编码。适用于纯文本的正则表达式在编码后的响应中可能会悄然失效。如果搜索结果少于预期:
- 检查响应是否经过压缩
- 尝试更宽泛的模式,或先搜索标头
- 使用 Burp 的 UI 检查原始响应与渲染后的响应
应拒绝的自我安慰
导致遗漏漏洞或误报的常见捷径:
| 捷径 | 为什么不对 |
|---|---|
| “这个正则表达式看起来不错” | 先用样本数据验证——编码和转义可能导致悄然失效 |
| “严重性高 = 必须修复” | 也要查看置信度评分;Burp 会产生误报 |
| “所有审计项都相关” | 根据实际威胁模型进行筛选;并非每个发现都适用于每个应用 |
| “代理历史记录是完整的” | Burp 的范围/拦截设置可能会对其进行筛选;你只能看到 Burp 捕获的内容 |
| “Burp 发现了问题,所以它就是漏洞” | Burp 的发现需要手动验证——它们表示潜在问题,而非确凿证据 |
| “搜索没有返回结果,所以流量不存在” | 先检查退出码。退出码 3 表示脚本无法区分结果为空还是扩展程序未加载,退出码 4 表示查询根本没有运行。只有退出码 0 才能说明“未找到内容”是针对项目而言,而非工具本身 |
输出格式
所有输出均为 JSON,每行一个对象。通过 jq 格式化:
{baseDir}/scripts/burp-search.sh project.burp auditItems | jq .
使用 grep 筛选:
{baseDir}/scripts/burp-search.sh project.burp auditItems | grep -i "sql injection"
示例
搜索 CORS 标头(限制字节数):
{baseDir}/scripts/burp-search.sh project.burp "responseHeader='.*Access-Control.*'" | head -c 50000
获取所有高严重性发现(审计项很少,但仍需限制数量):
{baseDir}/scripts/burp-search.sh project.burp auditItems | jq -c 'select(.severity == "High")' | head -n 100
仅从代理历史记录中提取请求 URL:
{baseDir}/scripts/burp-search.sh project.burp proxyHistory.request.headers | jq -r '.request.url' | head -n 200
搜索响应正文(必须将正文截断为 1000 个字符):
{baseDir}/scripts/burp-search.sh project.burp "responseBody='.*password.*'" | \
head -n 10 | jq -c '.body = (.body[:1000] + "...[TRUNCATED]")'
平台配置
包装脚本需要两个环境变量,以定位 Burp Suite 捆绑的 Java 和 JAR 文件。
macOS
export BURP_JAVA="/Applications/Burp Suite Professional.app/Contents/Resources/jre.bundle/Contents/Home/bin/java"
export BURP_JAR="/Applications/Burp Suite Professional.app/Contents/Resources/app/burpsuite_pro.jar"
Windows
$env:BURP_JAVA = "C:\Program Files\BurpSuiteProfessional\jre\bin\java.exe"
$env:BURP_JAR = "C:\Program Files\BurpSuiteProfessional\burpsuite_pro.jar"
Linux
export BURP_JAVA="/opt/BurpSuiteProfessional/jre/bin/java"
export BURP_JAR="/opt/BurpSuiteProfessional/burpsuite_pro.jar"
将这些导出语句添加到 shell 配置文件(.bashrc、.zshrc 等),以便持久生效。
手动调用
如果不使用包装脚本,可直接调用:
"$BURP_JAVA" -jar -Djava.awt.headless=true "$BURP_JAR" \
--project-file=/path/to/project.burp [FLAGS]