Burp Suite User Forum

Create new post

Extensions Development: Burp hanging when modifying request in an extension

Eric | Last updated: Mar 14, 2023 09:01PM UTC

Greetings, I am using the HttpHandler example for the Montoya API located here: https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/httphandler/src/main/java/example/httphandler/MyHttpHandler.java I have modified the request with a regex to do a search and replace and then attempt to send that modified request, but the request is never sent from repeater, well it doesn't show up in logger and the send button remains greyed out. For what it's worth, the match and replace seems to work just fine. I dump the string to the console for review and I can't see anything obvious it wouldn't like. Note that I noticed there are separate methods for HttpRequest.httpRequest() and HttpRequest.http2Request() but neither of these seem to work. The reason I am using toString is that it seems the easiest way to parse the entire request with a reqex versus parsing every header, url parameter, and body. Am I missing something? The code is roughly below: import burp.api.montoya.MontoyaApi; import burp.api.montoya.core.Annotations; import burp.api.montoya.core.HighlightColor; import burp.api.montoya.http.HttpService; import burp.api.montoya.http.handler.*; import burp.api.montoya.http.message.HttpHeader; import burp.api.montoya.http.message.requests.HttpRequest; import burp.api.montoya.logging.Logging; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.List; import java.util.Arrays; import java.util.regex.Matcher; import java.util.regex.Pattern; 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; public class MyHttpHandler implements HttpHandler { private final MontoyaApi api; private final Logging logging; private final ReplacerTab tab; public MyHttpHandler(MontoyaApi api, ReplacerTab mainTab) { this.api = api; this.logging = api.logging(); this.tab = mainTab; } @Override public RequestToBeSentAction handleHttpRequestToBeSent(HttpRequestToBeSent requestToBeSent) { HttpRequest modifiedRequest = requestToBeSent; Annotations annotations = requestToBeSent.annotations(); try { String[] options = {"requests", "requests and responses"}; Boolean enabled = this.tab.getEnabledValue(); String intercept = this.tab.getInterceptValue().toLowerCase(); logging.logToOutput("tool: " + requestToBeSent.toolSource().toolType().toolName()); if (enabled && Arrays.asList(options).contains(intercept)) { ArrayList<String> enabledTools = this.tab.getEnabledTools(); String toolSource = requestToBeSent.toolSource().toolType().toolName(); if (enabledTools.contains(toolSource.toLowerCase())) { String matchRegex = this.tab.getMatchSearchValue(); String requestAsStr = requestToBeSent.toString(); Pattern matchPattern = Pattern.compile(matchRegex, Pattern.MULTILINE); Matcher matcher = matchPattern.matcher(requestAsStr); Boolean matched = matcher.find(); if (matched) { String matchedValue = matcher.group(0); logging.logToOutput("Matched: " + matchedValue); annotations = annotations.withNotes("Request was modified with Super Replacer"); String replacerValue = null; if (this.tab.getMatchReplaceRegexValue()) { String replaceRegex = this.tab.getMatchSearchValue(); Pattern replacePattern = Pattern.compile(matchRegex, Pattern.MULTILINE); Matcher replacer = matchPattern.matcher(requestAsStr); Boolean replacerFound = replacer.find(); if (replacerFound) { replacerValue = replacer.group(0); } } else { replacerValue = this.tab.getReplaceWithValue(); } logging.logToOutput("Replacer: " + replacerValue); if (!replacerValue.isEmpty()) { String replaceCount = this.tab.getReplaceCountValue(); if (replaceCount.equalsIgnoreCase("first")) { requestAsStr = matcher.replaceFirst(replacerValue); } else if (replaceCount.equalsIgnoreCase("all")) { requestAsStr = matcher.replaceAll(replacerValue); } logging.logToOutput("Replaced " + matchedValue + " with " + replacerValue); logging.logToOutput(requestAsStr); //Modify the request by adding url param. modifiedRequest = HttpRequest.httpRequest(requestAsStr); if(modifiedRequest.httpVersion().equalsIgnoreCase("http/2")) { logging.logToOutput("Request is HTTP/2, converting."); HttpService service = modifiedRequest.httpService(); List<HttpHeader> headers = modifiedRequest.headers(); String body = modifiedRequest.bodyToString(); modifiedRequest = HttpRequest.http2Request(service, headers, body); } } else { logging.logToOutput("Replacer does not have a value"); } } else { logging.logToOutput("Matcher failed: " + matchRegex); } } else { logging.logToOutput(toolSource + " is not enabled for this tab."); } } else { logging.logToOutput("Tab is disabled or not set to intercept requests"); } //Return the modified request to burp with updated annotations. } catch(Exception e) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); logging.logToError(sw.toString()); } return continueWith(modifiedRequest, annotations); } @Override public ResponseReceivedAction handleHttpResponseReceived(HttpResponseReceived responseReceived) { return continueWith(responseReceived); } }

Eric | Last updated: Mar 14, 2023 11:05PM UTC

Hello, I wanted to follow up with my own solution. I was not adding an HttpService to the request. Instead of: modifiedRequest = HttpRequest.httpRequest(requestAsStr); it should be: modifiedRequest = HttpRequest.httpRequest(messageToBeSent.httpService(), requestAsStr);

You must be an existing, logged-in customer to reply to a thread. Please email us for additional support.