· Tutorials  · 6 min read

Writing BChecks for BurpSuite

Extending BurpSuite functionality to find more vulnerabilities

Extending BurpSuite functionality to find more vulnerabilities

Intro

Last year (in release 2023.10.2), the PortSwigger introduced a new method of scanning automation in BurpSuite - BChecks. It is a simple scripting language that allows users to create their own custom security checks, which will be performed during the scanning. Now, in some cases, instead of writing a new BApp extension, it is much quicker to utilize the BChecks functionality and do the automation or simply extend a list of detected vulnerabilities by the BurpSuite.

For demonstration purposes, let’s write our own script that will utilize the HTTP headers (e.g. X-Forwarded-For: 127.0.0.1) in attempt to bypass restrictions imposed by some webservers. It is a trivial method which may trick some webserver to process the specified IP address instead of the real one, which could lead to authorization or rate limiting restrictions bypasses.

Anatomy of BCheck

Each BCheck is defined as a plain text file with a .bcheck file extension with padding similar to the .yaml format. Each file definition must start with a metadata object, and have exactly one given...then statement.

Metadata

Contains information about the check itself. This object is mandatory for all BChecks and must be placed at the very start of the definition.

metadata:
language: v2-beta
name: "403/429 bypass using HTTP Header"
description: "Attempts to bypass 403/429 using the HTTP headers with local IP address"
author: "ShadowSurface"
tags: "bypass"

Control flow

These keywords control the flow of execution for the definition. For example, define section is optional and declares variables with inner scope. The run for each declares an array variable that can be iterated over. When this variable is called the check runs once for each item in the array.

define:
bypass_ip = "127.0.0.1"
run for each:
bypass_header =
"Forwarded",
"Via",
"X-Client-IP",
14 collapsed lines
"X-Forwarded-For",
"X-Forwarded-Host",
"X-Forwarded-Proto",
"X-Forwarded-Server",
"X-Forward-For",
"X-Forwared-Host",
"X-Host",
"X-Originating-IP",
"X-Real-IP",
"X-Remote-Addr",
"X-Remote-IP",
"X-Requested-By",
"X-Requested-For",
"X-Trusted-IP"

It is possible to declare an array only in run for each section, and not in the define.

Note: you can define multiple arrays in this section and the script will iterate over each of them.

Now we need to instruct the scanner to when it should run our check. As mentioned before, each BCheck must have a single given...then statement containing either one of the following:

KeywordDescription
given response thenThe check runs once for each response audited.
given request thenThe check runs once for each request audited.
given host thenThe check runs once for each host audited.
given path thenThe check runs once for each path audited.
given [any|query|header|body|cookie] insertion point thenThe check runs once insertion point is audited.

We will not use the given response then keyword as it is meant only to be used for passive checks, and it will not allow us to send the request in attempt to bypass the restriction. Instead, we will choose the given request then keyword to audit the base response when the request is sent, and send a new one, as it is not impose such limitations.

Conditionals

Conditional keywords control actions that happen as a result of a set condition and can be only used inside a given...then statement.

BChecks support a range of conditions, making matching and comparing any part of the requests/responses an easy task.

given request then
if {base.response.status_code} matches "(403|429)" then
# [perform action]
end if

Note: The base keyword represents the request sent and response received by Burp Scanner for the specified scan mode during crawling, while the latest keyword refers to the most recent request/response pair for this scan mode. More details about these objects are described in the “Reserved variables” section of the documentation.

Actions

This part of the BCheck will prompt Burp Scanner to perform a particular action. The actions can be

  • send request
  • send request (raw)
  • send payload
  • report issue
  • report issue and continue

We will select the send request action to send the request with our specified information, which, in this case, is a new header appended to it. If there is a difference between the new response and the previous one, we will instruct BurpSuite to mark it as a potential issue.

given request then
if {base.response.status_code} matches "(403|429)" then
send request:
replacing headers:
{bypass_header}: {bypass_ip}
if not( {latest.response.status_code} is {base.response.status_code} ) then
# [report issue]
end if
end if

Reporting the issue

To report the issue we need to initialize the report issue object. Each of these objects consists of: name (will be taken from metadata if absent), severity (ranges from info to high), confidence*, details about the issue, and remediation advice.

*Reporting confidence ranges:

ConfidenceDescription
tentativeThe issue is potentially present but there is a high chance that this could be a false positive.
firmThe issue is probably present, but this could be a false positive.
certainThe issue is definitely present.
report issue:
severity: high
confidence: tentative
detail: `Potential {base.response.status_code} bypass using {bypass_header} header.`
remediation: `Avoid using {bypass_header} for authorization or rate limiting.`

Full script

By combining all the previous sections, we end up with the following BCheck script:

metadata:
language: v2-beta
name: "403/429 bypass using HTTP Header"
description: "Attempts to bypass 403/429 using the HTTP headers with local IP address"
author: "ShadowSurface"
tags: "bypass"
define:
bypass_ip = "127.0.0.1"
run for each:
bypass_header =
"Forwarded",
"Via",
"X-Client-IP",
14 collapsed lines
"X-Forwarded-For",
"X-Forwarded-Host",
"X-Forwarded-Proto",
"X-Forwarded-Server",
"X-Forward-For",
"X-Forwared-Host",
"X-Host",
"X-Originating-IP",
"X-Real-IP",
"X-Remote-Addr",
"X-Remote-IP",
"X-Requested-By",
"X-Requested-For",
"X-Trusted-IP"
given request then
if {base.response.status_code} matches "(403|429)" then
send request:
replacing headers:
{bypass_header}: {bypass_ip}
if not( {latest.response.status_code} is {base.response.status_code} ) then
report issue:
severity: high
confidence: tentative
detail: `Potential {base.response.status_code} bypass using {bypass_header} header.`
remediation: `Avoid using {bypass_header} for authorization or rate limiting.`
end if
end if

Running BCheck

To quickly test your new check against the target, follow these steps:

  1. Navigate to Target -> Site map -> Site map filter and enable the display of requests with 4xx status codes. Site map filter

  2. Now you will see requests that returned 403/429 responses. Requests with 403/429 responses

  3. Right-click the target host and select Scan. In the Scan type menu, choose Audit selected items. Scan options

  4. In the Scan configuration menu, click Select from library and choose Audit checks - BChecks only. This ensures that only BChecks will run, saving you some time. Selecting Audit checks - BChecks only

  5. (⚠️) When scanning requests that returned 429 responses, Burp Suite may throttle the scan due to the default Resource pool configuration. Resource pool settings

    To significantly improve scan speed, create a new resource pool without throttling.

  6. Start the scan and view the All issues section to see if any vulnerabilities were identified. All issues section

Wrap-up

BCheks is a simple scripting language with some current limitations and yet massive potential. It provides a convenient interface to analyze requests/responses, interact with BupSuite Collaborator, and send HTTP requests.

We have already seen the popularity of the engines that handle community-written scripts, such as nuclei templates. It is indeed noteworthy to observe PortSwigger’s entry into this arena.

By leveraging the BurpSuite platform and extending it’s capabilities, it may become day-to-day tool in the arsenal of the web security researchers.

References

Back to Blog