一 概述
经常在渗透过程中,遇到一些要手动尝试的payload,比较麻烦,于是想学习一下burp插件的开发。2023年后Burp对插件的接口进行了更新,在网上看了很多开源插件都是基于旧版本api,并且网上没有特别详细的文章,对于初学者摸索很是头疼。
Burp Suite支持的插件类型有Java、Python、Ruby,我们选择最常见的Java来写(选择自己最熟悉的语言即可)
官方的api接口说明地址:
https://portswigger.github.io/burp-extensions-montoya-api/javadoc/index.html
二 官方实例
1 构建
官方提供了一个使用的案例:
https://github.com/PortSwigger/burp-extensions-montoya-api-examples/tree/main/customlogger
我们先使用这个案例看看
把这三个文件下载下来
然后IDEA新建一个项目,这边直接创建一个java普通项目即可,我的bp 2023.10用的是JDK 17
打开我们的burp,找到插件 APIs的位置,保存接口文件,导出到我们刚刚创建项目的src目录下
并且把刚刚官方的样例也放过来,结构如下:
然后在项目结构这边添加一个jar的工件,并且build一下,打包的jar就在out目录下
然后去Burp添加一下插件你就可以看到这样一个页面
并且我们随便抓两个包就可以看到
这个就是官方给出的一个简单的Demo,接下来我们分析一下这个demo做了什么
2 CustomLogger
首先看一眼官方文档,对于BurpExtension,所有的扩展都需要实现此接口,这个接口实际就是Burp插件启动的地方
并且这个接口需要重写一个initialize方法,这个方法会在加载扩展时调用。只有在此方法完成后,才会启用任何已注册的处理程序,这个initialize方法还接受一个MontoyaApi参数,Burp Suite使用此接口将一组方法传递给扩展,这些扩展可用于在Burp中执行各种操作,也就是说调用其他扩展是直接使用这个MontoyaApi。那么我们的主体部分就在initialize方法中实现,即官方代码这样:
下面是剩下几行的解释,其中tableModel 其实就是我们在插件中看到的上半部分,registerSuiteTab方法进行注册一个标签页,也就是建立UI视图,这个方法的第二个参数将在自定义选项卡中呈现的组件,示例代码中使用constructLoggerTab去创建一个组件
//设置插件的名称 api.extension().setName("Custom logger"); //用于管理表格数据 MyTableModel tableModel = new MyTableModel(); //方法向 Burp 的用户界面注册一个新的标签页 api.userInterface().registerSuiteTab("Custom logger", constructLoggerTab(tableModel)); //注册一个 HTTP 请求处理器,当 HTTP 请求和响应通过 Burp 时,MyHttpHandler 会调用其方法来处理数据 api.http().registerHttpHandler(new MyHttpHandler(tableModel));
下面的部分就是通过Swing UI的方式创建UI视图了,重要的是下面这段代码
//获取 Burp 提供的用户界面 API 对象,用于创建 UI 组件
UserInterface userInterface = api.userInterface(); //创建 HTTP 请求和响应编辑器 HttpRequestEditor requestViewer = userInterface.createHttpRequestEditor(READ_ONLY); HttpResponseEditor responseViewer = userInterface.createHttpResponseEditor(READ_ONLY); tabs.addTab("Request", requestViewer.uiComponent()); tabs.addTab("Response", responseViewer.uiComponent()); //将标签页添加到分隔面板 splitPane.setRightComponent(tabs); // table of log entries
//当用户在表格中选择某一行时,会触发这个方法,将对应信息填充到下方的请求响应视图 JTable table = new JTable(tableModel){ @Override public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) { // show the log entry for the selected row HttpResponseReceived responseReceived = tableModel.get(rowIndex); requestViewer.setRequest(responseReceived.initiatingRequest()); responseViewer.setResponse(responseReceived); super.changeSelection(rowIndex, columnIndex, toggle, extend); } };
这里的requestViewer和responseViewer就是视图UI下面的Request和Reponse那个,就是这个
3 MyTableModel
然后再来看一下MyTableModel,在上面的时候已经将这个MyTableModel创建出来并且放到了UI界面中,简单看一下这个里面的几个方法
这三个方法
分别对应于这个地方的Tool和URL,所以不难猜出,getColumnCount和getColumnName的返回值应该分别就是列的数量和上面的标签,而这个getValueAt其实就是每列下面要展示的值
4 MyHttpHandler
在MyHttpHandler中,重写两个方法,handleHttpRequestToBeSent和handleHttpResponseReceived,根据官方文档,这两个方法可以处理发送的请求和响应
并且在handleHttpResponseReceived中有这个一个玩意,做的其实就是把请求和响应数据添加到tableModel中(上面的每一行中)
tableModel.add(responseReceived);
三 其他API接口说明
这里再简单介绍几个其他API接口
1 logging()
我们在initialize()中添加这么两行,然后重build一下jar包,删除旧插件重新安装一下
api.logging().logToOutput("Hello World");
api.logging().logToError("Hello Error");
你将会看到
那么明了,这两个接口就是在Show in UI中输出信息,调试的时候用这个会很方便
2 HttpRequest
这里的话我们修改一下MyHttpHandler的构造方法,将最重要的MontoyaApi api也传进来
这里responseReceived接口中initiatingRequest()方法可以对根据这个请求获取到对应的方法,
然后我们可以使用api.http().sendRequest去发送请求
在httpRequest中可以看到很多对于请求进行修改的方法,这样我们可以对我们的请求进行修改,插入我们的payload之类
让AI提取的文档解释
boolean isInScope(); 功能:检查请求是否处于 Burp 的目标范围内。 使用场景:用于过滤或标记请求,以便用户专注于范围内的目标。 HttpService httpService(); 功能:返回请求的 HTTP 服务对象,包含目标主机、端口和协议信息等。 URL and Method Information String url(); 功能:返回请求的完整 URL。 可能异常:如果请求格式不正确,会抛出 MalformedRequestException。 String method(); 功能:返回请求的 HTTP 方法(如 GET、POST)。 可能异常:如果请求格式不正确,会抛出 MalformedRequestException。 String path(); 功能:返回请求路径,包括查询参数。 可能异常:如果请求格式不正确,会抛出 MalformedRequestException。 String pathWithoutQuery(); 功能:返回请求路径,不包含查询参数。 可能异常:如果请求格式不正确,会抛出 MalformedRequestException。 Content Type ContentType contentType(); 功能:返回请求的 Content-Type。 Parameters List<ParsedHttpParameter> parameters(); 功能:返回请求中的所有 HTTP 参数。 List<ParsedHttpParameter> parameters(HttpParameterType type); 功能:根据指定的参数类型过滤参数(如 URL 参数、POST 参数等)。 boolean hasParameters(); 功能:判断请求中是否有参数。 boolean hasParameters(HttpParameterType type); 功能:判断请求中是否有指定类型的参数。 ParsedHttpParameter parameter(String name, HttpParameterType type); 功能:返回与指定名称和类型的参数对应的 ParsedHttpParameter 对象,如果没有找到则返回 null。 String parameterValue(String name, HttpParameterType type); 功能:返回指定名称和类型的参数的值,如果没有找到则返回 null。 boolean hasParameter(String name, HttpParameterType type); 功能:检查是否存在具有指定名称和类型的参数。 boolean hasParameter(HttpParameter parameter); 功能:检查是否存在与提供的 HttpParameter 对象匹配的参数。 Headers boolean hasHeader(HttpHeader header); 功能:检查请求中是否包含指定的 HttpHeader。 boolean hasHeader(String name); 功能:检查请求中是否包含具有指定名称的头部。 boolean hasHeader(String name, String value); 功能:检查请求中是否包含具有指定名称和值的头部。 HttpHeader header(String name); 功能:返回具有指定名称的 HttpHeader 对象,如果没有找到则返回 null。 String headerValue(String name); 功能:返回具有指定名称的头部的值,如果没有找到则返回 null。 List<HttpHeader> headers(); 功能:返回请求中的所有 HTTP 头部。 HTTP Version String httpVersion(); 功能:返回 HTTP 请求或响应的版本字符串(如 "HTTP/1.1" 或 "HTTP/2")。 Body int bodyOffset(); 功能:返回请求体在消息中的偏移量。 ByteArray body(); 功能:返回请求体的字节数组。 String bodyToString(); 功能:返回请求体的字符串表示。 Markers List<Marker> markers(); 功能:返回请求中的标记列表。 Search and Contains boolean contains(String searchTerm, boolean caseSensitive); 功能:检查消息中是否包含指定的搜索字符串,可以选择是否区分大小写。 boolean contains(Pattern pattern); 功能:检查消息中是否包含符合指定正则表达式的部分。 General Message Information ByteArray toByteArray(); 功能:将整个 HTTP 请求消息转换为字节数组。 String toString(); 功能:返回 HTTP 请求的字符串表示。 Utilities HttpRequest copyToTempFile(); 功能:将 HttpRequest 对象复制到临时文件中,并返回新的 HttpRequest 对象。 HttpRequest withService(HttpService service); 功能:返回一个新的 HttpRequest,其中 HTTP 服务信息已更新。 HttpRequest withPath(String path); 功能:返回一个新的 HttpRequest,其中路径信息已更新。 HttpRequest withMethod(String method); 功能:返回一个新的 HttpRequest,其中 HTTP 方法已更新。 Header Manipulation HttpRequest withHeader(HttpHeader header); 功能:如果头部存在则更新,否则添加。 HttpRequest withHeader(String name, String value); 功能:如果头部存在则更新,否则添加。 HttpRequest withAddedHeader(String name, String value); 功能:添加新的 HTTP 头部。 HttpRequest withAddedHeader(HttpHeader header); 功能:添加新的 HTTP 头部。 HttpRequest withUpdatedHeader(String name, String value); 功能:更新具有指定名称的头部的值。 HttpRequest withUpdatedHeader(HttpHeader header); 功能:更新指定的头部。 HttpRequest withRemovedHeader(String name); 功能:移除具有指定名称的头部。 HttpRequest withRemovedHeader(HttpHeader header); 功能:移除指定的头部。 Body Manipulation HttpRequest withBody(String body); 功能:更新请求体的字符串内容。 HttpRequest withBody(ByteArray body); 功能:更新请求体的字节数组内容。 Parameter Manipulation HttpRequest withParameter(HttpParameter parameters); 功能:如果参数存在则更新,否则添加。 HttpRequest withAddedParameters(List<? extends HttpParameter> parameters); 功能:添加多个 HTTP 参数。 HttpRequest withAddedParameters(HttpParameter... parameters); 功能:添加多个 HTTP 参数。 HttpRequest withRemovedParameters(List<? extends HttpParameter> parameters); 功能:移除多个 HTTP 参数。 HttpRequest withRemovedParameters(HttpParameter... parameters); 功能:移除多个 HTTP 参数。 HttpRequest withUpdatedParameters(List<? extends HttpParameter> parameters); 功能:更新多个 HTTP 参数。 HttpRequest withUpdatedParameters(HttpParameter... parameters); 功能:更新多个 HTTP 参数。 Transformation HttpRequest withTransformationApplied(HttpTransformation transformation); 功能:应用指定的转换并返回新的 HttpRequest。 Default Headers HttpRequest withDefaultHeaders(); 功能:添加默认的 HTTP 头部。 Markers HttpRequest withMarkers(List<Marker> markers); 功能:返回一个新的 HttpRequest,其中标记已更新。 HttpRequest withMarkers(Marker... markers); 功能:返回一个新的 HttpRequest,其中标记已更新。 Static Methods static HttpRequest httpRequest(); 功能:创建一个新的空 HttpRequest 对象。 static HttpRequest httpRequest(ByteArray request); 功能:从字节数组创建 HttpRequest。 static HttpRequest httpRequest(String request); 功能:从字符串创建 HttpRequest。 static HttpRequest httpRequest(HttpService service, ByteArray request); 功能:从 HTTP 服务和字节数组创建 HttpRequest。 static HttpRequest httpRequest(HttpService service, String request); 功能:从 HTTP 服务和字符串创建 HttpRequest。 static HttpRequest httpRequestFromUrl(String url); 功能:从 URL 创建 HttpRequest。 static HttpRequest http2Request(HttpService service, List<HttpHeader> headers, ByteArray body); 功能:创建 HTTP/2 请求。 static HttpRequest http2Request(HttpService service, List<HttpHeader> headers, String body); 功能:创建 HTTP/2 请求。
比如我们可以通过下面这样修改请求路径为自定义的"/"+path,修改请求方法为GET(这里不能写Get,花了半天时间才发现的错误点,踩坑踩坑),并且修改请求的bady为空
httpRequest.withPath("/"+path).withMethod("GET").withBody("");
通过HttpRequest.withAddedHeader("X-Forwarded-For", "127.0.0.1")对请求添加一个请求头
3 HttpReponse
我们还需要根据返回包来判断我们的payload是否有效,HttpReponse下提供了对应的方法
比如可以通过httpResponse.statusCode()获取响应值,通过httpResponse.bodyToString().contains("Whitelabel Error Page")来判断是否包含特定的响应信息
4 DNS平台
创建一个collaboratorClient ,其实就相关与我们在Bp中使用collaborator点击Get Start
CollaboratorClient collaboratorClient = montoyaApi.collaborator().createClient();
generatePayload()获取一个dns域名
String dnsDomain = collaboratorClient.generatePayload().toString();
根据dns域名获取到对应的记录数组,如果数组不为空,那么可以判断该dns被请求(这里编写的时候,payload发起请求后,先暂停两秒,防止太快而获取不到解析记录)
List<Interaction> interactions = collaboratorClient.getInteractions(InteractionFilter.interactionPayloadFilter(dnsDomain));
5 其他
这里还有一个常用,下面的两句分别判断httpResponseReceived是否来自代理或者重放,这样可以过滤其他模块的请求,放在太多无用请求
httpResponseReceived.toolSource().isFromTool(ToolType.PROXY);
httpResponseReceived.toolSource().isFromTool(ToolType.REPEATER);
在写插件的过程中,我们还会遇到的是修改之后的请求如何添加到tableModel中,这里的解决方式是,我们自己包装一个方法,在HttpHandler类和tableModel中传递这个封装的方法,而非直接使用responseReceived
自己初步刚刚完成的小插件,恳请大佬指点
https://github.com/Jingyi-u/SimpleScan--Burp-/tree/1.0.0
推荐阅读
https://github.com/Maskhe/FastjsonScan
https://github.com/saoshao/DetSql
4A评测 - 免责申明
本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。
不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。
本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。
如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!
程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。
侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)