Burp Suite is my go-to tool for performing penetration tests against web applications. I was recently asked if it was possible to integrate Burp into a development pipeline, so that a development team could automatically audit a web application that was in development. I personally had never used Burp in that capacity, so I thought would be neat to look into. Well, thankfully, the Burp REST API will allow us to perform some operations programmatically.
There are a plethora of Dynamic Application Security Testing (DAST) tools on the market. Many of them are incredibly pricey. Burp Community edition offers a large number of features for free, so it seemed to me that this could be a great starting point for a development team. Although you can’t do everything with Burp using the REST API, you can at least create scans and retrieve the results of those scans. Integrating this into a development process will put your security practices well above average.
Enable and Configure the Burp REST API
In order to utilize the Burp REST API, you must enable and configure it. For security reasons, PortSwigger has disabled Burp’s API by default. Also, you should create an API key and use that key to access the API.
To enable the REST API, launch Burp and navigate to the User options tab. Then activate the Misc sub-tab. Scroll down and you will find the REST API section. In this section, perform the following steps:
- Check the Service running checkbox to enable the service. Note the Service URL. By default, it should be http://127.0.0.1:1337. If you need to change the port, click the Change… button. The remainder of this post will assume that you are leaving the default port of 1337.
- Under API Keys, click the New button. This will open the New API key dialog to allow you to create an API key.
- In the New API key dialog, enter the name for the new API key.
- Click the Copy key to clipboard button and store the API key in a safe place, such as LastPass, 1Password, or some other key vault technology. Note that Once you dismiss this dialog, you will no longer be able to retrieve the API key.
- Click the OK button.
You will now be able to invoke the REST API.
Dissecting the REST API
Currently the Burp REST API is very simple, offering only three primary functions. You can view these API endpoints directly in your browser. To access the REST API, open your web browser to the following URL, replacing [api_key] with the API key created in the previous section.
http://127.0.0.1:1337/[api_key]
Your browser will redirect you to the REST API documentation for the latest API version supported by your installation of Burp. As of the time of this writing, it is v0.1. You’ll want to make a note of this API version, as you’ll need when you make an API request. The remainder of this post will assume that your version is v0.1.
Your browser should list all of the available REST API endpoints. As I mentioned before, there are currently three endpoints:
- GET /knowledge_base/issue_definitions: allows you to retrieve a list of all issues that can be detected by Burp Scanner.
- POST /scan: allows you to create a new scan.
- GET /scan/[task_id]: allows you to retrieve the progress of the scan you created.
Getting a List of Issue Definitions
When Burp Scanner detects a problem, it will report an issue. This issue will have a specific definition. You can view all of the types of issues that Burp Scanner can detect by visiting Burp’s Target / Issue definitions tab. You can retrieve this list of issue definitions programmatically by issuing a GET request to Burp’s API at the following URL:
http://127.0.0.1:1337/[api_key]/v0.1/knowledge_base/issue_definitions
When you execute a scan, the scan will indicate the IDs of issue types that are found. The data returned by this API endpoint will help you identify the type of issue found and provide documentation including description, remediation, and references.
Each IssueDefinition returned by this API call contains the following properties:
- issue_type_id: a unique identifier representing the type of issue found by the Burp scanner.
- name: a human readable name for the type of issue, such as “SQL injection” or “Cross-site scripting (DOM-based)”.
- description: an HTML-formatted string containing the description of the issue.
- remediation: an HTML-formatted string containing the recommend steps to remediate the issue.
- references: an HTML-formatted string containing links to references with additional information surrounding the type of issue.
- vulnerability_classifications: an HTML-formatted string containing links to all associated CWE’s.
Not all issue definitions returned will contain all properties. For example, “Web cache poisoning” contains references, but “Unidentified code injection” does not. Also, extended generated issues, only contain an issue_type_id, name, and description.
I currently do not see a way of finding the typical severity, so that’s a bit unfortunate. It’s not a show stopper, though.
Creating a New Scan
Creating a new scan is as simple as calling a POST method on the following URL:
http://127.0.0.1:1337/[api_key]/v0.1/scan
The Scan Data Type
The REST API provides many of the same features available to you as when you create a scan manually. So, if you aren’t familiar with Burp Scanner, in general, I would advise reviewing the documentation.The scan endpoint takes a JSON payload with of type Scan. According to the documentation, the scan should be nested in a “scan” property, but this is not correct. The Scan data type is, however, documented within the REST API documentation. Currently, the it contains the following properties:
- urls: an array of Strings indicating the URLs to be scanned.
- name: an optional name to give the scan, for identification purposes.
- scope: an optional Scope object, which will can be used to restrict the set of URLs for which the scanner attempts to process. These scopes can use either basic or advanced scope controls.
- application_logins: an optional array of ApplicationLogin objects which can be used to initialize a session with the target website. These credentials will be submitted to any login functions that the scanner encounters and will enable the scanner to crawl and audit authorized URLs.
- scan_configurations: an optional array of Configuration objects that can be used to control the scanner. You can utilize an existing configuration from the library, or you can use your own custom configuration.
- resource_pool: an optional String identifying the name of the resource pool to utilize for this scan. If you don’t specify a resource pool, the default resource pool will be utilized. You must use the Burp UI to create a new resource pool, as this functionality does not currently exist in the API.
- scan_callback: an optional Callback identifying a URL for Burp to call with scan progress. Burp will issue a PUT request to the designated URL. For more information see the next section.
Creating a Simple, Default Scan
In its most basic form, you simply need to specify an array of URLs to scan. By default, Burp will perform a crawl and audit using the default configuration. So, to scan a web application listening port 5000 on your local development machine, you could POST the following JSON body to the Burp REST API:
{ "urls": [ "http://localhost:5000/" ] }
A successful POST will result in a 201 HTTP response code. The Location header in the response will indicate the scan’s task ID. This value will be useful when checking on the status of the scan.
Receiving Updates on a Scan Through Callbacks
If you supply the scan_callback argument to the /scan API, Burp will callback to this URL on a periodic basis to update you with the scan’s status. If you were scanning the same local web application listening on port 5000 and you had an HTTP listener listening for the callback on port 5002, then you could simply invoke /scan with the following payload:
{ "urls": [ "http://localhost:5000/" ], "scan_callback": { "url": "http://localhost:5002/" } }
Burp will now issue PUT requests to http://localhost:5002/ periodically to inform you of any updates.
NOTE: As of the time of this writing, Burp does not set the Content-Type header in the request. The body will be a JSON payload, but various tooling may not be able to perform content type negotiation. Thus, if you are attempting to create an ASP.NET Core 2.0 Web API to receive this request, you’ll need to pull the Body out of the Request, instead of receiving the body in an argument to the respective HttpPut method. I’ve submitted a bug to PortSwigger.
The Unnamed, Scan Task Data Type
The JSON payload you receive will have the following properties:
- task_id: the respective ID of the scan task for this request. This will be the same value returned in the Location header in the response from the call to the /scan API.
- scan_status: the status of the respective scan. If the scan is currently active, this will be “auditing”. If the scan completed successfully, this will be “succeeded”.
- scan_metrics: a JSON object containing various statistics about the current scan, including the number of crawl or audit requests made, how many unique locations have been visited, how many requests have been queued up, and the percentage of completion.
- message: a string containing a message sent by Burp. I have yet to see this populated with anything, so I think that it is reserved for future use, or I just haven’t hit the case where Burp will supply it yet.
- issue_events: I assume that this should be an array of all of the issues that have been discovered, but this hasn’t been populated for me either.
To get more information, you’ll need to call the scan’s task endpoint in the REST API. We’ll dive into that in the next section.
Getting Details For a Scan
As mentioned earlier, when you invoke the /scan API, Burp will return a scan task ID in the Location header of the HTTP response. This scan task ID can be used to get details from the scan by calling into the following URL:
http://127.0.0.1:1337/[api_key]/v0.1/scan/[task_id]
Issue Event Filter Parameters
You can specify an empty payload to retrieve all issues. Or, you can provide a JSON payload to filter issues. This JSON payload has the following parameters:
- after: if you supply an issue ID (as a String) for this property, then Burp will only return issues that were found after that issue. For example, if you had three issues, “1”, “2”, and “3”, and you specified “1” for this property, then only issues “2” and “3” would be returned.
- issue_events: a number indicating the maximum number of issues to return. Specifying a value of 0 will return no issues, however, you will still receive all of the statistical information regarding the scan, including its progress.
You can combine the after and issue_events parameters to page through the issues, rather than grabbing them all at once for performance reasons.
The Unnamed, Issue Event Data Type
The schema of the payload returned by this API will match the schema of the data that Burp sends to you in the callback defined above. The difference here is that Burp will actually populate the issue_events array with all issues that fulfill your filter criteria (or all issues if no criteria is specified).
The issue_events property will be an array of issue events, each containing the following properties:
- id: a string representing the ID of the issue event documented by the Burp Scanner. This value will correspond with the “#” column of the issue event listed on the Issue activity tab of the scan task’s details tab in Burp. The difference is that in this JSON payload, the ID is zero-based and in the UI it is one-based.
- type: a string representing the type of issue event. This value will correspond with the Action column on the Issue activity tab (for example, “Issue found”).
- issue: a JSON object representing the issue documented by the event. You can retrieve full information regarding the issue, including the name and type, severity, confidence, origin, and evidence containing request and response data. You can use the type_index property on the issue object as a key into the list of issue definitions (as defined above).
What’s Next?
This this post, I showed you the basics of the Burp REST API and how you can use this API to automate the process of creating a scan. In a future post, we’ll dive into the process of creating a new scan using a built-in scan configuration and a custom scan configuration. We’ll also talk about integrating this into a basic CI pipeline so that you can continuously audit a web application under development.