【Python+Java】Burpsuite插件开发

2023-05-09 11,413

如果你喜欢我的文章,欢迎关注公众号:安全女巫
转载请注明出处:
https://mp.weixin.qq.com/s/xEKSXm2-fCHhyvZxrQUQvQ

burpsuite 最新版下载地址:

关注公众号回复burpsuite

0x1 前言

官方只支持三种语言:Java, Python & Ruby

因Burpsuite使用Java编写,推荐使用java语言编写插件。若想用Python或Ruby,需使用借助JPython或JRuby,以达到使用Java调用Python或Ruby库的目的。

可根据实际情况进行插件编写。



0x2 Burp Api接口

保存所有接口到本地

0x3 Java插件编写

java环境准备

安装jdk

安装idea

idea创建web项目,可做了解  https://blog.csdn.net/justdoit_potato/article/details/82994046

代码编写

创建项目时,File-New-Project-选择jdk版本,点击下一步.

如此,便成功创建项目
将burp导出的API文件Burp文件夹,复制至新建项目src目录,便于后续调用与编写。
新建BurpExtender.java文件,内容如下:
package burp;

import java.io.PrintWriter;

public class BurpExtender implements IBurpExtender
{
   public void registerExtenderCallbacks (IBurpExtenderCallbacks callbacks)
   {
       // set our extension name
       callbacks.setExtensionName("Hello world extension");

       // obtain our output and error streams
       PrintWriter stdout = new PrintWriter(callbacks.getStdout(), true);
       PrintWriter stderr = new PrintWriter(callbacks.getStderr(), true);

       // write a message to our output stream
       stdout.println("Hello output");

       // write a message to our error stream
       stderr.println("Hello errors");

       // write a message to the Burp alerts tab
       callbacks.issueAlert("Hello alerts");

       // throw an exception that will appear in our error stream
       throw new RuntimeException("Hello exceptions");
   }
}

项目打包

File-Project Structure-Artifacts

plugin_jar为jar包目录

Build-Build Artifacts

成功打包为jar

Burp插件导入

插件编写信息,成功展示


Burp调试

以上为简单插件编写,仅为输出展示可不进行调试。若是进行复杂插件编写,必不可少,需idea调试burp插件。具体配置如下:
idea配置,监听8888端口

开启插件调试命令:

java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8888 --illegal-access=permit -Dfile.encoding=utf-8 -javaagent:BurpSuiteLoader_v2021.8.jar -noverify -jar burpsuite_pro_v2021.8.jar
进行部署
可见,运行时,jdk版本与burp运行时jdk版本不一致。需将idea中jdk修改
File->Project Settings
此处点击,设置断点
设置成功后点击进行debug模式
此时,将burp插件进行加载,可见调试输出信息

Tips

Burp sdk与Idea jdk版本需保持一致,否则Burp调试异常
Burp版本最好使用社区版本,否则Burp调试无法开启

文章中,原本使用的中文破解版Burp,jdk 1.8,因遇到以上2问题,更换Burp为burpsuite_pro_2021.8、jdk 11

0x4 Python插件编写

python环境准备

安装python2
设置jpython路径

代码编写

将burp导出的API文件Burp文件夹,复制至python脚本同级目录,便于后续调用与编写。
python脚本 hello.py
from burp import IBurpExtender
from java.io import PrintWriter
from java.lang import RuntimeException

class BurpExtender(IBurpExtender):  
   def registerExtenderCallbacks(self, callbacks):
       callbacks.setExtensionName("Hello world extension")
       stdout = PrintWriter(callbacks.getStdout(), True)
       stderr = PrintWriter(callbacks.getStderr(), True)
       stdout.println("Hello output")
       stderr.println("Hello errors")
       callbacks.issueAlert("Hello alerts")
       raise RuntimeException("Hello exception")

Burp插件导入

导入成功显示如下:




Burp调试

因Burp插件导入,只需写插件地址即可。若是地址py脚本内容变动,只需重新载入。正因为,

重新载入

点击反勾选按钮,再次点击进行勾选即可,可见更改已经生效。

其它样例

官方文档中提供了三种语言的插件简单样例,可根据自己需要选择。https://portswigger.net/burp/extender#SampleExtensions

下面简单描述下,样例的加载与代码分析

事件监听

下载Event listeners的python代码,可见registerExtenderCallbacks用于注册以下监听

监听到的内容该如何展示,又展示在哪块?
当扫描任务发现漏洞时,会展示在Output处
当插件进行反勾选时,Output输出扩展未加载

报文重定向

下载TrafficRedirector的python代码,可见registerExtenderCallbacks用于注册HTTP监听
进行代码分析
载入插件后,访问host为127.0.0.1的url,发现已重定向到host2.example.org

自动记录日志

Custom Logger用于添加新选项卡以记录所有请求和响应。
下载Custom Logger的python代码,可见registerExtenderCallbacks用于注册HTTP监听
from burp import IBurpExtender
from burp import ITab
from burp import IHttpListener
from burp import IMessageEditorController
from java.awt import Component;
from java.io import PrintWriter;
from java.util import ArrayList;
from java.util import List;
from javax.swing import JScrollPane;
from javax.swing import JSplitPane;
from javax.swing import JTabbedPane;
from javax.swing import JTable;
from javax.swing import SwingUtilities;
from javax.swing.table import AbstractTableModel;
from threading import Lock

class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel):
   

   def registerExtenderCallbacks(self, callbacks):
       self._callbacks = callbacks
       self._helpers = callbacks.getHelpers()
       callbacks.setExtensionName("Custom logger")
       self._log = ArrayList()
       self._lock = Lock()
       self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
       logTable = Table(self)
       scrollPane = JScrollPane(logTable)
       self._splitpane.setLeftComponent(scrollPane)
       tabs = JTabbedPane()
       self._requestViewer = callbacks.createMessageEditor(self, False)
       self._responseViewer = callbacks.createMessageEditor(self, False)
       tabs.addTab("Request", self._requestViewer.getComponent())
       tabs.addTab("Response", self._responseViewer.getComponent())
       self._splitpane.setRightComponent(tabs)
       callbacks.customizeUiComponent(self._splitpane)
       callbacks.customizeUiComponent(logTable)
       callbacks.customizeUiComponent(scrollPane)
       callbacks.customizeUiComponent(tabs)
       callbacks.addSuiteTab(self)
       callbacks.registerHttpListener(self)
       return
   
   def getTabCaption(self):
       return "Logger"
   
   def getUiComponent(self):
       return self._splitpane
   
   def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
       if messageIsRequest:
           return
       self._lock.acquire()
       row = self._log.size()
       self._log.add(LogEntry(toolFlag, self._callbacks.saveBuffersToTempFiles(messageInfo), self._helpers.analyzeRequest(messageInfo).getUrl()))
       self.fireTableRowsInserted(row, row)
       self._lock.release()
   def getRowCount(self):
       try:
           return self._log.size()
       except:
           return 0
   def getColumnCount(self):
       return 2
   def getColumnName(self, columnIndex):
       if columnIndex == 0:
           return "Tool"
       if columnIndex == 1:
           return "URL"
       return ""
   def getValueAt(self, rowIndex, columnIndex):
       logEntry = self._log.get(rowIndex)
       if columnIndex == 0:
           return self._callbacks.getToolName(logEntry._tool)
       if columnIndex == 1:
           return logEntry._url.toString()
       return ""
   def getHttpService(self):
       return self._currentlyDisplayedItem.getHttpService()
   def getRequest(self):
       return self._currentlyDisplayedItem.getRequest()
   def getResponse(self):
       return self._currentlyDisplayedItem.getResponse()

class Table(JTable):
   def init(self, extender):
       self._extender = extender
       self.setModel(extender)
   

   def changeSelection(self, row, col, toggle, extend):
       logEntry = self._extender._log.get(row)
       self._extender._requestViewer.setMessage(logEntry._requestResponse.getRequest(), True)
       self._extender._responseViewer.setMessage(logEntry._requestResponse.getResponse(), False)
       self._extender._currentlyDisplayedItem = logEntry._requestResponse      
       JTable.changeSelection(self, row, col, toggle, extend)

class LogEntry:
   def init(self, tool, requestResponse, url):
       self.tool = tool
       self.requestResponse = requestResponse
       self._url = url
代码分析:
目前仅对实例中4个进行代码分析,若后续自己有兴趣可参照写法进行插件编写~



本文作者:公众号:安全女巫

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/200103.html

Tags:
评论  (0)
快来写下你的想法吧!

公众号:安全女巫

文章数:15 积分: 0

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号