This is the 4th tutorial where I have skipped 3rd tutorial which will be updated later and developed a Burp Extension using jython and implemented addition on custom header in the request headers derived from response body/response header using Burp Suite Macro.
This custom header extension can be directly invoked and it can be used for automating CSRF tokens or JWT Token in the request headers. There were multiple custom extensions which implemented JWT or Authorisation token but this extension can be customised according to the need. Also this blog will guide you through how to write extensions in Burp Suite using Jython. This can be used to fetch the dynamic value from the response.
a) X-CSRF token to be added in the request body.
b) CSRF token is derived from the response body.
c) Basic knowledge of Macro.
d) Modified extension with custom regex as needed.
e) Custom header is already present in the all the request.
f) Custom burp extension is loaded.
2. As this is DVWA, there was no custom header.
We will be replacing X-CSRF: xxxxxxx
to the dynamic value fetched from the request body value='c82d0a16fd455d8db048022a5d6bd0a9'
3. Let’s select the request from the Burp history and quickly create the Macro.
Project Options > Sessions > Add .
4. In the Session handling rule editor
add the Rule Description:
Blog-DynamicResponseHTMLBody. Then in the Rule Actions
click on Add
then Run a macro
.
5. Then in the Session handling action editor
, select Add a new macro
.
6. In the Macro Recorder
, select the request which contains dynamic value and click OK.
7. In the Macro Editor
, add Macro description
: FetchDynamicValue. Then click Configure Item
.
8. As there are no cookies, hence above boxes are unticked. Now on Custom parameter locations in response
, click Add
.
2. Perform the common steps mentioned above.
3. For Define Custom Parameter
, provide parameter name
: any_value (this can be any value, we just need this to fetch macro response later from python extension using Burp API).
Select the value from the response body.
4. Custom parameter in the Configure Macro Item
should have any_value.Then click OK.
5. Click OK, for saving and closing the Macro Editor
.
6. For Session handling action editor
, Select the After running the macro, invoke a Burp extension action handler
and select our own extension macro_custom_header_resbody.py .
Click OK.
7. Save the Session handling action editor and switch to Scope
.
8. In the Scope
tab of Session handling rule editor
, change Tools Scope
and URL Scope
according to the need. Click OK.
9. Now add the custom header as this is the demo DVWA and it doesn’t contain CSRF header. We could have added custom header by invoking another custom header extension .
X-CSRF: xxxxxx
and send the request.
10. Check the value of X-CSRF:
token, this value is dynamically updated.
2. In the Session handling rule editor
, Add Rule Description
and in the Rule Actions
select Run a macro
.
3. In the Session handling rule editor
, select Add a new macro
.
4. For Define Custom Parameter
, provide parameter name
: any_random_value (this can be any value, we just need this to fetch macro response later for header value from python extension using Burp API).
Select the value from the response header.
5. In the Configure Macro Item
, untick Cookie handling
as it is not required and in the Custom parameter locations in response
check the any_random_value
and click OK.
6. Then in the Macro Editor
, enter the Macro Description
and click OK.
7. Then in the Session handling action editor
, select the newly created macro i.e. FetchDynamicValue-Header
. Afterwards select the extension in After running the macro, invoke a Burp extension action handler:
macro_custom_header_resheader.py
8. Then change to Scope
tab. For Tools Scope
select the scope and URL Scope accordingly.
9. Now add the custom X-CSRF: xxxxxxx
token and send the request in the repeater.
10. Check the value of the extension, it is modified according to the demo header(we selected date header as DVWA doesn’t contain any csrf token in response headers).
a) For the response header below mentioned part is fetching the response headers. macro_response_info.getHeaders()
fetches the value of response headers.
Then macro_body_offset.get(1)[14:]
slices from specific index.
This value needs to be changed according to the dynamic value from header.
macro_response_info = self.helpers.analyzeResponse(macroItems[0].getResponse())self.stdout.println('Loading custom header for Macro complete: By justm0rph3u5')
# get the list of headers from the response, if token is present in the response header then we need to list all the header and extract the value
macro_body_offset = macro_response_info.getHeaders()
#from the macro body(which contains the response headers), we are extracting dynamic value of the header
new_header = macro_body_offset.get(1)[14:]
b) The second part where X-CSRF
header is mentioned needs to be updated before loading the extension. This string checks if the mentioned header is present in the list of request header to perform further modifications.
Change value X-CSRf
at both the places.
for header in headers:
#Change this value according to the custom header present in the request. So if X-SESSION_ID: xxxxxxxx is the header then change the string to 'X_SESSION_ID'
if 'X-CSRF' in header:
head_delete = header#remove the header
headers.remove(head_delete)
#add new header, some wierd java error may come. please diy
#While adding the new header, kindly change the value to 'X_SESSION_ID', from above example.
headers.add('X-CSRF: ' + new_header)
c) This part of the code updates the message body and headers in the Burp Suite.
# create new message with headers and body
new_message_request = self.helpers.buildHttpMessage(headers, message_body)
baseRequestResponse.setRequest(new_message_request)
d) Finally, custom Burp Suite extension is ready which can be used to add any header with dynamic value. This needs further modification but for time being this works great.
2. For Dynamic Value in the Response Body
a) For the dynamic value in the response body below mentioned part is fetching the response body value.macroItems[0].getResponse()
extracts the token from the macro response. Then self.helpers.bytesToString(macro_body_value)
provides the response content. Regex will be ran on this content to fetch the exact value.
macro_response = self.helpers.analyzeResponse(macroItems[0].getResponse())
self.stdout.println('Loading custom header for Macro complete: By justm0rph3u5')
# extract the token from the macro response
macro_message = macroItems[0].getResponse()# print(self.helpers.bytesToString(macro_message))
#this part of the code deals with fetching value of HTML Response Body
macro_offset = macro_response.getBodyOffset()
macro_body_value = macro_message[macro_offset:-1]
macro_body_str = self.helpers.bytesToString(macro_body_value)
b) Also update the regex, this regex will be used to extract the value from dynamic html page.
For value='c82d0a16fd455d8db048022a5d6bd0a9'
this regex is used value=\'\S+\'
.
This value needs to be changed according to the dynamic value from body.
c) Use re module from python and create regex which extracts and slices the exact value of the token from HTTP response body.
Modify according to the exact value: match_1.group()[7:-1]
#Regex checks the value of the Token to be fetched from the html body. Here is was csrf token in the response body. Modify regex and slice it accordinglymatched = re.finditer(regex, macro_body_str, re.MULTILINE)
for matchNum, match_1 in enumerate(matched, start=1):
#change this value of index according to the regex.
#Modify this
new_header=match_1.group()[7:-1]
d) This part where X-CSRF
header is mentioned needs to be updated before loading the extension. This string checks if the mentioned header is present in the list of request header to perform further modifications.
Change value X-CSRf
at both the places to the desired header. For example X-Session-ID, JWT-Token, etc.
for header in headers:
if 'X-CSRF' in header:
head_delete = headerheaders.remove(head_delete)
# add new header, some wierd java error may come. please diy
# While adding the new header, kindly change the value to 'X_SESSION_ID', from above example.
headers.add('X-CSRF: ' + new_header)
e) This code updates the message body and headers in the Burp Suite.
# create new message with headers and body
new_message_request = self.helpers.buildHttpMessage(headers, message_body)
baseRequestResponse.setRequest(new_message_request)
d) There might be other custom Burp Suite extension which modifies the headers but after searching for hours this extension can be used with simple Burp Macro
and can quickly fetch the value and update the headers.
Note: This article is trying to solve the problem mentioned in this portswigger forum.
Finally we can update header in Burp Suite via Session Handling/Macros.