Manipulating Authorization Token Using Burp Suite
During the web application security assessment on a web API, the Authorization Token had some limitation which it is only valid for 5 minutes. Burpsuite unable to perform a complete scanning or if it is completed, the result is not accurate due to the Authorization Token keep changing in 5 minutes timeframe. This post will described how to manipulating authorization token using Burp Suite.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
HTTP/1.1 401 Unauthorized Server: ###### Date: Wed, ## ### #### 08:36:10 GMT Content-Type: application/json; charset=utf-8 Content-Length: 61 Connection: close Cache-Control: no-cache Pragma: no-cache Expires: -1 WWW-Authenticate: Bearer X-Powered-By: ####### {"Message":"Authorization has been denied for this request."} |
To overcome this issue, we need to find a way how to bypass this restriction as Burpsuite require a valid token each time it performs scanning as well as the repeater and intruder. Search on google lead us to a website where they wrote a Burp extender (written in python) to fetch the new token and replace it in the header every time Burpsuite make a request. The Burpsuite extender inspect every request for the tag ‘Authorization: Bearer’ in its header and after that delete it and replace it with the new one in order for the current session to be valid. The bearer token was generated by the following request, the bearer token will be included in JSON keyword called ‘###Token‘ inside the response body.
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 |
POST /api/v2/###/#########n HTTP/1.1 Content-Type: application/json Authorization: [redacted] User-Agent: PostmanRuntime/7.24.1 Accept: */* Cache-Control: no-cache Postman-Token: dec8be9f-c4a1-416d-891c-bb2025002afb Host: ############################## Accept-Encoding: gzip, deflate Connection: close Content-Length: 81 { "a######d":"######50", "email": "#####@####.com", "#########":false } ---------------------------------------------------------------------------------------------------------------------- HTTP/1.1 200 OK Server: ###### Date: Fri, ## ### #### 02:41:19 GMT Content-Type: application/json; charset=utf-8 Content-Length: 345 Connection: close X-Powered-By: ###### [snipped] {"code":"200","message":"Success","data":{"###Token":"k+HEEB7CmaF0RwzvWrV7L2TdzKDt3lWXLGh2CxCUq6D#######################Pn1fTY8u4/QNOhCxnzFCxb0DiTkMXLMG8EGpDE+rMamoNzZWUtUMtAldAhgXBdNFgEqTw+7Tf0qFzKbKFWTn0goWgT3WbzFyNBW+cI6HARTYQZF8Qf6+CfhrQJLvoSZ8PMBRo6qy4Mb6BtOSm#######################vQbPkzR2wnuPYQrNxED6iIYhFFeHtuPZS+lAEnfxeVgTy"}} |
Create Macro in Burpsuite
To automate the process, we need to create a macro in Burpsuite. The macro will initiating a request to the server to refresh the bearer token. In Burpsuite go to Project Options – Macro:

Macro Recorder screen will be prompted, select the request that generate the bearer token.


Create Session Handling Rules in Burpsuite
To replace the expired token with the new one, we need to create a macro in Burpsuite (explained above). The macro will initiate a request to get the new bearer token before the Burpsuite extender fetch the new generated token and replace it in the request header. To do this, we need to create a new session handling rules in the Burpsuite.

The rule basically check for HTTP header that match the defined expression “HTTP/1.1 401 Unauthorized”.

If the response match, it will run the macro and after completed it will invoke Burpsuite extender to fetch the new generated bearer token and replace it to the request header.

Result


Credit: https://twelvesec.com/2017/05/05/authorization-token-manipulation/
Bearer Authorization Token (Burpsuite Extender)
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 |
import json import datetime from java.io import PrintWriter from burp import IBurpExtender, IBurpExtenderCallbacks, ISessionHandlingAction class BurpExtender(IBurpExtender, ISessionHandlingAction): NAME = "Bearer Authorization Token" def registerExtenderCallbacks(self, callbacks): self.callbacks = callbacks self.helpers = callbacks.getHelpers() callbacks.setExtensionName(self.NAME) self.callbacks.registerSessionHandlingAction(self) self.stdout = PrintWriter(callbacks.getStdout(), True) #self.stderr = PrintWriter(callbacks.getStdout(), True) self.stdout.println("Bearer Authorization Token \n") self.stdout.println('starting at time : {:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now())) self.stdout.println("-----------------------------------------------------------------\n\n") return def getActionName(self): return self.NAME def performAction(self, currentRequest, macroItems): request_info = self.helpers.analyzeRequest(currentRequest) #Extract the Bearer token from the macro response macro_response_info = self.helpers.analyzeResponse(macroItems[0].getResponse()) macro_msg = macroItems[0].getResponse() resp_body = macro_msg[macro_response_info.getBodyOffset():] macro_body_string = self.helpers.bytesToString(resp_body) bearer_token = json.loads(macro_body_string) bearer = bearer_token["data"]["###Token"] #self.stdout.println(bearer) headers = request_info.getHeaders() req_body = currentRequest.getRequest()[request_info.getBodyOffset():] resp_headers = macro_response_info.getHeaders() headers = request_info.getHeaders() auth_to_delete = '' for head in headers: if 'Authorization: bearer ' in head: auth_to_delete = head try: headers.remove(auth_to_delete) except: pass headers.add('Authorization: bearer ' + bearer) self.stdout.println('Header Checked at time : {:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now())) self.stdout.println("-----------------------------------------------------------------" ) self.stdout.println("Adding new header - Authorization bearer: " + bearer) self.stdout.println("-----------------------------------------------------------------") self.stdout.println("Geting authorized..done\n\n") # Build request with bypass headers message = self.helpers.buildHttpMessage(headers, req_body) # Update Request with New Header currentRequest.setRequest(message) return |