文章总结: 本文介绍BurpSuite的BChecks功能,这是一种基于YAML语法的轻量级扫描规则扩展方式,无需开发完整插件即可实现主动和被动扫描。通过SQL注入检测、盲注验证和SSRF利用Collaborator等实战案例演示BChecks的应用,同时指出其局限性如无法获取响应时间、操作字节数组等复杂场景仍需传统扩展实现。 综合评分: 85 文章分类: 渗透测试,WEB安全,安全工具,漏洞分析,红队
扩展Burp Suite的乐趣与收益——Montoya方式——第8部分:BChecks——快速扩展Active和Passive Scanner
幻泉之洲
2026年5月13日 13:04 北京
在小说阅读器读本章
去阅读
BChecks是Burp Suite去年推出的一种轻量级扫描规则扩展方式,用类似YAML的语言编写,无需开发完整扩展。本文通过SQL注入、盲注、SSRF等真实案例,带你快速上手BChecks,同时指出它的局限性:无法获取响应时间、不能操作字节数组,复杂场景还是得用传统扩展。
BChecks是什么?为什么还需要传统扩展?
前面两篇文章我们讲了怎么用Montoya API扩展Burp的Active和Passive Scanner,以及怎么在插件里用Collaborator。今天换个路子——BChecks。
BChecks是PortSwigger去年加进来的新功能,让你不用写插件就能给Scanner加检测规则。规则文件是.bcheck后缀,语法有点像YAML,写起来很快。但别以为它能包打天下。说实话,前两篇文章里我写的那些主动扫描检测规则,一个都没法用BChecks实现。为啥?因为BChecks目前拿不到响应时间(Part 6需要这个),也不能操作字节数组(Part 7构造payload需要)。所以它更适合那些简单的、基于字符串匹配或请求响应的检测。
先列几个有用的链接:
- BCheck定义参考(https://portswigger.net/burp/documentation/scanner/bchecks/bcheck-definition-reference):最权威的手册。
- BCheck示例(https://portswigger.net/burp/documentation/scanner/bchecks/worked-examples):PortSwigger官方示例。
- BCheck GitHub仓库(https://github.com/PortSwigger/BChecks):官方和社区贡献的规则,你也可以提交自己的。
环境搭建:一个带SQL注入的Flask应用
老规矩,先搭靶子。写个简单的Flask应用,暴露一个GET接口,直接拼接SQL查询,典型注入点。
import flask from flask import request import sqlite3
app = flask.Flask(__name__)
@app.route(‘/’, methods=[‘GET’]) def handle_request(): name = request.args.get(‘name’) if name: dbfile = ‘test.db’ con = sqlite3.connect(dbfile) cur = con.cursor() cur.execute(“SELECT * FROM items WHERE name='” + name + “‘;”) items = cur.fetchall(); con.close() return items; else: return “Missing parameters”;
app.run(host=”127.0.0.1″, port=5000, debug=True)
创建数据库并插入测试数据:
$ sqlite3 test.db SQLite version 3.46.0 2024-05-23 13:25:27 Enter “.help” for usage hints. sqlite> create table items(id int, name text, value int); sqlite> insert into items values(1,’spoon’,5); sqlite> insert into items values(2,’fork’,5); sqlite> insert into items values(3,’table’,500); sqlite> insert into items values(4,’tv’,200); sqlite> select * from items; 1|spoon|5 2|fork|5 3|table|500 4|tv|200 sqlite> .quit
启动Flask后用浏览器访问,加个单引号看看效果:
OK,确认注入存在。
BCheck入门:被动检测SQL错误
先翻翻官方文档的结构:metadata、control flow(核心是given…then块)、conditionals(if/then/else)、actions(发送请求、报告问题)、reserved variables(request、response等)、functions(字符串、正则、编码、哈希,还能生成Collaborator地址)、以及一些杂项。每个BCheck必须有且只有一个given…then块。
第一个规则很简单:被动检查响应里有没有SQL错误关键字。metadata部分:
metadata: language: v2-beta name: “SQL error” description: “Passive detection for SQL errors” author: “Federico Dotta” tags: “SQL injection”, “passive”, “SQL”
注意language目前必须是v2-beta。然后写given response then,因为我们只关心响应。
given response then
if {to_lower(latest.response.body)} matches “mysql|mariadb|sqlite|mssql|db2|pgsql|sql” then
report issue: name: “SQL exception – Potential SQL Injection” severity: info confidence: tentative detail: “The response body potentially includes a SQL exception. Check for SQL injections.” remediation: “Remove verbose errors and apply parameterized query to all SQL queries.” end if
这里用了to_lower函数把响应体转小写,再用正则匹配。如果命中,就报一个info级别的issue。用内置IDE测试一下:
工作正常。
主动检测:加单引号看反应
被动检测只能等错误出现,主动检测更激进——我们主动发送带payload的请求。这次改成given any insertion point,然后send payload append一个单引号。
metadata: language: v2-beta name: “SQL Injection” description: “Active detection of SQL Injection” author: “Federico Dotta” tags: “SQL injection”, “SQL”
given any insertion point then
send payload: appending: “‘”
if {to_lower(latest.response.body)} matches “mysql|mariadb|sqlite|mssql|db2|pgsql|sql” then
report issue: name: “SQL Injection” severity: high confidence: tentative detail: “The parameter seems to be vulnerable to SQL Injection” remediation: “Apply parameterized query to all SQL queries.” end if
这里注意:我们用了latest.response.body,因为新发了一个请求。base.response.body是原始响应的结果。如果扫到关键字就报high级别的issue。
能跑。
减少误报:用两个单引号做二次验证
上面那个规则误报率可能有点高——如果服务器本来就有“sql”这种单词在正常响应里,就会误报。我个人做渗透测试时,宁可多出几个假阳性,也不想漏掉任何一个漏洞。但有些场景下(比如自动化CI/CD管道),假阳性多了就烦了。所以可以优化一下:先发一个单引号,如果关键字命中,再发两个单引号。两个单引号在SQL里是转义后的单个引号,不会引发错误。如果第二次响应里没有关键字,那就更可能是真的SQL注入。
metadata: language: v2-beta name: “SQL Injection (less FP)” description: “Active detection of SQL Injection with less false positives” author: “Federico Dotta” tags: “SQL injection”, “SQL”
given any insertion point then
send payload: appending: “‘”
if {to_lower(latest.response.body)} matches “mysql|mariadb|sqlite|mssql|db2|pssql|sql” then
send payload: appending: “””
if not({to_lower(latest.response.body)} matches “mysql|mariadb|sqlite|mssql|db2|pssql|sql”) then
report issue: name: “SQL Injection (less FP)” severity: high confidence: firm detail: “The parameter seems to be vulnerable to SQL Injection” remediation: “Apply parameterized query to all SQL queries.” end if end if
这里用了not函数反转条件。如果单引号触发关键字,而双引号不触发,就报issue,confidence升级为firm。
盲SQL注入检测:布尔盲注
布尔盲注的关键是构造两个条件:一个永远为真,一个永远为假。通过比较响应体是否一致来判断。BCheck里可以用define块定义变量,避免硬编码。
metadata: language: v2-beta name: “Blind SQL Injection” description: “Active detection of blind SQL Injection” author: “Federico Dotta” tags: “SQL injection”, “blind”, “SQL”
define: blind_payload_true = “‘ AND ‘534’=’534” blind_payload_false = “‘ AND ‘534’=’535”
given any insertion point then
send payload called positive: appending: {blind_payload_true}
if {base.response.body} is {positive.response.body} then
send payload called negative: appending: {blind_payload_false}
if not({positive.response.body} is {negative.response.body}) then
report issue: name: “SQL Injection” severity: high confidence: firm detail: “The parameter seems to be vulnerable to SQL Injection (blind boolean based)” remediation: “Apply parameterized query to all SQL queries.” end if end if
这里用了send payload called给请求命名,方便后续比较。先发真条件,如果响应体和原始响应一样(说明真条件没破坏原有数据),再发假条件。如果假条件和真条件响应不一样,就报漏洞。注意:这个规则只适用于字符串类型的注入点,如果参数是数字,需要去掉单引号。
SSRF检测:用Collaborator捕获外联
最后玩个高级的——检测SSRF。先改一下Flask后端,加一个url参数,如果传了url,服务端会请求那个URL。
import flask from flask import request import sqlite3 import socket import requests
app = flask.Flask(__name__)
@app.route(‘/’, methods=[‘GET’]) def handle_request(): name = request.args.get(‘name’) url = request.args.get(‘url’) if name: … else: if url: r = requests.get(url = url) return r.text else: return “Missing parameters”;
app.run(host=”127.0.0.1″, port=5000, debug=True)
手动测试一下:从Burp的Collaborator标签生成一个地址,贴进去。
果然收到了交互。现在写BCheck:用generate_collaborator_address()生成地址,替换掉参数值,然后检查是否有HTTP交互。
metadata: language: v2-beta name: “SSRF” description: “Active detection of SSRF with Collaborator” author: “Federico Dotta” tags: “SSRF”, “Collaborator”, “External interaction”
given any insertion point then
send payload:
replacing: http://{generate\_collaborator\_address()}
if http interactions then
report issue: name: “SSRF (HTTP interaction)” severity: high confidence: firm detail: “The parameter is vulnerable to SSRF. An HTTP interaction has been received.” remediation: “Avoid contacting arbitrary URL supplied by user” end if
注意两点:用反引号拼接字符串,用generator_collaborator_address()。send payload用了replacing,因为要替换掉原参数值,而不是追加。然后检查http interactions条件。
效果不错。但有些场景下出站HTTP被防火墙拦截,只有DNS能出去。所以可以改进一下:先检查HTTP交互,如果没有,再检查DNS交互,降低漏洞等级。
metadata: language: v2-beta name: “SSRF (improved)” description: “Active detection of SSRF with Collaborator” author: “Federico Dotta” tags: “SSRF”, “Collaborator”, “External interaction”
given any insertion point then
send payload:
replacing: http://{generate\_collaborator\_address()}
if http interactions then
report issue: name: “SSRF” severity: high confidence: firm detail: “The parameter is vulnerable to SSRF. An HTTP interaction has been received.” remediation: “Avoid contacting arbitrary URL supplied by user” else if dns interactions then
report issue: name: “SSRF” severity: medium confidence: firm detail: “The parameter may be vulnerable to SSRF. Only DNS interaction has been received, maybe for egress filtering.” remediation: “Avoid contacting arbitrary URL supplied by user” end if
这样如果只有DNS交互,报medium级别,提醒可能被出站过滤了。
测试小技巧:用Burp Scanner单独跑BCheck
用内置IDE的“Run test”每次只能测试一个插入点,效率低。更聪明的方法是:在Burp Scanner里创建一个只跑BCheck的扫描配置,然后用Intruder的“Scan defined insertion point”功能只扫单个参数。参考Part 6里讲过这种方法。
渗透测试时也可以直接用这个配置扫全站,只跑BCheck规则,比完整的Burp扫描快很多。
总结
BChecks确实很香——写几行就能加一个扫描规则,适合那些简单的、基于字符串匹配或请求/响应对比的检测。但别指望它能替代完整扩展,它拿不到响应时间、操作不了字节数组,复杂逻辑还得老老实实写Java代码。
强烈建议去GitHub仓库看看社区贡献的BChecks,很多针对已知CVE的规则,Burp自带的主动检查里没有这些。
所有后端代码和插件代码都在我的GitHub仓库里:https://github.com/federicodotta/Burp-Suite-Extender-Montoya-Course。
参考资料
[1] https://hnsecurity.it/blog/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-8/
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:幻泉之洲 《扩展Burp Suite的乐趣与收益——Montoya方式——第8部分:BChecks——快速扩展Active和Passive Scanner》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论