想写一个burpsuite插件,看到burpsuite更新了最新的api,首先通过学习官网的github示例学习下api功能使用https://github.com/PortSwigger/burp-extensions-montoya-api-examples
Hello World 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package example.helloworld;import burp.api.montoya.BurpExtension;import burp.api.montoya.MontoyaApi;import burp.api.montoya.logging.Logging;public class HelloWorld implements BurpExtension { @Override public void initialize (MontoyaApi api) { api.extension().setName("Hello world extension" ); Logging logging = api.logging(); logging.logToOutput("Hello output." ); logging.logToError("Hello error." ); logging.raiseInfoEvent("Hello info event." ); logging.raiseDebugEvent("Hello debug event." ); logging.raiseErrorEvent("Hello error event." ); logging.raiseCriticalEvent("Hello critical event." ); throw new RuntimeException ("Hello exception." ); } }
上面代码的logging是输出在这里的: 可以用来输出自动化扫描后的结果
HTTP Handler Example Extension 它注册一个 HTTP 处理程序 对于传出请求消息: 如果请求是请求:POST 请求正文将记录到 output 将向请求添加注释 将 URL 参数添加到请求中 对于传入的响应消息: 如果相应的请求包含标头,则会添加高亮显示Content-LengthBLUE
MyHttpHandler.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 import burp.api.montoya.MontoyaApi;import burp.api.montoya.core.Annotations;import burp.api.montoya.core.HighlightColor;import burp.api.montoya.http.handler.*;import burp.api.montoya.http.message.requests.HttpRequest;import burp.api.montoya.logging.Logging;import static burp.api.montoya.http.handler.RequestToBeSentAction.continueWith;import static burp.api.montoya.http.handler.ResponseReceivedAction.continueWith;import static burp.api.montoya.http.message.params.HttpParameter.urlParameter;class MyHttpHandler implements HttpHandler { private final Logging logging; public MyHttpHandler (MontoyaApi api) { this .logging = api.logging(); } @Override public RequestToBeSentAction handleHttpRequestToBeSent (HttpRequestToBeSent requestToBeSent) { Annotations annotations = requestToBeSent.annotations(); if (isPost(requestToBeSent)) { annotations = annotations.withNotes("Request was a post" ); logging.logToOutput(requestToBeSent.bodyToString()); } HttpRequest modifiedRequest = requestToBeSent.withAddedParameters(urlParameter("foo" , "bar" )); return continueWith(modifiedRequest, annotations); } @Override public ResponseReceivedAction handleHttpResponseReceived (HttpResponseReceived responseReceived) { Annotations annotations = responseReceived.annotations(); if (responseHasContentLengthHeader(responseReceived)) { annotations = annotations.withHighlightColor(HighlightColor.BLUE); } return continueWith(responseReceived, annotations); } private static boolean isPost (HttpRequestToBeSent httpRequestToBeSent) { return httpRequestToBeSent.method().equalsIgnoreCase("POST" ); } private static boolean responseHasContentLengthHeader (HttpResponseReceived httpResponseReceived) { return httpResponseReceived.initiatingRequest().headers().stream().anyMatch(header -> header.name().equalsIgnoreCase("Content-Length" )); } }
HttpHandlerExample.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import burp.api.montoya.BurpExtension;import burp.api.montoya.MontoyaApi;public class HttpHandlerExample implements BurpExtension { @Override public void initialize (MontoyaApi api) { api.extension().setName("HTTP Handler Example" ); api.http().registerHttpHandler(new MyHttpHandler (api)); } }
Proxy Handler Example Extension The extension works as follows:
It registers a Proxy handler
For outgoing request messages:
It drops all POST
requests
Requests with foo
in the URL are not intercepted
If the Content-Type
is JSON
, the request is highlighted RED
and Burp rules for Interception are followed
All other requests are intercepted
User modified requests are continued as normal
For incoming response messages:
All responses that contain the string username
are highlighted BLUE
All other responses follow Burp rules for Interception
ProxyHandlerExample.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import burp.api.montoya.BurpExtension;import burp.api.montoya.MontoyaApi;public class ProxyHandlerExample implements BurpExtension { @Override public void initialize (MontoyaApi api) { api.extension().setName("Proxy Handler Example" ); api.proxy().registerRequestHandler(new MyProxyHttpRequestHandler ()); api.proxy().registerResponseHandler(new MyProxyHttpResponseHandler ()); } }
MyProxyHttpResponseHandler.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import burp.api.montoya.proxy.http.InterceptedResponse;import burp.api.montoya.proxy.http.ProxyResponseHandler;import burp.api.montoya.proxy.http.ProxyResponseReceivedAction;import burp.api.montoya.proxy.http.ProxyResponseToBeSentAction;import static burp.api.montoya.core.HighlightColor.BLUE;class MyProxyHttpResponseHandler implements ProxyResponseHandler { @Override public ProxyResponseReceivedAction handleResponseReceived (InterceptedResponse interceptedResponse) { if (interceptedResponse.bodyToString().contains("username" )) { return ProxyResponseReceivedAction.continueWith(interceptedResponse, interceptedResponse.annotations().withHighlightColor(BLUE)); } return ProxyResponseReceivedAction.continueWith(interceptedResponse); } @Override public ProxyResponseToBeSentAction handleResponseToBeSent (InterceptedResponse interceptedResponse) { return ProxyResponseToBeSentAction.continueWith(interceptedResponse); } }
MyProxyHttpRequestHandler.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import burp.api.montoya.proxy.http.InterceptedRequest;import burp.api.montoya.proxy.http.ProxyRequestHandler;import burp.api.montoya.proxy.http.ProxyRequestReceivedAction;import burp.api.montoya.proxy.http.ProxyRequestToBeSentAction;import static burp.api.montoya.core.HighlightColor.RED;import static burp.api.montoya.http.message.ContentType.JSON;class MyProxyHttpRequestHandler implements ProxyRequestHandler { @Override public ProxyRequestReceivedAction handleRequestReceived (InterceptedRequest interceptedRequest) { if (interceptedRequest.method().equals("POST" )) { return ProxyRequestReceivedAction.drop(); } if (interceptedRequest.url().contains("foo" )) { return ProxyRequestReceivedAction.doNotIntercept(interceptedRequest); } if (interceptedRequest.contentType() == JSON) { return ProxyRequestReceivedAction.continueWith(interceptedRequest, interceptedRequest.annotations().withHighlightColor(RED)); } return ProxyRequestReceivedAction.intercept(interceptedRequest); } @Override public ProxyRequestToBeSentAction handleRequestToBeSent (InterceptedRequest interceptedRequest) { return ProxyRequestToBeSentAction.continueWith(interceptedRequest); } }
观察可以看到上面的代码似乎已经取代了我这里的拦截,因为即便是拦截关闭的话,也依旧是拦截状态
Event Listeners Example Extension This extension demonstrates how to register listeners for various runtime events:
HTTP requests and responses for all Burp tools.
HTTP messages intercepted by the Proxy.
Addition of new scan issues.
The extension being unloaded by the user.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 public class EventListeners implements BurpExtension { private Logging logging; @Override public void initialize (MontoyaApi api) { logging = api.logging(); Http http = api.http(); Proxy proxy = api.proxy(); Extension extension = api.extension(); Scanner scanner = api.scanner(); extension.setName("Event listeners" ); http.registerHttpHandler(new MyHttpHandler (api)); proxy.registerRequestHandler(new MyProxyRequestHandler (api)); proxy.registerResponseHandler(new MyProxyResponseHandler (api)); scanner.registerAuditIssueHandler(new MyAuditIssueListenerHandler ()); extension.registerUnloadingHandler(new MyExtensionUnloadHandler ()); } private class MyAuditIssueListenerHandler implements AuditIssueHandler { @Override public void handleNewAuditIssue (AuditIssue auditIssue) { logging.logToOutput("New scan issue: " + auditIssue.name()); } } private class MyExtensionUnloadHandler implements ExtensionUnloadingHandler { @Override public void extensionUnloaded () { logging.logToOutput("Extension was unloaded." ); } } } public class MyHttpHandler implements HttpHandler { private final Logging logging; public MyHttpHandler (MontoyaApi api) { logging = api.logging(); } @Override public RequestToBeSentAction handleHttpRequestToBeSent (HttpRequestToBeSent httpRequestToBeSent) { logging.logToOutput("HTTP request to " + httpRequestToBeSent.httpService() + " [" + httpRequestToBeSent.toolSource().toolType().toolName() + "]" ); return RequestToBeSentAction.continueWith(httpRequestToBeSent); } @Override public ResponseReceivedAction handleHttpResponseReceived (HttpResponseReceived httpResponseReceived) { logging.logToOutput("HTTP response from " + httpResponseReceived.initiatingRequest().httpService() + " [" + httpResponseReceived.toolSource().toolType().toolName() + "]" ); return ResponseReceivedAction.continueWith(httpResponseReceived); } } public class MyProxyRequestHandler implements ProxyRequestHandler { private final Logging logging; public MyProxyRequestHandler (MontoyaApi api) { logging = api.logging(); } @Override public ProxyRequestReceivedAction handleRequestReceived (InterceptedRequest interceptedRequest) { logging.logToOutput("Initial intercepted proxy request to " + interceptedRequest.httpService()); return ProxyRequestReceivedAction.continueWith(interceptedRequest); } @Override public ProxyRequestToBeSentAction handleRequestToBeSent (InterceptedRequest interceptedRequest) { logging.logToOutput("Final intercepted proxy request to " + interceptedRequest.httpService()); return ProxyRequestToBeSentAction.continueWith(interceptedRequest); } } public class MyProxyResponseHandler implements ProxyResponseHandler { private final Logging logging; public MyProxyResponseHandler (MontoyaApi api) { logging = api.logging(); } @Override public ProxyResponseReceivedAction handleResponseReceived (InterceptedResponse interceptedResponse) { logging.logToOutput("Initial intercepted proxy response from " + interceptedResponse.initiatingRequest().httpService()); return ProxyResponseReceivedAction.continueWith(interceptedResponse); } @Override public ProxyResponseToBeSentAction handleResponseToBeSent (InterceptedResponse interceptedResponse) { logging.logToOutput("Final intercepted proxy response from " + interceptedResponse.initiatingRequest().httpService()); return ProxyResponseToBeSentAction.continueWith(interceptedResponse); } }
Traffic Redirector Example Extension This extension demonstrates how to redirect outgoing HTTP requests from one host to another. This task might arise, for example, if you have mapped out an application which then moves to a different staging URL. By simply redirecting traffic to the new hostname, you can continue to drive your testing from the original site map.
The extension works as follows:
It registers an HTTP handler.
For outgoing request messages, it retrieves the HTTP service for the request.
If the HTTP service host matches the “from” host, builds an HTTP service using the “to” host, and other details unchanged.
It returns the HTTP request with the new HTTP service.
Note: The sample code uses “host1.example.org” and “host2.example.org” as the “from” and “to” hostnames. You should edit the code to use your own hostnames before using it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 public class TrafficRedirector implements BurpExtension { static final String HOST_FROM = "host1.example.org" ; static final String HOST_TO = "host2.example.org" ; @Override public void initialize (MontoyaApi api) { api.extension().setName("Traffic redirector" ); api.http().registerHttpHandler(new MyHttpHandler ()); } } import burp.api.montoya.http.HttpService;import burp.api.montoya.http.handler.*;import burp.api.montoya.http.message.requests.HttpRequest;import static burp.api.montoya.http.HttpService.httpService;import static burp.api.montoya.http.handler.RequestToBeSentAction.continueWith;public class MyHttpHandler implements HttpHandler { @Override public RequestToBeSentAction handleHttpRequestToBeSent (HttpRequestToBeSent httpRequestToBeSent) { HttpService service = httpRequestToBeSent.httpService(); if (TrafficRedirector.HOST_FROM.equalsIgnoreCase(service.host())) { HttpRequest updatedHttpServiceRequest = httpRequestToBeSent.withService(httpService(TrafficRedirector.HOST_TO, service.port(), service.secure())); HttpRequest updatedHostHeaderRequest = updatedHttpServiceRequest.withUpdatedHeader("Host" , TrafficRedirector.HOST_TO); return continueWith(updatedHostHeaderRequest); } return continueWith(httpRequestToBeSent); } @Override public ResponseReceivedAction handleHttpResponseReceived (HttpResponseReceived httpResponseReceived) { return ResponseReceivedAction.continueWith(httpResponseReceived); } }
Custom Logger Example Extension Adds a new tab to Burp’s UI and displays a log of HTTP traffic for all Burp tools.
This extension provides a suite-wide HTTP logger within the main Burp UI.
The extension uses the following techniques:
It creates a custom tab within the main Burp UI, in which to display logging user interface
It displays a table of items and a read-only editor for requests and responses within a splitpane
When an item passes through the HttpHandler, it gets added to the table
You can view the request and response for an item in the table by clicking on the relevant row
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 import burp.api.montoya.BurpExtension;import burp.api.montoya.MontoyaApi;import burp.api.montoya.http.handler.HttpResponseReceived;import burp.api.montoya.ui.UserInterface;import burp.api.montoya.ui.editor.HttpRequestEditor;import burp.api.montoya.ui.editor.HttpResponseEditor;import javax.swing.*;import java.awt.*;import static burp.api.montoya.ui.editor.EditorOptions.READ_ONLY;public class CustomLogger implements BurpExtension { private MontoyaApi api; @Override public void initialize (MontoyaApi api) { this .api = api; api.extension().setName("Custom logger" ); MyTableModel tableModel = new MyTableModel (); api.userInterface().registerSuiteTab("Custom logger" , constructLoggerTab(tableModel)); api.http().registerHttpHandler(new MyHttpHandler (tableModel)); } private Component constructLoggerTab (MyTableModel tableModel) { JSplitPane splitPane = new JSplitPane (JSplitPane.VERTICAL_SPLIT); JTabbedPane tabs = new JTabbedPane (); UserInterface userInterface = api.userInterface(); 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); JTable table = new JTable (tableModel) { @Override public void changeSelection (int rowIndex, int columnIndex, boolean toggle, boolean extend) { HttpResponseReceived responseReceived = tableModel.get(rowIndex); requestViewer.setRequest(responseReceived.initiatingRequest()); responseViewer.setResponse(responseReceived); super .changeSelection(rowIndex, columnIndex, toggle, extend); } }; JScrollPane scrollPane = new JScrollPane (table); splitPane.setLeftComponent(scrollPane); return splitPane; } } import burp.api.montoya.http.handler.*;public class MyHttpHandler implements HttpHandler { private final MyTableModel tableModel; public MyHttpHandler (MyTableModel tableModel) { this .tableModel = tableModel; } @Override public RequestToBeSentAction handleHttpRequestToBeSent (HttpRequestToBeSent requestToBeSent) { return RequestToBeSentAction.continueWith(requestToBeSent); } @Override public ResponseReceivedAction handleHttpResponseReceived (HttpResponseReceived responseReceived) { tableModel.add(responseReceived); return ResponseReceivedAction.continueWith(responseReceived); } } import burp.api.montoya.http.handler.HttpResponseReceived;import javax.swing.table.AbstractTableModel;import java.util.ArrayList;import java.util.List;public class MyTableModel extends AbstractTableModel { private final List<HttpResponseReceived> log; public MyTableModel () { this .log = new ArrayList <>(); } @Override public synchronized int getRowCount () { return log.size(); } @Override public int getColumnCount () { return 2 ; } @Override public String getColumnName (int column) { return switch (column) { case 0 -> "Tool" ; case 1 -> "URL" ; default -> "" ; }; } @Override public synchronized Object getValueAt (int rowIndex, int columnIndex) { HttpResponseReceived responseReceived = log.get(rowIndex); return switch (columnIndex) { case 0 -> responseReceived.toolSource().toolType(); case 1 -> responseReceived.initiatingRequest().url(); default -> "" ; }; } public synchronized void add (HttpResponseReceived responseReceived) { int index = log.size(); log.add(responseReceived); fireTableRowsInserted(index, index); } public synchronized HttpResponseReceived get (int rowIndex) { return log.get(rowIndex); } }
Custom Request Editor Tab Example Extension Adds a new tab to Burp’s HTTP message editor, in order to handle a data serialization format
This extension provides a new tab on the message editor for requests that contain a specified parameter.
The extension uses the following techniques:
It creates a custom request tab on the message editor, provided that the data
parameter is present
If it is appropriate, the editor is set to be read-only
The value of the data
parameter is deserialized (URL decoded, then Base64 decoded) and displayed in the custom tab
If the value of the data is modified, the content will be re-serialized (Base64 encoded then URL encoded) and updated in the HttpRequest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 import burp.api.montoya.MontoyaApi;import burp.api.montoya.ui.editor.extension.EditorCreationContext;import burp.api.montoya.ui.editor.extension.ExtensionProvidedHttpRequestEditor;import burp.api.montoya.ui.editor.extension.HttpRequestEditorProvider;class MyHttpRequestEditorProvider implements HttpRequestEditorProvider { private final MontoyaApi api; MyHttpRequestEditorProvider(MontoyaApi api) { this .api = api; } @Override public ExtensionProvidedHttpRequestEditor provideHttpRequestEditor (EditorCreationContext creationContext) { return new MyExtensionProvidedHttpRequestEditor (api, creationContext); } } import burp.api.montoya.MontoyaApi;import burp.api.montoya.core.ByteArray;import burp.api.montoya.http.message.HttpRequestResponse;import burp.api.montoya.http.message.params.HttpParameter;import burp.api.montoya.http.message.params.ParsedHttpParameter;import burp.api.montoya.http.message.requests.HttpRequest;import burp.api.montoya.ui.Selection;import burp.api.montoya.ui.editor.EditorOptions;import burp.api.montoya.ui.editor.RawEditor;import burp.api.montoya.ui.editor.extension.EditorCreationContext;import burp.api.montoya.ui.editor.extension.EditorMode;import burp.api.montoya.ui.editor.extension.ExtensionProvidedHttpRequestEditor;import burp.api.montoya.utilities.Base64EncodingOptions;import burp.api.montoya.utilities.Base64Utils;import burp.api.montoya.utilities.URLUtils;import java.awt.*;import java.util.Optional;import static burp.api.montoya.core.ByteArray.byteArray;class MyExtensionProvidedHttpRequestEditor implements ExtensionProvidedHttpRequestEditor { private final RawEditor requestEditor; private final Base64Utils base64Utils; private final URLUtils urlUtils; private HttpRequestResponse requestResponse; private final MontoyaApi api; private ParsedHttpParameter parsedHttpParameter; MyExtensionProvidedHttpRequestEditor(MontoyaApi api, EditorCreationContext creationContext) { this .api = api; base64Utils = api.utilities().base64Utils(); urlUtils = api.utilities().urlUtils(); if (creationContext.editorMode() == EditorMode.READ_ONLY) { requestEditor = api.userInterface().createRawEditor(EditorOptions.READ_ONLY); } else { requestEditor = api.userInterface().createRawEditor(); } } @Override public HttpRequest getRequest () { HttpRequest request; if (requestEditor.isModified()) { String base64Encoded = base64Utils.encodeToString(requestEditor.getContents(), Base64EncodingOptions.URL); String encodedData = urlUtils.encode(base64Encoded); request = requestResponse.request().withUpdatedParameters(HttpParameter.parameter(parsedHttpParameter.name(), encodedData, parsedHttpParameter.type())); } else { request = requestResponse.request(); } return request; } @Override public void setRequestResponse (HttpRequestResponse requestResponse) { this .requestResponse = requestResponse; String urlDecoded = urlUtils.decode(parsedHttpParameter.value()); ByteArray output; try { output = base64Utils.decode(urlDecoded); } catch (Exception e) { output = byteArray(urlDecoded); } this .requestEditor.setContents(output); } @Override public boolean isEnabledFor (HttpRequestResponse requestResponse) { Optional<ParsedHttpParameter> dataParam = requestResponse.request().parameters().stream() .filter(p -> p.name().equals("data" )).findFirst(); dataParam.ifPresent(httpParameter -> parsedHttpParameter = httpParameter); return dataParam.isPresent(); } @Override public String caption () { return "Serialized input" ; } @Override public Component uiComponent () { return requestEditor.uiComponent(); } @Override public Selection selectedData () { return requestEditor.selection().isPresent() ? requestEditor.selection().get() : null ; } @Override public boolean isModified () { return requestEditor.isModified(); } } import burp.api.montoya.BurpExtension; import burp.api.montoya.MontoyaApi; public class CustomRequestEditorTab implements BurpExtension { @Override public void initialize (MontoyaApi api) { api.extension().setName("Serialized input editor" ); api.userInterface().registerHttpRequestEditorProvider(new MyHttpRequestEditorProvider (api)); } }
上面的代码为含有参数data的请求新建了特殊的编辑器,可以对data参数进行配置修改
Custom Scan Checks Example Extension The sample extension demonstrates the following techniques:
Registering a custom AuditInsertionPointProvider
If the request contains the data
parameter, it will provide a custom AuditInsertionPoint
The custom AuditInsertionPoint
will perform the following:
Deserialize the data (URL decode and then Base64 decode)
Parse the location of the input=
string withing the decoded data
Split the data into a prefix, location to place the payload, and a suffix
When building the request with the appropriate payload, it will perform the following:
Build the raw data with the appropriate payload
Re-serialize the data (Base64 encode then URL encode)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 import burp.api.montoya.MontoyaApi; import burp.api.montoya.http.message.HttpRequestResponse; import burp.api.montoya.http.message.params.ParsedHttpParameter; import burp.api.montoya.scanner.audit.insertionpoint.AuditInsertionPoint; import burp.api.montoya.scanner.audit.insertionpoint.AuditInsertionPointProvider; import java.util.List; import static java.util.stream.Collectors.toList; class MyInsertionPointProvider implements AuditInsertionPointProvider { private final MontoyaApi api; MyInsertionPointProvider(MontoyaApi api) { this .api = api; } @Override public List<AuditInsertionPoint> provideInsertionPoints (HttpRequestResponse baseHttpRequestResponse) { List<ParsedHttpParameter> parameters = baseHttpRequestResponse.request().parameters(); return parameters.stream() .filter(p -> p.name().equals("data" )) .map(p -> new MyAuditInsertionPoint (api, baseHttpRequestResponse, p)) .collect(toList()); } } import burp.api.montoya.MontoyaApi;import burp.api.montoya.core.ByteArray;import burp.api.montoya.core.Range;import burp.api.montoya.http.message.HttpRequestResponse;import burp.api.montoya.http.message.params.HttpParameter;import burp.api.montoya.http.message.params.ParsedHttpParameter;import burp.api.montoya.http.message.requests.HttpRequest;import burp.api.montoya.scanner.audit.insertionpoint.AuditInsertionPoint;import burp.api.montoya.utilities.Utilities;import java.util.List;import static burp.api.montoya.http.message.params.HttpParameter.parameter;class MyAuditInsertionPoint implements AuditInsertionPoint { private final String insertionPointPrefix; private final String insertionPointSuffix; private final HttpRequestResponse requestResponse; private final ParsedHttpParameter parameter; private final String baseValue; private final Utilities utilities; MyAuditInsertionPoint(MontoyaApi api, HttpRequestResponse baseHttpRequestResponse, ParsedHttpParameter parameter) { this .requestResponse = baseHttpRequestResponse; this .parameter = parameter; this .utilities = api.utilities(); String paramValue = parameter.value(); String urlDecoded = utilities.urlUtils().decode(paramValue); ByteArray byteData = utilities.base64Utils().decode(urlDecoded); String data = byteData.toString(); int start = data.indexOf("input=" ) + 6 ; int end = data.indexOf("&" , start); if (end == -1 ) { end = data.length(); } baseValue = data.substring(start, end); insertionPointPrefix = data.substring(0 , start); insertionPointSuffix = data.substring(end); } @Override public String name () { return "Base64-wrapped input" ; } @Override public String baseValue () { return baseValue; } @Override public HttpRequest buildHttpRequestWithPayload (ByteArray payload) { String input = insertionPointPrefix + payload.toString() + insertionPointSuffix; String updatedParameterValue = utilities.urlUtils().encode(utilities.base64Utils().encodeToString(input)); HttpParameter updatedParameter = parameter(parameter.name(), updatedParameterValue, parameter.type()); return requestResponse.request().withUpdatedParameters(updatedParameter); } @Override public List<Range> issueHighlights (ByteArray payload) { return null ; } } import burp.api.montoya.BurpExtension;import burp.api.montoya.MontoyaApi;public class CustomScanInsertionPoints implements BurpExtension { @Override public void initialize (MontoyaApi api) { api.extension().setName("Custom scan insertion points" ); api.scanner().registerInsertionPointProvider(new MyInsertionPointProvider (api)); } }
上面这个示例不是很懂,也没找到对应的出发点