PortSwigger / burp-extensions-montoya-api

Burp Extensions Api
Other
139 stars 5 forks source link

I can't come up with a suitable example. #25

Closed Nzoth9 closed 1 year ago

Nzoth9 commented 1 year ago

Hi, Burp team! First of all, once again, congratulations on the montoya API release. 🎉(Burp you too!) Thanks to this, even beginners like me can easily implement the API.

What I want to implement is to reuse GET query parameters or POST data, convert it to JSON, and send the request again. I guess I'll have to tinker with handleHttpResponseReceived to implement this.

However, it seems that the new Montoya API doesn't have an object with a request and a response.(RequestResponse objects) and i don't even know how to trigger a new request. (I've asked the question before, is that still valid?)

Could you please give me a good example?

Thank you, dear team!

SeanBurnsUK commented 1 year ago

Which tool are you interacting with, Proxy? Or do you just want to send requests you make yourself from the extension?

to send a request from the extension you can use

api.http().sendRequest() functions.

eg.

HttpService myService = HttpService.httpService("localhost", 80, false);
HttpRequest myRequest = HttpRequest.httpRequest(myService, "GET / HTTP/1.0\r\n\r\n");
HttpRequestResponse requestResponse = api.http().sendRequest(myRequest);
System.out.println(requestResponse.statusCode());
Nzoth9 commented 1 year ago

Hi!, @SeanBurnsUK! Thank you for reply!

I have one more question, what should I do with a control that contains two objects with request and response data (for example, RequestResponse)?

In other words, can we use the object where the request and response are together (the request is end)?

Nzoth9 commented 1 year ago

Hello, @SeanBurnsUK? I was able to get the following code through the above and other examples.

@Override
     public ResponseReceivedAction handleHttpResponseReceived(HttpResponseReceived responseReceived) {
     ....
     this.logging.logToOutput("start!");
     this.logging.logToOutput("start2!");
     try {
           this.api.http().sendRequest(responseReceived.initiatingRequest());
           this.logging.logToOutput("start3!");
        } catch(Exception e) {
            this.logging.logToError(e.getMessage());
        }
        annotations = annotations.withHighlightColor(HighlightColor.BLUE);
        return continueWith(responseReceived, annotations);
}

However, no error occurs and logToOutput doesn't even run. And when I unload the extension, suddenly the code runs.

스크린샷 2023-01-19 오후 10 37 38

SendRequest works when I unload the extension What's going on? Thank you!

petrabrunner commented 1 year ago

Hi - just a few curious questions that might get you in the right direction of your problem (not sure):

the fact that it only starts running when you unload the plugin might indicate a problem with concurrency... not sure where though... you will have to debug that yourself.

Nzoth9 commented 1 year ago

Hi!, @petrabrunner! I have been eagerly waiting for a reply all day. Thanks for the reply, It seems there is something I am not thinking of.

This code is the code I wrote.

    @Override
    public ResponseReceivedAction handleHttpResponseReceived(HttpResponseReceived httpResponseReceived) {
        HttpService service = httpResponseReceived.initiatingRequest().httpService();
        HttpRequest request = HttpRequest.httpRequest(service, httpResponseReceived.initiatingRequest().toByteArray());

        this.api.logging().logToOutput("start request");
        HttpRequestResponse http = this.api.http().sendRequest(request);
        this.api.logging().logToOutput("create request");

        return ResponseReceivedAction.continueWith(httpResponseReceived);
    }

(This time, modified handleHttpResponseReceived of TraffitRedirect in API example.)

This code also outputs a log called 'create request' when only unloading. I also thought it was because of concurrency, but I don't know of a suitable example.

what could be the problem? I simply want to reuse the request used in the response and send it as JSON.

seanjburns commented 1 year ago

I am not sure what you are doing makes sense. Your code basically looks like a blocking infinite loop.

If you put logging into the request handler "handleHttpRequestToBeSent" it should hopefully show you what is going on. It should be printing that lots of requests are being sent.

api.http().sendRequest() is a blocking call waiting for a response, but you have put that code into the response handler (so no responses will ever get processed).

When the "last" request crashes because of stack overflow or an error of some sort, it will then return "no response" and the entire stack will then be processed, which is causing the behaviour you see when "unloading" your extension (because unloading stops more requests being sent, which mean the response can continue to be processed.

1: Burp sends a request (1) 2: Burp receives the response (1) 3: Your Handler gets the response (1) 4: Your Handler builds a new request (2) 5: Your Handler sends request (2) 6: Your Handler waits (blocks) for the response to (2)... (Notice how you have not told (1) to continue processing yet) 7: Burp sends a request (2) 8: Burp receives the response (2) 9: Your Handler gets the response (2) 10: Your Handler builds a request (3) 11: Your Handler sends request (3) 12: Your Handler waits (blocks) for the response to (3)... (Notice how you have not told (2) and hence (1) to continue processing) . . .

seanjburns commented 1 year ago

I also recommend attaching a debugger to burp so you can debug your code.

https://www.jetbrains.com/help/idea/attaching-to-local-process.html

Nzoth9 commented 1 year ago

Hi!, How are you? @seanjburns First of all, thanks to reply. 👍🏼

what i want to do is, reuse the request used in the response and make a new request. I still don't know why sendRequest isn't working. (Is there any way to check sendRequest internal source code?)

Isn't sendRequest a function that receives an HttpRequest as a parameter and issues a request? Obviously, I don't seem to have an understanding of the source code on proxy. (I'm sorry you must be busy.)

Nzoth9 commented 1 year ago

https://www.netspi.com/blog/technical/web-application-penetration-testing/debugging-burp-extensions/

Let's refer to this example. thank you. @seanjburns

Nzoth9 commented 1 year ago

@seanjburns! I didn't understand this a bit.

I think I understand a little bit what you mean by the phrase. I did the debugging as you said.

스크린샷 2023-01-20 오전 9 24 30

I think the api.http().sendRequest() line is executed, but the line below it is not executed.

  1. Can you tell us more about api.http().sendRequest()?
  2. How to create new request with request used in response?

thanks!

seanjburns commented 1 year ago

Line 73 sendRequest is working. It is waiting for a response, before it can goto line 74.

"Why" is it waiting for a response is because you have configured a response handler, so all responses to all requests have to go through the response handler and complete.

"Why" is it not completing is because your response handler is sending "another" request and waiting for its response, which must go through your handler.

This is causing an infinite loop.

seanjburns commented 1 year ago

If we go back to your original question

"What I want to implement is to reuse GET query parameters or POST data, convert it to JSON, and send the request again. I guess I'll have to tinker with handleHttpResponseReceived to implement this."

This is an example (not a good one, but its shows the concept) Notice how the IF breaks the infinite loop

    public ResponseReceivedAction handleHttpResponseReceived(HttpResponseReceived responseReceived) {
        HttpRequest originalRequest = responseReceived.initiatingRequest();

        if (!isInJsonFormat(originalRequest)) {
            HttpRequest jsonFormattedRequest = convertToJsonFormat(originalRequest);
            api.http().sendRequest(jsonFormattedRequest);
        }

        return continueWith(responseReceived);
    }

    private HttpRequest convertToJsonFormat(HttpRequest originalRequest) {
        //TODO implement your convert json logic
        return originalRequest.withBody("{Json Body}");
    }

    private boolean isInJsonFormat(HttpRequest originalRequest) {
        //TODO implement your check if it is in your json format
        return originalRequest.body().toString().contains("{Json Body}");
    }

In General I would not do any slow/blocking operations inside the Http Handlers as all request that burp sends go through your http handlers, Burp will run VERY slowly if you are sending requests from inside the Handlers.

It would be better to store the requests you want to send in a list and then send the list in another thread/later using a button or a schedule.

Nzoth9 commented 1 year ago

Thanks to reply <3, @seanjburns! How do you modify the HttpRequest of Content-Type?

Hannah-PortSwigger commented 1 year ago

Hi

To modify the Content-Type you will need to modify or add the "Content-Type" header in the request.

Nzoth9 commented 1 year ago

Hi, @Hannah-PortSwigger! Thanks to reply <3 !