Burp Suite User Forum

Create new post

Sending Request using Montoya API

DL | Last updated: Dec 27, 2023 05:14PM UTC

Hi Guys, Sending requests using the Montoya API based on examples is to use the following : ``` api.http().sendRequest(request2Send) ``` However, when I attempted to send a request, I get the following error ``` java.lang.RuntimeException: Extensions should not make HTTP requests in the Swing event dispatch thread ``` My code is as follows ``` for (int k = 0; k< numRow; k++) { HttpRequest request2Send = HttpRequest.httpRequest(textBoxRequest); try { HttpRequestResponse response2receive = api.http().sendRequest(request2Send); textBoxResponse.setResponse(k, response2receive.response().toString()); } catch(Exception e) {tableUserRoles.setResponse(k, e.toString());} } ``` I have tried creating a new thread like below and I still get an error: HttpService cannot be null. ``` for (int k = 0; k < numRow; k++) { final int currentK = k; HttpRequest request2Send = HttpRequest.httpRequest(textBoxRequest); new Thread(() -> { try { HttpRequestResponse response2receive = api.http().sendRequest(request2Send); textBoxResponse.setResponse(currentK, response2receive.response().toString()); } catch (Exception e) { textBoxResponse.setResponse(currentK, e.toString()); } }).start(); } ``` Can anyone advise on what is the recommended way of sending a request in the above scenario? I have expended all the effort trying to read up documentation and I am unable to find out the reason why.

Dominyque, PortSwigger Agent | Last updated: Dec 28, 2023 09:55AM UTC

Hi Have you tried looking at our GitHub examples: https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/httphandler/src/main/java/example/httphandler/MyHttpHandler.java Please let me know if this is helpful

DL | Last updated: Dec 28, 2023 02:42PM UTC

Hi Dominyque, I have seen this example, but I do not know what it means. Do you mean that I will need to implement a HttpHandler class like the example? If so, how will this help send the request? I have created HttpRequest object using the HttpRequest.httpRequest(String) Method `HttpRequest request2Send = HttpRequest.httpRequest(textBoxRequest);` What I am trying to achieve here is that I have multiple textboxes of request. And I want to send them sequentially and receive their response. So far it has been, copy request from proxy to textbox[i] and the intention is that when I click the button to send request, it will sequentially send all requests and populate the response textbox.

DL | Last updated: Dec 28, 2023 02:48PM UTC

From the example you provided, it seem like it will help me abstract the HttpRequest building process, however, the main issue is on sending the request. I am unable to send the request because of the following error for the first set of code ``` java.lang.RuntimeException: Extensions should not make HTTP requests in the Swing event dispatch thread ``` Then if I create a new thread to send the request(2nd set of code), I will face the following error. ``` java.lang.IllegalArgumentException: HTTP service cannot be null ``` So what does it mean when HTTP service is null?

Hannah, PortSwigger Agent | Last updated: Jan 02, 2024 12:28PM UTC


We would recommend making the HTTP requests on a separate thread, as you have done. This is because issuing HTTP requests is a slow operation that would cause lockups in the UI if performed on the Swing thread.

When issuing requests, you need to provide both the raw data of the request, as well as an HttpService, so that Burp knows where to direct the raw request data to.

To resolve your "HTTP service cannot be null" message, please add a service to your HttpRequest.

For example:
HttpRequest request2Send = HttpRequest.httpRequest(HttpService.httpService("https://portswigger-labs.net"), textBoxRequest);
You could also do the following:
request2Send = request2Send.withService(HttpService.httpService("https://portswigger-labs.net"));

Please let me know how you get on.

DL | Last updated: Jan 06, 2024 03:28PM UTC

Hi Hannah, Happy New Year! Oddly here is a code that works without adding service. As far as I can understand from the API documentation, service is the "Host:" header? My HttpRequest objects will definitely have this, as I simply stored these objects as string to a JTable cell. When needed, I just convert them back to HttpRequest objects. <pre> List<HttpRequest> httpRequest2Send = new ArrayList<>(); for (int i = 0; i < numRow; i++) { HttpRequest manipulatedRequest = originalRequest; tableUserRoles.setRequest(i, ""); for (int j = 0; j < numHeader; j++) { if(tableUserRoles.getCellValue(i, j + numStaticColumn) != "") { HttpHeader header = HttpHeader.httpHeader(tableUserRoles.getCellValue(i, j + numStaticColumn)); manipulatedRequest = manipulatedRequest.withAddedHeader(header); } } tableUserRoles.setRequest(i, manipulatedRequest.toString()); httpRequest2Send.add(manipulatedRequest); } //Send Request and await response for each row List<HttpRequestResponse> httpRequestResponses = new ArrayList<>(); Thread sendRequestThread = new Thread(() -> {try { httpRequestResponses.addAll(api.http().sendRequests(httpRequest2Send)); } catch(Exception e) {api.logging().logToOutput(e.toString());} }); sendRequestThread.start(); try {sendRequestThread.join();} catch(Exception e) {api.logging().logToOutput(e.toString());} </pre> However, for some reason, I am facing this issue <code>HTTP service cannot be null issue</code>again. This is the code that is facing this issue. <pre> List<HttpRequest> httpRequest2Send = new ArrayList<>(); List<HttpRequestResponse> httpRequestResponses = new ArrayList<>(); for (int selectedRow : selectedRows) { for (int i = 1; i < userCount+1; i++) { int columnUser = (i*3)+1; String strHttpRequest = tableMatrixModel.getValueAt(selectedRow, columnUser).toString(); httpRequest2Send.add(HttpRequest.httpRequest(strHttpRequest)); } } //send request Thread sendRequestThread = new Thread(() -> {try { httpRequestResponses.addAll(api.http().sendRequests(httpRequest2Send)); } catch(Exception e) {api.logging().logToOutput(e.toString());} }); sendRequestThread.start(); try {sendRequestThread.join();} </pre> And just in case, yes I am sure that the request is correct, because I have tested printing the request out to another cell. The following is the request <pre> GET / HTTP/1.1 Host: example.com Sec-Ch-Ua: "Chromium";v="119", "Not?A_Brand";v="24" Sec-Ch-Ua-Mobile: ?0 Sec-Ch-Ua-Platform: "Linux" Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.123 Safari/537.36 Sec-Purpose: prefetch;prerender Purpose: prefetch Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Sec-Fetch-Site: none Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Accept-Encoding: gzip, deflate, br Accept-Language: en-GB,en-US;q=0.9,en;q=0.8 Priority: u=0, i Connection: close </pre> On the side note, how do you do code blocks here?

DL | Last updated: Jan 06, 2024 03:38PM UTC

The follwing is the error log java.lang.IllegalArgumentException: HTTP service cannot be null at burp.Zqif.ZA(Unknown Source) at burp.Zqif.sendRequest(Unknown Source) at burp.Zqif.sendRequest(Unknown Source) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at burp.Zji8.invoke(Unknown Source) at jdk.proxy2/jdk.proxy2.$Proxy26.sendRequest(Unknown Source) at burp.Zsuj.sendRequest(Unknown Source) at Extension.GUI_test.lambda$3(GUI_Matrix.java:196) at java.base/java.lang.Thread.run(Thread.java:840)

Hannah, PortSwigger Agent | Last updated: Jan 08, 2024 03:24PM UTC


For your code that works without setting the service, it looks like you're not creating the request from scratch, as you've used HttpRequest manipulatedRequest = originalRequest;
As you have a copy of the original request, which already has an HttpService associated with it, you are using that.

In the second example (with the error), you are creating a request from a raw String with no associated HttpService - HttpRequest.httpRequest(strHttpRequest)

The "Host" header is not used to determine the target/service - this is because you may want to try sending requests to a target with a manipulated Host header to see if you still receive a valid response.

It is not possible for regular users to format their posts with code blocks as we strip out that information from forum posts.

Please let me know if you have any further questions!

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