Automatically Renew Expired Tokens During Burp Scans


When performing long automated scans with Burp Suite, issues with authentication expiring can be a thorn in the flesh. This post shows how Session Handling Rules can often be used to solve this.

In our example REST API target, authentication is performed in the following way:

  1. An API request is sent which includes a username and password and requests a token
  2. A JWT (JSON Web Token) is received in the response
  3. Future API requests are sent with an authorization header that uses a bearer scheme and includes the token

If you didn't follow that, don't worry because I'll explain as we go. After I show each step of the authentication, I'll show how to use automation to solve this issue so that neither Scanner traffic nor manual testing with Repeater is hampered. 

Let's start with requesting a token from our example target's /gettoken endpoint.


REQUEST:

POST /gettoken HTTP/2

Host: example.com


username=testuser&password=password123


RESPONSE:

HTTP/2 200 OK

Content-Type: application/json; charset=utf-8


{

  "access_token": "<token>",

  "expires_in": 3600,

  "token_type": "Bearer"

}


The value of the access_token key in the response is what we are looking for. Note that it will expire in 3,600 seconds, which is an hour. This token will need to be sent with future requests. It will be sent in the Authorization header without quotes, as shown below.


REQUEST:

GET /api/info HTTP/2

Host: example.com

Content-Type: application/json

Authorization: Bearer <token>


RESPONSE:

HTTP/2 200 OK

Content-Type: application/json; charset=utf-8


{<data>}


If our token has expired, our example server will complain, as shown below.


REQUEST:

GET /api/info HTTP/2

Host: example.com

Content-Type: application/json

Authorization: Bearer <EXPIRED-TOKEN>


RESPONSE:

HTTP/2 500 Internal Server Error

Content-Type: text/plain; charset=utf-8


{...token may have expired...}


This last piece is what we need to solve. We need automated and manual testing not to be hampered by expired tokens. Here is the automation we are going to put into place to solve it:

  1. Use a Session Handling Rule to parse responses for "token may have expired" to detect an invalid session
  2. Configure the Session Handling Rule such that when an invalid session is detected, a macro is triggered which requests a new token
  3. Configure the Sessions Handling Rule to also call the 'Use the Add Custom Header' Burp extension which will insert the fresh token into the Authorization header of new requests

Hopefully, you now have a high level understanding of the problem we need to solve and our overall strategy to solve it. Now let's get into the exact steps to build this automation.


1. Install the Add Custom Header extension from Extender>BApp Store

2. Navigate to the Add Custom Header extension, choose Regular Expression, and add any necessary modifications to the default RegEx (like a space after the colon, etc.)

3. Capture a login (request for a token) through a browser or Postman, etc.

4. Create a macro that grabs the token during login: Project options>Sessions>Macros>Add

5. In the resulting Macro recorder window, select the item pertaining to the login you captured and click ok

6. Choose Configure item>Add

7. Enter a Parameter name

8. Select (highlight) the value of the access token (without the quotes)

9. Hit ok 3 times


We now have a macro that grabs a new token and an extension that inserts it in requests. Now we need a rule that will trigger these when needed. Below are the steps for the Session Handling Rule.

1. Project options>Sessions>Session Handling Rules>Add

2. Click on the Scope tab and choose the relevant tools and URLs. Make sure that the check boxes for Repeater and Scanner are checked.

3. Go back to the Details tab and choose Rule Actions>Add>Check session is valid

4. Choose Issue current request and 

5. Under Location(s), check the box for Response body

6. In the Look for expression field, put in the appropriate string, which in this case is: token may have expired

7. Set the Match type: Literal string

8. Set the Match indicates: Invalid session

9. Set If the session is invalid: Run a macro

10. Select the macro you created earlier

11. Uncheck the next 2 boxes but check this one: After running the macro, invoke a Burp extension action handler...

12. In the drop down menu, choose Add Custom Header


Now it's time to test. If everything is working, you should be able to make a request with an expired token using Repeater and have it automatically replaced with a good token behind the scenes.


REQUEST:

GET /api/info HTTP/2

Host: example.com

Content-Type: application/json

Authorization: Bearer <EXPIRED-TOKEN>


RESPONSE:

HTTP/2 200 OK

Content-Type: application/json; charset=utf-8


{<data>}


If you have any trouble, you can use the sessions tracer to troubleshoot: Project options>Sessions>Session Handling Rules>Open sessions tracer

You should be good to go with running scans or even doing manual testing now.


Credit: Special thanks to Rick Osgood who helped me figure this out!



Comments

Popular Posts