├── .github └── dependabot.yml ├── ai ├── build.gradle ├── src │ └── main │ │ └── java │ │ └── example │ │ └── ai │ │ ├── MyPromptMessage.java │ │ ├── AiExample.java │ │ └── MyProxyRequestHandler.java └── README.md ├── menubar ├── build.gradle ├── README.md └── src │ └── main │ └── java │ └── example │ └── menubar │ ├── MyExtensionUnloadingHandler.java │ └── MenuBar.java ├── collaborator ├── build.gradle ├── src │ └── main │ │ └── java │ │ └── example │ │ └── collaborator │ │ ├── poller │ │ ├── InteractionHandler.java │ │ └── Poller.java │ │ ├── InteractionLogger.java │ │ ├── MyProxyRequestHandler.java │ │ ├── MyInteractionHandler.java │ │ └── CollaboratorExample.java └── README.md ├── contextmenu ├── build.gradle ├── README.md └── src │ └── main │ └── java │ └── example │ └── contextmenu │ ├── ContextMenu.java │ └── MyContextMenuItemsProvider.java ├── customlogger ├── build.gradle ├── README.md └── src │ └── main │ └── java │ └── example │ └── customlogger │ ├── MyHttpHandler.java │ ├── MyTableModel.java │ └── CustomLogger.java ├── helloworld ├── build.gradle ├── README.md └── src │ └── main │ └── java │ └── example │ └── helloworld │ └── HelloWorld.java ├── httphandler ├── build.gradle ├── README.md └── src │ └── main │ └── java │ └── example │ └── httphandler │ ├── HttpHandlerExample.java │ └── MyHttpHandler.java ├── persistence ├── build.gradle ├── README.md └── src │ └── main │ └── java │ └── example │ └── persistence │ ├── PersistenceExample.java │ ├── SavingLoadingRequests.java │ └── RequestResponseLogging.java ├── proxyhandler ├── build.gradle ├── README.md └── src │ └── main │ └── java │ └── example │ └── proxyhandler │ ├── ProxyHandlerExample.java │ ├── MyProxyHttpResponseHandler.java │ └── MyProxyHttpRequestHandler.java ├── .gitignore ├── customscanchecks ├── build.gradle ├── src │ └── main │ │ └── java │ │ └── example │ │ └── customscanchecks │ │ ├── CustomScanChecks.java │ │ └── MyScanCheck.java └── README.md ├── eventlisteners ├── build.gradle ├── README.md └── src │ └── main │ └── java │ └── example │ └── eventlisteners │ ├── MyHttpHandler.java │ ├── MyProxyRequestHandler.java │ ├── MyProxyResponseHandler.java │ └── EventListeners.java ├── intruderpayloads ├── build.gradle ├── src │ └── main │ │ └── java │ │ └── example │ │ └── intruderpayloads │ │ ├── IntruderPayloads.java │ │ ├── MyPayloadGeneratorProvider.java │ │ ├── MyPayloadGenerator.java │ │ └── MyPayloadProcessor.java └── README.md ├── trafficredirector ├── build.gradle ├── README.md └── src │ └── main │ └── java │ └── example │ └── trafficredirector │ ├── TrafficRedirector.java │ └── MyHttpHandler.java ├── websockethandler ├── build.gradle ├── README.md └── src │ └── main │ └── java │ ├── WebSocketHandlerExample.java │ ├── MyWebSocketCreatedHandler.java │ └── MyWebSocketMessageHandler.java ├── customrequesteditortab ├── build.gradle ├── README.md └── src │ └── main │ └── java │ └── example │ └── customrequesteditortab │ ├── CustomRequestEditorTab.java │ ├── MyHttpRequestEditorProvider.java │ └── MyExtensionProvidedHttpRequestEditor.java ├── customsessiontokens ├── build.gradle ├── src │ └── main │ │ └── java │ │ └── example │ │ └── customsessiontokens │ │ ├── CustomSessionTokens.java │ │ └── MySessionHandlingAction.java └── README.md ├── proxywebsockethandler ├── build.gradle ├── src │ └── main │ │ └── java │ │ ├── MyProxyWebSocketCreationHandler.java │ │ ├── ProxyWebSocketHandlerExample.java │ │ └── MyProxyWebSocketMessageHandler.java └── README.md ├── customscaninsertionpoints ├── build.gradle ├── src │ └── main │ │ └── java │ │ └── example │ │ └── customscaninsertionpoints │ │ ├── CustomScanInsertionPoints.java │ │ ├── MyInsertionPointProvider.java │ │ └── MyAuditInsertionPoint.java └── README.md ├── multiapi ├── build.gradle ├── README.md └── src │ └── main │ └── java │ └── example │ └── multiapi │ └── MultiApiExample.java ├── gradle └── wrapper │ └── gradle-wrapper.properties ├── settings.gradle ├── README.md └── LICENSE /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "gradle" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | -------------------------------------------------------------------------------- /ai/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /menubar/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /collaborator/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /contextmenu/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /customlogger/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /helloworld/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /httphandler/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /persistence/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /proxyhandler/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | .idea 25 | .gradle 26 | .DS_Store 27 | build/ 28 | out/ 29 | dist/ 30 | -------------------------------------------------------------------------------- /customscanchecks/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /eventlisteners/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /intruderpayloads/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /trafficredirector/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /websockethandler/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /customrequesteditortab/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /customsessiontokens/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /proxywebsockethandler/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /customscaninsertionpoints/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | } 16 | 17 | jar { 18 | from { 19 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /menubar/README.md: -------------------------------------------------------------------------------- 1 | Menu Bar Example Extension 2 | ============================ 3 | 4 | ###### Registers a top level menu bar with actions. 5 | 6 | --- 7 | 8 | This extension demonstrates registering a top level menu bar item with various actions. 9 | 10 | It demonstrates the following techniques: 11 | - Creating a `BasicMenuItem` with a caption 12 | - Providing an action for a `BasicMenuItem` 13 | - Adding the `Menu` to Burp 14 | - Registering an `ExtensionUnloadingHandler` -------------------------------------------------------------------------------- /multiapi/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.portswigger.burp.extensions.example' 6 | version '1.0.0' 7 | 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly 'net.portswigger.burp.extensions:montoya-api:2025.10' 15 | compileOnly 'net.portswigger.burp.extender:burp-extender-api:2.3' 16 | } 17 | 18 | jar { 19 | from { 20 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 21 | } 22 | } -------------------------------------------------------------------------------- /proxywebsockethandler/src/main/java/MyProxyWebSocketCreationHandler.java: -------------------------------------------------------------------------------- 1 | import burp.api.montoya.proxy.websocket.ProxyWebSocketCreation; 2 | import burp.api.montoya.proxy.websocket.ProxyWebSocketCreationHandler; 3 | 4 | class MyProxyWebSocketCreationHandler implements ProxyWebSocketCreationHandler { 5 | 6 | @Override 7 | public void handleWebSocketCreation(ProxyWebSocketCreation webSocketCreation) { 8 | webSocketCreation.proxyWebSocket().registerProxyMessageHandler(new MyProxyWebSocketMessageHandler()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /websockethandler/README.md: -------------------------------------------------------------------------------- 1 | WebSocket Handler Example Extension 2 | =================================== 3 | 4 | ###### Demonstrates performing various actions on websocket messages passing through any tool in Burp 5 | 6 | --- 7 | 8 | The extension works as follows: 9 | - It registers a web socket created handler 10 | - When a web socket is created 11 | - It sends an initial text message 12 | - It registers a message listener for the websocket 13 | - Any message from the client that contains the text "password" is base64 encoded. 14 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | # 4 | # This code may be used to extend the functionality of Burp Suite Community Edition 5 | # and Burp Suite Professional, provided that this usage does not violate the 6 | # license terms for those products. 7 | # 8 | 9 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip 10 | distributionBase=GRADLE_USER_HOME 11 | distributionPath=wrapper/dists 12 | zipStorePath=wrapper/dists 13 | zipStoreBase=GRADLE_USER_HOME 14 | -------------------------------------------------------------------------------- /helloworld/README.md: -------------------------------------------------------------------------------- 1 | Hello World Example Extension 2 | ============================ 3 | 4 | ###### Prints output to various locations within Burp. 5 | 6 | --- 7 | 8 | This extension is about as basic as things can get, while actually 9 | doing something. 10 | 11 | It demonstrates the following techniques: 12 | - Setting the name of the extension, which will be shown to the user in the UI. 13 | - Writing messages to the output and error streams. 14 | - Writing messages to the main Burp alerts log. 15 | - Generating an exception to demonstrate how this is reported to the user. -------------------------------------------------------------------------------- /eventlisteners/README.md: -------------------------------------------------------------------------------- 1 | Event Listeners Example Extension 2 | ============================ 3 | 4 | ###### Registers handlers for various runtime events, and prints a message when each event occurs. 5 | 6 | --- 7 | 8 | This extension demonstrates how to register listeners for various runtime 9 | events: 10 | - HTTP requests and responses for all Burp tools. 11 | - HTTP messages intercepted by the Proxy. 12 | - Addition of new scan issues. 13 | - The extension being unloaded by the user. 14 | 15 | The sample extension simply prints a message to the output stream when an event 16 | occurs. -------------------------------------------------------------------------------- /collaborator/src/main/java/example/collaborator/poller/InteractionHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.collaborator.poller; 10 | 11 | import burp.api.montoya.collaborator.Interaction; 12 | 13 | public interface InteractionHandler 14 | { 15 | void handleInteraction(Interaction interaction); 16 | } 17 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include 'helloworld' 2 | include 'eventlisteners' 3 | include 'httphandler' 4 | include 'multiapi' 5 | include 'proxyhandler' 6 | include 'trafficredirector' 7 | include 'customrequesteditortab' 8 | include 'customscaninsertionpoints' 9 | include 'customscannerchecks' 10 | include 'customscanchecks' 11 | include 'customsessiontokens' 12 | include 'intruderpayloads' 13 | include 'customlogger' 14 | include 'persistence' 15 | include 'menubar' 16 | 17 | include 'proxywebsockethandler' 18 | include 'websockethandler' 19 | include 'contextmenu' 20 | include 'collaborator' 21 | 22 | include 'ai' 23 | -------------------------------------------------------------------------------- /proxywebsockethandler/README.md: -------------------------------------------------------------------------------- 1 | Proxy WebSocket Handler Example Extension 2 | ========================================= 3 | 4 | ###### Demonstrates performing various actions on websocket messages passing through the Proxy 5 | 6 | --- 7 | 8 | The extension works as follows: 9 | - It registers a Proxy web socket creation handler 10 | - When a Proxy web socket is created 11 | - It registers a proxy web socket message listener for the created websocket 12 | - Any message that contains the text "username" is highlighted in red. 13 | - Any message from the client that contains the text "password" is force intercepted. 14 | -------------------------------------------------------------------------------- /httphandler/README.md: -------------------------------------------------------------------------------- 1 | HTTP Handler Example Extension 2 | ============================ 3 | 4 | ###### Demonstrates performing various actions on requests passing through any tool in Burp 5 | 6 | --- 7 | 8 | The extension works as follows: 9 | - It registers an HTTP handler 10 | - For outgoing request messages: 11 | - If the request is a `POST` request: 12 | - The body of the request is logged to output 13 | - A comment is added to the request 14 | - A URL parameter is added to the request 15 | - For incoming response messages: 16 | - If the corresponding request contained a `Content-Length` header, a `BLUE` highlight is added -------------------------------------------------------------------------------- /websockethandler/src/main/java/WebSocketHandlerExample.java: -------------------------------------------------------------------------------- 1 | import burp.api.montoya.BurpExtension; 2 | import burp.api.montoya.MontoyaApi; 3 | 4 | //Burp will auto-detect and load any class that extends BurpExtension. 5 | public class WebSocketHandlerExample implements BurpExtension { 6 | 7 | @Override 8 | public void initialize(MontoyaApi api) { 9 | api.extension().setName("WebSocket Handler Example"); 10 | 11 | //Register web socket handler with Burp. 12 | MyWebSocketCreatedHandler exampleWebSocketCreationHandler = new MyWebSocketCreatedHandler(api); 13 | api.websockets().registerWebSocketCreatedHandler(exampleWebSocketCreationHandler); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /customlogger/README.md: -------------------------------------------------------------------------------- 1 | Custom Logger Example Extension 2 | ============================ 3 | 4 | ###### Adds a new tab to Burp's UI and displays a log of HTTP traffic for all Burp tools. 5 | 6 | --- 7 | 8 | This extension provides a suite-wide HTTP logger within the main Burp UI. 9 | 10 | The extension uses the following techniques: 11 | - It creates a custom tab within the main Burp UI, in which to display logging user interface 12 | - It displays a table of items and a read-only editor for requests and responses within a splitpane 13 | - When an item passes through the HttpHandler, it gets added to the table 14 | - You can view the request and response for an item in the table by clicking on the relevant row -------------------------------------------------------------------------------- /contextmenu/README.md: -------------------------------------------------------------------------------- 1 | Context Menu Example Extension 2 | ============================ 3 | 4 | ###### Registers new context menu items to print requests and responses. 5 | 6 | --- 7 | This extension adds a new context menu item to print out the request or response of an HttpRequestResponse in the Target, Proxy or Logger tab. 8 | 9 | The sample extension demonstrates the following techniques: 10 | - Registering a new `ContextMenuItemsProvider`. 11 | - Creating a `JMenuItem`. 12 | - Adding an action listener to a `JMenuItem`. 13 | - If you right-click in a message editor context, it will use the item from the message editor. 14 | - If you right-click on a table item, it will print the request/response for the first selected item. -------------------------------------------------------------------------------- /proxywebsockethandler/src/main/java/ProxyWebSocketHandlerExample.java: -------------------------------------------------------------------------------- 1 | import burp.api.montoya.BurpExtension; 2 | import burp.api.montoya.MontoyaApi; 3 | 4 | //Burp will auto-detect and load any class that extends BurpExtension. 5 | public class ProxyWebSocketHandlerExample implements BurpExtension { 6 | 7 | @Override 8 | public void initialize(MontoyaApi api) { 9 | api.extension().setName("Proxy Websocket Handler Example"); 10 | 11 | //Register proxy web socket handler with Burp. 12 | MyProxyWebSocketCreationHandler exampleWebSocketCreationHandler = new MyProxyWebSocketCreationHandler(); 13 | api.proxy().registerWebSocketCreationHandler(exampleWebSocketCreationHandler); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /websockethandler/src/main/java/MyWebSocketCreatedHandler.java: -------------------------------------------------------------------------------- 1 | import burp.api.montoya.MontoyaApi; 2 | import burp.api.montoya.websocket.WebSocketCreated; 3 | import burp.api.montoya.websocket.WebSocketCreatedHandler; 4 | 5 | class MyWebSocketCreatedHandler implements WebSocketCreatedHandler { 6 | 7 | private final MontoyaApi api; 8 | 9 | MyWebSocketCreatedHandler(MontoyaApi api) { 10 | this.api = api; 11 | } 12 | 13 | @Override 14 | public void handleWebSocketCreated(WebSocketCreated webSocketCreated) { 15 | webSocketCreated.webSocket().sendTextMessage("First Message"); 16 | 17 | webSocketCreated.webSocket().registerMessageHandler(new MyWebSocketMessageHandler(api)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /customscanchecks/src/main/java/example/customscanchecks/CustomScanChecks.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.customscanchecks; 10 | 11 | import burp.api.montoya.BurpExtension; 12 | import burp.api.montoya.MontoyaApi; 13 | 14 | public class CustomScanChecks implements BurpExtension 15 | { 16 | @Override 17 | public void initialize(MontoyaApi api) 18 | { 19 | api.extension().setName("Custom Scanner checks"); 20 | 21 | api.scanner().registerScanCheck(new MyScanCheck(api)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /multiapi/README.md: -------------------------------------------------------------------------------- 1 | Multi-API Example Extension 2 | ============================ 3 | 4 | ###### Demonstrates using both the Montoya API and the legacy Extender API in one extension 5 | 6 | --- 7 | 8 | This extension works as follows: 9 | - `registerExtenderCallbacks()` is called 10 | - It registers an extension name 11 | - It also includes `http://test.url` as an in-scope URL 12 | - `initialize()`is called 13 | - It registers a new Suite tab 14 | - Registers an extension name, which overwrites the `registerExtenderCallbacks()` name 15 | - Checks whether `http://test.url` is in scope, and writes an alert to the Dashboard 16 | - The new Suite tab contains a button 17 | - When the button is used, the filename according to both the Wiener API and Montoya API are printed to the output -------------------------------------------------------------------------------- /persistence/README.md: -------------------------------------------------------------------------------- 1 | Persistence Example Extension 2 | ============================ 3 | 4 | ###### Demonstrates saving and loading data to the project file. 5 | 6 | --- 7 | 8 | The extension works as follows: 9 | - It saves and loads a simple incrementing integer value with the project file. 10 | - Sends to the event log how many times Burp or the extension were restarted. 11 | - It saves and loads extension built http requests 12 | - Sends the requests to repeater with an incrementing tab counter when Burp is restarted or the extension is reloaded. 13 | - It saves the last 5 requests/responses issued by Burp 14 | - Prints the last 5 request/responses to the output log when burp is restarted or the extension is reloaded. 15 | - Uses Persisted Lists to automatically save/load data stored in the list. -------------------------------------------------------------------------------- /proxyhandler/README.md: -------------------------------------------------------------------------------- 1 | Proxy Handler Example Extension 2 | ============================ 3 | 4 | ###### Demonstrates performing various actions on requests passing through the Proxy 5 | 6 | --- 7 | 8 | The extension works as follows: 9 | - It registers a Proxy handler 10 | - For outgoing request messages: 11 | - It drops all `POST` requests 12 | - Requests with `foo` in the URL are not intercepted 13 | - If the `Content-Type` is `JSON`, the request is highlighted `RED` and Burp rules for Interception are followed 14 | - All other requests are intercepted 15 | - User modified requests are continued as normal 16 | - For incoming response messages: 17 | - All responses that contain the string `username` are highlighted `BLUE` 18 | - All other responses follow Burp rules for Interception -------------------------------------------------------------------------------- /contextmenu/src/main/java/example/contextmenu/ContextMenu.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.contextmenu; 10 | 11 | import burp.api.montoya.BurpExtension; 12 | import burp.api.montoya.MontoyaApi; 13 | 14 | public class ContextMenu implements BurpExtension 15 | { 16 | @Override 17 | public void initialize(MontoyaApi api) 18 | { 19 | api.extension().setName("Context menu extension"); 20 | 21 | api.userInterface().registerContextMenuItemsProvider(new MyContextMenuItemsProvider(api)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /customrequesteditortab/README.md: -------------------------------------------------------------------------------- 1 | Custom Request Editor Tab Example Extension 2 | ============================ 3 | 4 | ###### Adds a new tab to Burp's HTTP message editor, in order to handle a data serialization format 5 | 6 | --- 7 | 8 | This extension provides a new tab on the message editor for requests that contain a specified parameter. 9 | 10 | The extension uses the following techniques: 11 | - It creates a custom request tab on the message editor, provided that the `data` parameter is present 12 | - If it is appropriate, the editor is set to be read-only 13 | - The value of the `data` parameter is deserialized (URL decoded, then Base64 decoded) and displayed in the custom tab 14 | - If the value of the data is modified, the content will be re-serialized (Base64 encoded then URL encoded) and updated in the HttpRequest -------------------------------------------------------------------------------- /customscaninsertionpoints/src/main/java/example/customscaninsertionpoints/CustomScanInsertionPoints.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.customscaninsertionpoints; 10 | 11 | import burp.api.montoya.BurpExtension; 12 | import burp.api.montoya.MontoyaApi; 13 | 14 | public class CustomScanInsertionPoints implements BurpExtension 15 | { 16 | @Override 17 | public void initialize(MontoyaApi api) 18 | { 19 | api.extension().setName("Custom scan insertion points"); 20 | 21 | api.scanner().registerInsertionPointProvider(new MyInsertionPointProvider(api)); 22 | } 23 | } -------------------------------------------------------------------------------- /customrequesteditortab/src/main/java/example/customrequesteditortab/CustomRequestEditorTab.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.customrequesteditortab; 10 | 11 | import burp.api.montoya.BurpExtension; 12 | import burp.api.montoya.MontoyaApi; 13 | 14 | public class CustomRequestEditorTab implements BurpExtension 15 | { 16 | @Override 17 | public void initialize(MontoyaApi api) 18 | { 19 | api.extension().setName("Serialized input editor"); 20 | 21 | api.userInterface().registerHttpRequestEditorProvider(new MyHttpRequestEditorProvider(api)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /intruderpayloads/src/main/java/example/intruderpayloads/IntruderPayloads.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.intruderpayloads; 10 | 11 | import burp.api.montoya.BurpExtension; 12 | import burp.api.montoya.MontoyaApi; 13 | 14 | public class IntruderPayloads implements BurpExtension 15 | { 16 | @Override 17 | public void initialize(MontoyaApi api) 18 | { 19 | api.extension().setName("Intruder payloads"); 20 | 21 | api.intruder().registerPayloadGeneratorProvider(new MyPayloadGeneratorProvider()); 22 | api.intruder().registerPayloadProcessor(new MyPayloadProcessor(api)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /customscanchecks/README.md: -------------------------------------------------------------------------------- 1 | Custom Scan Checks Example Extension 2 | ============================ 3 | 4 | ###### Implements custom checks to extend the capabilities of Burp's active and passive scanning engines. 5 | 6 | --- 7 | 8 | The sample extension demonstrates the following techniques: 9 | - Registering a custom scan check 10 | - Performing passive and active scanning when initiated by the user 11 | - Using the Burp-provided `AuditInsertionPoint` to construct requests for active scanning using specified payloads 12 | - Using a helper method to search responses for relevant match strings 13 | - Providing an `MarkedHttpRequestResponse` to highlight relevant portions of requests and responses, 14 | - Synchronously reporting custom scan issues in response to the relevant checks. 15 | - Guiding Burp on when to consolidate duplicated issues at the same URL (e.g., when the user has scanned the same item multiple times). -------------------------------------------------------------------------------- /customscaninsertionpoints/README.md: -------------------------------------------------------------------------------- 1 | Custom Scan Checks Example Extension 2 | ============================ 3 | 4 | ###### Provides custom attack insertion points for active scanning. 5 | 6 | --- 7 | 8 | The sample extension demonstrates the following techniques: 9 | - Registering a custom `AuditInsertionPointProvider` 10 | - If the request contains the `data` parameter, it will provide a custom `AuditInsertionPoint` 11 | - The custom `AuditInsertionPoint` will perform the following: 12 | - Deserialize the data (URL decode and then Base64 decode) 13 | - Parse the location of the `input=` string withing the decoded data 14 | - Split the data into a prefix, location to place the payload, and a suffix 15 | - When building the request with the appropriate payload, it will perform the following: 16 | - Build the raw data with the appropriate payload 17 | - Re-serialize the data (Base64 encode then URL encode) -------------------------------------------------------------------------------- /customsessiontokens/src/main/java/example/customsessiontokens/CustomSessionTokens.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.customsessiontokens; 10 | 11 | import burp.api.montoya.BurpExtension; 12 | import burp.api.montoya.MontoyaApi; 13 | 14 | //Burp will auto-detect and load any class that extends BurpExtension. 15 | public class CustomSessionTokens implements BurpExtension 16 | { 17 | @Override 18 | public void initialize(MontoyaApi api) 19 | { 20 | api.extension().setName("Session token example"); 21 | 22 | api.http().registerSessionHandlingAction(new MySessionHandlingAction()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /httphandler/src/main/java/example/httphandler/HttpHandlerExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.httphandler; 10 | 11 | import burp.api.montoya.BurpExtension; 12 | import burp.api.montoya.MontoyaApi; 13 | 14 | 15 | //Burp will auto-detect and load any class that extends BurpExtension. 16 | public class HttpHandlerExample implements BurpExtension { 17 | @Override 18 | public void initialize(MontoyaApi api) { 19 | api.extension().setName("HTTP Handler Example"); 20 | 21 | //Register our http handler with Burp. 22 | api.http().registerHttpHandler(new MyHttpHandler(api)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /menubar/src/main/java/example/menubar/MyExtensionUnloadingHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.menubar; 10 | 11 | import burp.api.montoya.MontoyaApi; 12 | import burp.api.montoya.extension.ExtensionUnloadingHandler; 13 | 14 | public class MyExtensionUnloadingHandler implements ExtensionUnloadingHandler 15 | { 16 | private final MontoyaApi api; 17 | 18 | public MyExtensionUnloadingHandler(MontoyaApi api) 19 | { 20 | this.api = api; 21 | } 22 | 23 | @Override 24 | public void extensionUnloaded() 25 | { 26 | api.logging().logToOutput("Extension has been unloaded."); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /customsessiontokens/README.md: -------------------------------------------------------------------------------- 1 | Custom Session Tokens Example Extension 2 | ============================ 3 | 4 | ###### Demonstrates working with custom session tokens that Burp doesn't normally understand. 5 | 6 | --- 7 | 8 | This example demonstrates how you can couple a recorded macro with an extension to automatically gain a session token for a website and use it in later requests that Burp makes. 9 | 10 | The macro mechanism that Burp provides allows you to record the request triggering creation of a session made via the proxy. 11 | 12 | The extension uses the following techniques: 13 | - Registers a `SessionHandlingAction` handler 14 | - Fetches the list of macro requests and responses 15 | - Extracts the response headers from the last `HttprequestResponse` item in the list 16 | - Finds the relevant session header (in this example, this header is `X-Custom-Session-Id`) 17 | - Returns an `HttpRequest` with an updated session header -------------------------------------------------------------------------------- /ai/src/main/java/example/ai/MyPromptMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.ai; 10 | 11 | import burp.api.montoya.ai.chat.Message; 12 | 13 | import static burp.api.montoya.ai.chat.Message.systemMessage; 14 | import static burp.api.montoya.ai.chat.Message.userMessage; 15 | 16 | public class MyPromptMessage 17 | { 18 | private final Message systemMessage; 19 | 20 | public MyPromptMessage(String systemPrompt) 21 | { 22 | systemMessage = systemMessage(systemPrompt); 23 | } 24 | 25 | public Message[] build(String userPrompt) 26 | { 27 | return new Message[]{systemMessage, userMessage(userPrompt)}; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /intruderpayloads/src/main/java/example/intruderpayloads/MyPayloadGeneratorProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.intruderpayloads; 10 | 11 | import burp.api.montoya.intruder.AttackConfiguration; 12 | import burp.api.montoya.intruder.PayloadGenerator; 13 | import burp.api.montoya.intruder.PayloadGeneratorProvider; 14 | 15 | public class MyPayloadGeneratorProvider implements PayloadGeneratorProvider 16 | { 17 | @Override 18 | public String displayName() 19 | { 20 | return "My custom payloads"; 21 | } 22 | 23 | @Override 24 | public PayloadGenerator providePayloadGenerator(AttackConfiguration attackConfiguration) 25 | { 26 | return new MyPayloadGenerator(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /proxyhandler/src/main/java/example/proxyhandler/ProxyHandlerExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.proxyhandler; 10 | 11 | import burp.api.montoya.BurpExtension; 12 | import burp.api.montoya.MontoyaApi; 13 | 14 | //Burp will auto-detect and load any class that extends BurpExtension. 15 | public class ProxyHandlerExample implements BurpExtension 16 | { 17 | @Override 18 | public void initialize(MontoyaApi api) 19 | { 20 | api.extension().setName("Proxy Handler Example"); 21 | 22 | //Register proxy handlers with Burp. 23 | api.proxy().registerRequestHandler(new MyProxyHttpRequestHandler()); 24 | api.proxy().registerResponseHandler(new MyProxyHttpResponseHandler()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /trafficredirector/README.md: -------------------------------------------------------------------------------- 1 | Traffic Redirector Example Extension 2 | ============================ 3 | 4 | ###### Redirects all outbound requests from one host to another. 5 | 6 | --- 7 | 8 | This extension demonstrates how to redirect outgoing HTTP requests from one host to another. This task might arise, for example, if you have mapped out an application which then moves to a different staging URL. By simply redirecting traffic to the new hostname, you can continue to drive your testing from the original site map. 9 | 10 | The extension works as follows: 11 | - It registers an HTTP handler. 12 | - For outgoing request messages, it retrieves the HTTP service for the request. 13 | - If the HTTP service host matches the "from" host, builds an HTTP service using the "to" host, and other details unchanged. 14 | - It returns the HTTP request with the new HTTP service. 15 | 16 | **Note:** The sample code uses "host1.example.org" and "host2.example.org" as the "from" and "to" hostnames. You should edit the code to use your own hostnames before using it. -------------------------------------------------------------------------------- /trafficredirector/src/main/java/example/trafficredirector/TrafficRedirector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.trafficredirector; 10 | 11 | import burp.api.montoya.BurpExtension; 12 | import burp.api.montoya.MontoyaApi; 13 | 14 | //Burp will auto-detect and load any class that extends BurpExtension. 15 | public class TrafficRedirector implements BurpExtension { 16 | static final String HOST_FROM = "host1.example.org"; 17 | static final String HOST_TO = "host2.example.org"; 18 | 19 | @Override 20 | public void initialize(MontoyaApi api) { 21 | // set extension name 22 | api.extension().setName("Traffic redirector"); 23 | 24 | // register a new HTTP handler 25 | api.http().registerHttpHandler(new MyHttpHandler()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /websockethandler/src/main/java/MyWebSocketMessageHandler.java: -------------------------------------------------------------------------------- 1 | import burp.api.montoya.MontoyaApi; 2 | import burp.api.montoya.websocket.*; 3 | 4 | import static burp.api.montoya.websocket.Direction.CLIENT_TO_SERVER; 5 | 6 | class MyWebSocketMessageHandler implements MessageHandler { 7 | 8 | private final MontoyaApi api; 9 | 10 | public MyWebSocketMessageHandler(MontoyaApi api) { 11 | this.api = api; 12 | } 13 | 14 | @Override 15 | public TextMessageAction handleTextMessage(TextMessage textMessage) { 16 | if (textMessage.direction() == CLIENT_TO_SERVER && textMessage.payload().contains("password")) { 17 | String base64EncodedPayload = api.utilities().base64Utils().encodeToString(textMessage.payload()); 18 | 19 | return TextMessageAction.continueWith(base64EncodedPayload); 20 | } 21 | 22 | return TextMessageAction.continueWith(textMessage); 23 | } 24 | 25 | @Override 26 | public BinaryMessageAction handleBinaryMessage(BinaryMessage binaryMessage) { 27 | return BinaryMessageAction.continueWith(binaryMessage); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /customlogger/src/main/java/example/customlogger/MyHttpHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.customlogger; 10 | 11 | import burp.api.montoya.http.handler.*; 12 | 13 | public class MyHttpHandler implements HttpHandler 14 | { 15 | private final MyTableModel tableModel; 16 | 17 | public MyHttpHandler(MyTableModel tableModel) 18 | { 19 | 20 | this.tableModel = tableModel; 21 | } 22 | 23 | @Override 24 | public RequestToBeSentAction handleHttpRequestToBeSent(HttpRequestToBeSent requestToBeSent) 25 | { 26 | return RequestToBeSentAction.continueWith(requestToBeSent); 27 | } 28 | 29 | @Override 30 | public ResponseReceivedAction handleHttpResponseReceived(HttpResponseReceived responseReceived) 31 | { 32 | tableModel.add(responseReceived); 33 | return ResponseReceivedAction.continueWith(responseReceived); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /customrequesteditortab/src/main/java/example/customrequesteditortab/MyHttpRequestEditorProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.customrequesteditortab; 10 | 11 | import burp.api.montoya.MontoyaApi; 12 | import burp.api.montoya.ui.editor.extension.EditorCreationContext; 13 | import burp.api.montoya.ui.editor.extension.ExtensionProvidedHttpRequestEditor; 14 | import burp.api.montoya.ui.editor.extension.HttpRequestEditorProvider; 15 | 16 | class MyHttpRequestEditorProvider implements HttpRequestEditorProvider 17 | { 18 | private final MontoyaApi api; 19 | 20 | MyHttpRequestEditorProvider(MontoyaApi api) 21 | { 22 | this.api = api; 23 | } 24 | 25 | @Override 26 | public ExtensionProvidedHttpRequestEditor provideHttpRequestEditor(EditorCreationContext creationContext) 27 | { 28 | return new MyExtensionProvidedHttpRequestEditor(api, creationContext); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /intruderpayloads/src/main/java/example/intruderpayloads/MyPayloadGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.intruderpayloads; 10 | 11 | import burp.api.montoya.intruder.GeneratedPayload; 12 | import burp.api.montoya.intruder.IntruderInsertionPoint; 13 | import burp.api.montoya.intruder.PayloadGenerator; 14 | 15 | import java.util.List; 16 | 17 | public class MyPayloadGenerator implements PayloadGenerator 18 | { 19 | private static final List PAYLOADS = List.of("|", ""); 20 | private int payloadIndex; 21 | 22 | @Override 23 | public GeneratedPayload generatePayloadFor(IntruderInsertionPoint insertionPoint) 24 | { 25 | payloadIndex++; 26 | 27 | if (payloadIndex > PAYLOADS.size()) 28 | { 29 | return GeneratedPayload.end(); 30 | } 31 | 32 | String payload = PAYLOADS.get(payloadIndex); 33 | 34 | return GeneratedPayload.payload(payload); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /collaborator/README.md: -------------------------------------------------------------------------------- 1 | Collaborator Example Extension 2 | ============================ 3 | 4 | ###### Demonstrates using Collaborator and Persistence functionality. 5 | 6 | --- 7 | This extension demonstrates creating a `CollaboratorClient`, polling the Collaborator Server and saving the Collaborator `SecretKey` to the project file using Persistence. 8 | 9 | The sample extension demonstrates the following techniques: 10 | - Creating a Collaborator Client 11 | - If the extension has been previously loaded in the project file, it restores the previously used `CollaboratorClient` 12 | - If this is the first time the extension has been loaded in this project file, it creates a new `CollaboratorClient` and saves the `SecretKey` to the project file 13 | - Registers a `ProxyRequestHandler` to insert Collaborator payloads into requests 14 | - Polls the Collaborator Server for asynchronous interactions 15 | - Logs any discovered interactions to the extension Output tab 16 | - When the extension is unloaded or Burp Suite is closed, the extension stops polling the Collaborator server 17 | 18 | You can test this extension on the following URL: https://portswigger-labs.net/ssrf-dns.php 19 | 20 | The `poller` package has been designed to be easily reused in other extensions. -------------------------------------------------------------------------------- /intruderpayloads/README.md: -------------------------------------------------------------------------------- 1 | Custom Intruder Payloads Example Extension 2 | ============================ 3 | 4 | ###### Provides custom Intruder payloads and payload processing. 5 | 6 | --- 7 | 8 | This example shows how you can use an extension to: 9 | - Generate custom Intruder payloads 10 | - Apply custom processing to Intruder payloads (including built-in ones) 11 | 12 | When an extension registers itself as an Intruder payload provider, this will be available within the Intruder UI for the user to select as the payload source for an attack. When an extension registers itself as a payload processor, the user can create a payload processing rule and select the extension's processor as the rule's action. 13 | 14 | The extension uses the following techniques: 15 | - Registers a new `PayloadGeneratorProvider`, which returns a new `PayloadGenerator` 16 | - Registers a new `PayloadProcessor` 17 | - The `PayloadGenerator` does the following: 18 | - Contains a list of payloads to be used 19 | - Iterates through the payload list, until there are no longer any payloads available 20 | - The `PayloadProcessor` does the following: 21 | - Decodes the base value of the payload 22 | - Parses the location of the `input` string in the decoded data 23 | - Rebuilds the serialized data with the new payload -------------------------------------------------------------------------------- /menubar/src/main/java/example/menubar/MenuBar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.menubar; 10 | 11 | import burp.api.montoya.BurpExtension; 12 | import burp.api.montoya.MontoyaApi; 13 | import burp.api.montoya.ui.menu.BasicMenuItem; 14 | import burp.api.montoya.ui.menu.Menu; 15 | import burp.api.montoya.ui.menu.MenuItem; 16 | 17 | public class MenuBar implements BurpExtension 18 | { 19 | @Override 20 | public void initialize(MontoyaApi api) 21 | { 22 | api.extension().setName("Add menu bar"); 23 | api.logging().logToOutput("Extension has been loaded."); 24 | 25 | BasicMenuItem alertEventItem = BasicMenuItem.basicMenuItem("Raise critical alert").withAction(() -> api.logging().raiseCriticalEvent("Alert from extension")); 26 | 27 | BasicMenuItem basicMenuItem = MenuItem.basicMenuItem("Unload extension"); 28 | MenuItem unloadExtensionItem = basicMenuItem.withAction(() -> api.extension().unload()); 29 | 30 | Menu menu = Menu.menu("Menu bar").withMenuItems(alertEventItem, unloadExtensionItem); 31 | 32 | api.userInterface().menuBar().registerMenu(menu); 33 | 34 | api.extension().registerUnloadingHandler(new MyExtensionUnloadingHandler(api)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /eventlisteners/src/main/java/example/eventlisteners/MyHttpHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.eventlisteners; 10 | 11 | import burp.api.montoya.MontoyaApi; 12 | import burp.api.montoya.http.handler.*; 13 | import burp.api.montoya.logging.Logging; 14 | 15 | public class MyHttpHandler implements HttpHandler 16 | { 17 | private final Logging logging; 18 | 19 | public MyHttpHandler(MontoyaApi api) 20 | { 21 | logging = api.logging(); 22 | } 23 | 24 | @Override 25 | public RequestToBeSentAction handleHttpRequestToBeSent(HttpRequestToBeSent httpRequestToBeSent) { 26 | logging.logToOutput("HTTP request to " + httpRequestToBeSent.httpService() + " [" + httpRequestToBeSent.toolSource().toolType().toolName() + "]"); 27 | 28 | return RequestToBeSentAction.continueWith(httpRequestToBeSent); 29 | } 30 | 31 | @Override 32 | public ResponseReceivedAction handleHttpResponseReceived(HttpResponseReceived httpResponseReceived) { 33 | logging.logToOutput("HTTP response from " + httpResponseReceived.initiatingRequest().httpService() + " [" + httpResponseReceived.toolSource().toolType().toolName() + "]"); 34 | 35 | return ResponseReceivedAction.continueWith(httpResponseReceived); 36 | } 37 | } -------------------------------------------------------------------------------- /collaborator/src/main/java/example/collaborator/InteractionLogger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.collaborator; 10 | 11 | import burp.api.montoya.MontoyaApi; 12 | import burp.api.montoya.collaborator.Interaction; 13 | 14 | import java.util.List; 15 | 16 | import static java.lang.String.format; 17 | 18 | public class InteractionLogger 19 | { 20 | private final MontoyaApi api; 21 | 22 | public InteractionLogger(MontoyaApi api) 23 | { 24 | this.api = api; 25 | } 26 | 27 | public void logInteractions(List allInteractions) 28 | { 29 | api.logging().logToOutput(allInteractions.size() + " unread interactions."); 30 | 31 | for (Interaction allInteraction : allInteractions) 32 | { 33 | logInteraction(allInteraction); 34 | } 35 | } 36 | 37 | public void logInteraction(Interaction interaction) 38 | { 39 | api.logging().logToOutput( 40 | format( 41 | """ 42 | Interaction type: %s 43 | Interaction ID: %s 44 | """, 45 | interaction.type().name(), 46 | interaction.id() 47 | ) 48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /proxyhandler/src/main/java/example/proxyhandler/MyProxyHttpResponseHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.proxyhandler; 10 | 11 | import burp.api.montoya.proxy.http.InterceptedResponse; 12 | import burp.api.montoya.proxy.http.ProxyResponseHandler; 13 | import burp.api.montoya.proxy.http.ProxyResponseReceivedAction; 14 | import burp.api.montoya.proxy.http.ProxyResponseToBeSentAction; 15 | 16 | import static burp.api.montoya.core.HighlightColor.BLUE; 17 | 18 | class MyProxyHttpResponseHandler implements ProxyResponseHandler { 19 | @Override 20 | public ProxyResponseReceivedAction handleResponseReceived(InterceptedResponse interceptedResponse) { 21 | //Highlight all responses that have username in them 22 | if (interceptedResponse.bodyToString().contains("username")) { 23 | return ProxyResponseReceivedAction.continueWith(interceptedResponse, interceptedResponse.annotations().withHighlightColor(BLUE)); 24 | } 25 | 26 | return ProxyResponseReceivedAction.continueWith(interceptedResponse); 27 | } 28 | 29 | @Override 30 | public ProxyResponseToBeSentAction handleResponseToBeSent(InterceptedResponse interceptedResponse) { 31 | return ProxyResponseToBeSentAction.continueWith(interceptedResponse); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /customscaninsertionpoints/src/main/java/example/customscaninsertionpoints/MyInsertionPointProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.customscaninsertionpoints; 10 | 11 | import burp.api.montoya.MontoyaApi; 12 | import burp.api.montoya.http.message.HttpRequestResponse; 13 | import burp.api.montoya.http.message.params.ParsedHttpParameter; 14 | import burp.api.montoya.scanner.audit.insertionpoint.AuditInsertionPoint; 15 | import burp.api.montoya.scanner.audit.insertionpoint.AuditInsertionPointProvider; 16 | 17 | import java.util.List; 18 | 19 | import static java.util.stream.Collectors.toList; 20 | 21 | class MyInsertionPointProvider implements AuditInsertionPointProvider 22 | { 23 | private final MontoyaApi api; 24 | 25 | MyInsertionPointProvider(MontoyaApi api) 26 | { 27 | this.api = api; 28 | } 29 | 30 | @Override 31 | public List provideInsertionPoints(HttpRequestResponse baseHttpRequestResponse) 32 | { 33 | List parameters = baseHttpRequestResponse.request().parameters(); 34 | 35 | return parameters.stream() 36 | .filter(p -> p.name().equals("data")) 37 | .map(p -> new MyAuditInsertionPoint(api, baseHttpRequestResponse, p)) 38 | .collect(toList()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /eventlisteners/src/main/java/example/eventlisteners/MyProxyRequestHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.eventlisteners; 10 | 11 | import burp.api.montoya.MontoyaApi; 12 | import burp.api.montoya.logging.Logging; 13 | import burp.api.montoya.proxy.http.InterceptedRequest; 14 | import burp.api.montoya.proxy.http.ProxyRequestHandler; 15 | import burp.api.montoya.proxy.http.ProxyRequestReceivedAction; 16 | import burp.api.montoya.proxy.http.ProxyRequestToBeSentAction; 17 | 18 | public class MyProxyRequestHandler implements ProxyRequestHandler 19 | { 20 | private final Logging logging; 21 | 22 | public MyProxyRequestHandler(MontoyaApi api) 23 | { 24 | logging = api.logging(); 25 | } 26 | 27 | @Override 28 | public ProxyRequestReceivedAction handleRequestReceived(InterceptedRequest interceptedRequest) { 29 | logging.logToOutput("Initial intercepted proxy request to " + interceptedRequest.httpService()); 30 | 31 | return ProxyRequestReceivedAction.continueWith(interceptedRequest); 32 | } 33 | 34 | @Override 35 | public ProxyRequestToBeSentAction handleRequestToBeSent(InterceptedRequest interceptedRequest) { 36 | logging.logToOutput("Final intercepted proxy request to " + interceptedRequest.httpService()); 37 | 38 | return ProxyRequestToBeSentAction.continueWith(interceptedRequest); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /proxywebsockethandler/src/main/java/MyProxyWebSocketMessageHandler.java: -------------------------------------------------------------------------------- 1 | import burp.api.montoya.core.HighlightColor; 2 | import burp.api.montoya.proxy.websocket.*; 3 | 4 | import static burp.api.montoya.websocket.Direction.CLIENT_TO_SERVER; 5 | 6 | class MyProxyWebSocketMessageHandler implements ProxyMessageHandler { 7 | 8 | @Override 9 | public TextMessageReceivedAction handleTextMessageReceived(InterceptedTextMessage interceptedTextMessage) { 10 | if (interceptedTextMessage.payload().contains("username")) { 11 | interceptedTextMessage.annotations().setHighlightColor(HighlightColor.RED); 12 | } 13 | 14 | if (interceptedTextMessage.direction() == CLIENT_TO_SERVER && interceptedTextMessage.payload().contains("password")) { 15 | return TextMessageReceivedAction.intercept(interceptedTextMessage); 16 | } 17 | 18 | return TextMessageReceivedAction.continueWith(interceptedTextMessage); 19 | } 20 | 21 | @Override 22 | public TextMessageToBeSentAction handleTextMessageToBeSent(InterceptedTextMessage interceptedTextMessage) { 23 | return TextMessageToBeSentAction.continueWith(interceptedTextMessage); 24 | } 25 | 26 | @Override 27 | public BinaryMessageReceivedAction handleBinaryMessageReceived(InterceptedBinaryMessage interceptedBinaryMessage) { 28 | return BinaryMessageReceivedAction.continueWith(interceptedBinaryMessage); 29 | } 30 | 31 | @Override 32 | public BinaryMessageToBeSentAction handleBinaryMessageToBeSent(InterceptedBinaryMessage interceptedBinaryMessage) { 33 | return BinaryMessageToBeSentAction.continueWith(interceptedBinaryMessage); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /eventlisteners/src/main/java/example/eventlisteners/MyProxyResponseHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.eventlisteners; 10 | 11 | import burp.api.montoya.MontoyaApi; 12 | import burp.api.montoya.logging.Logging; 13 | import burp.api.montoya.proxy.http.InterceptedResponse; 14 | import burp.api.montoya.proxy.http.ProxyResponseHandler; 15 | import burp.api.montoya.proxy.http.ProxyResponseReceivedAction; 16 | import burp.api.montoya.proxy.http.ProxyResponseToBeSentAction; 17 | 18 | public class MyProxyResponseHandler implements ProxyResponseHandler 19 | { 20 | private final Logging logging; 21 | 22 | public MyProxyResponseHandler(MontoyaApi api) 23 | { 24 | logging = api.logging(); 25 | } 26 | 27 | @Override 28 | public ProxyResponseReceivedAction handleResponseReceived(InterceptedResponse interceptedResponse) { 29 | logging.logToOutput("Initial intercepted proxy response from " + interceptedResponse.initiatingRequest().httpService()); 30 | 31 | return ProxyResponseReceivedAction.continueWith(interceptedResponse); 32 | } 33 | 34 | @Override 35 | public ProxyResponseToBeSentAction handleResponseToBeSent(InterceptedResponse interceptedResponse) { 36 | logging.logToOutput("Final intercepted proxy response from " + interceptedResponse.initiatingRequest().httpService()); 37 | 38 | return ProxyResponseToBeSentAction.continueWith(interceptedResponse); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /trafficredirector/src/main/java/example/trafficredirector/MyHttpHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.trafficredirector; 10 | 11 | import burp.api.montoya.http.HttpService; 12 | import burp.api.montoya.http.handler.*; 13 | import burp.api.montoya.http.message.requests.HttpRequest; 14 | 15 | import static burp.api.montoya.http.HttpService.httpService; 16 | import static burp.api.montoya.http.handler.RequestToBeSentAction.continueWith; 17 | 18 | public class MyHttpHandler implements HttpHandler 19 | { 20 | @Override 21 | public RequestToBeSentAction handleHttpRequestToBeSent(HttpRequestToBeSent httpRequestToBeSent) { 22 | HttpService service = httpRequestToBeSent.httpService(); 23 | 24 | if (TrafficRedirector.HOST_FROM.equalsIgnoreCase(service.host())) { 25 | HttpRequest updatedHttpServiceRequest = httpRequestToBeSent.withService(httpService(TrafficRedirector.HOST_TO, service.port(), service.secure())); 26 | HttpRequest updatedHostHeaderRequest = updatedHttpServiceRequest.withUpdatedHeader("Host", TrafficRedirector.HOST_TO); 27 | 28 | return continueWith(updatedHostHeaderRequest); 29 | } 30 | 31 | return continueWith(httpRequestToBeSent); 32 | } 33 | 34 | @Override 35 | public ResponseReceivedAction handleHttpResponseReceived(HttpResponseReceived httpResponseReceived) { 36 | return ResponseReceivedAction.continueWith(httpResponseReceived); 37 | } 38 | } -------------------------------------------------------------------------------- /helloworld/src/main/java/example/helloworld/HelloWorld.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.helloworld; 10 | 11 | import burp.api.montoya.BurpExtension; 12 | import burp.api.montoya.MontoyaApi; 13 | import burp.api.montoya.logging.Logging; 14 | 15 | //Burp will auto-detect and load any class that extends BurpExtension. 16 | public class HelloWorld implements BurpExtension 17 | { 18 | @Override 19 | public void initialize(MontoyaApi api) 20 | { 21 | // set extension name 22 | api.extension().setName("Hello world extension"); 23 | 24 | Logging logging = api.logging(); 25 | 26 | // write a message to our output stream 27 | logging.logToOutput("Hello output."); 28 | 29 | // write a message to our error stream 30 | logging.logToError("Hello error."); 31 | 32 | // write a message to the Burp alerts tab 33 | logging.raiseInfoEvent("Hello info event."); 34 | logging.raiseDebugEvent("Hello debug event."); 35 | logging.raiseErrorEvent("Hello error event."); 36 | logging.raiseCriticalEvent("Hello critical event."); 37 | 38 | // throw an exception that will appear in our error stream 39 | try 40 | { 41 | throw new RuntimeException("Hello exception."); 42 | } 43 | catch (RuntimeException e) 44 | { 45 | logging.logToError("Hello thrown exception.", e); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /collaborator/src/main/java/example/collaborator/MyProxyRequestHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.collaborator; 10 | 11 | import burp.api.montoya.collaborator.CollaboratorClient; 12 | import burp.api.montoya.http.message.params.HttpParameter; 13 | import burp.api.montoya.http.message.requests.HttpRequest; 14 | import burp.api.montoya.proxy.http.InterceptedRequest; 15 | import burp.api.montoya.proxy.http.ProxyRequestHandler; 16 | import burp.api.montoya.proxy.http.ProxyRequestReceivedAction; 17 | import burp.api.montoya.proxy.http.ProxyRequestToBeSentAction; 18 | 19 | public class MyProxyRequestHandler implements ProxyRequestHandler 20 | { 21 | private final CollaboratorClient collaboratorClient; 22 | 23 | public MyProxyRequestHandler(CollaboratorClient collaboratorClient) 24 | { 25 | this.collaboratorClient = collaboratorClient; 26 | } 27 | 28 | @Override 29 | public ProxyRequestReceivedAction handleRequestReceived(InterceptedRequest interceptedRequest) 30 | { 31 | String payload = collaboratorClient.generatePayload().toString(); 32 | 33 | HttpRequest newRequest = interceptedRequest.withParameter(HttpParameter.urlParameter("host", payload)); // Test this on: https://portswigger-labs.net/ssrf-dns.php 34 | 35 | return ProxyRequestReceivedAction.continueWith(newRequest); 36 | } 37 | 38 | @Override 39 | public ProxyRequestToBeSentAction handleRequestToBeSent(InterceptedRequest interceptedRequest) 40 | { 41 | return ProxyRequestToBeSentAction.continueWith(interceptedRequest); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ai/src/main/java/example/ai/AiExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.ai; 10 | 11 | import burp.api.montoya.BurpExtension; 12 | import burp.api.montoya.EnhancedCapability; 13 | import burp.api.montoya.MontoyaApi; 14 | 15 | import java.util.Set; 16 | import java.util.concurrent.ExecutorService; 17 | import java.util.concurrent.Executors; 18 | 19 | import static burp.api.montoya.EnhancedCapability.AI_FEATURES; 20 | 21 | public class AiExample implements BurpExtension 22 | { 23 | public static final String SYSTEM_MESSAGE = """ 24 | You are an API request analyzer. Your job is to determine whether an HTTP request might be related to authentication. 25 | You must analyze the content and context of the request carefully and respond only with "Yes" if the request is related to authentication, or "No" if it is not. 26 | Do not provide any additional information beyond "Yes" or "No." 27 | """; 28 | 29 | @Override 30 | public void initialize(MontoyaApi api) 31 | { 32 | api.extension().setName("AI extension"); 33 | 34 | ExecutorService executorService = Executors.newFixedThreadPool(5); 35 | MyPromptMessage promptMessageHandler = new MyPromptMessage(SYSTEM_MESSAGE); 36 | 37 | api.proxy().registerRequestHandler(new MyProxyRequestHandler(api.ai(), api.logging(), executorService, promptMessageHandler)); 38 | 39 | api.extension().registerUnloadingHandler(executorService::shutdownNow); 40 | } 41 | 42 | @Override 43 | public Set enhancedCapabilities() 44 | { 45 | return Set.of(AI_FEATURES); 46 | } 47 | } -------------------------------------------------------------------------------- /proxyhandler/src/main/java/example/proxyhandler/MyProxyHttpRequestHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.proxyhandler; 10 | 11 | 12 | import burp.api.montoya.proxy.http.InterceptedRequest; 13 | import burp.api.montoya.proxy.http.ProxyRequestHandler; 14 | import burp.api.montoya.proxy.http.ProxyRequestReceivedAction; 15 | import burp.api.montoya.proxy.http.ProxyRequestToBeSentAction; 16 | 17 | import static burp.api.montoya.core.HighlightColor.RED; 18 | import static burp.api.montoya.http.message.ContentType.JSON; 19 | 20 | class MyProxyHttpRequestHandler implements ProxyRequestHandler { 21 | @Override 22 | public ProxyRequestReceivedAction handleRequestReceived(InterceptedRequest interceptedRequest) { 23 | //Drop all post requests 24 | if (interceptedRequest.method().equals("POST")) { 25 | return ProxyRequestReceivedAction.drop(); 26 | } 27 | 28 | //Do not intercept any request with foo in the url 29 | if (interceptedRequest.url().contains("foo")) { 30 | return ProxyRequestReceivedAction.doNotIntercept(interceptedRequest); 31 | } 32 | 33 | //If the content type is json, highlight the request and follow burp rules for interception 34 | if (interceptedRequest.contentType() == JSON) { 35 | return ProxyRequestReceivedAction.continueWith(interceptedRequest, interceptedRequest.annotations().withHighlightColor(RED)); 36 | } 37 | 38 | //Intercept all other requests 39 | return ProxyRequestReceivedAction.intercept(interceptedRequest); 40 | } 41 | 42 | @Override 43 | public ProxyRequestToBeSentAction handleRequestToBeSent(InterceptedRequest interceptedRequest) { 44 | //Do nothing with the user modified request, continue as normal. 45 | return ProxyRequestToBeSentAction.continueWith(interceptedRequest); 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /customlogger/src/main/java/example/customlogger/MyTableModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.customlogger; 10 | 11 | import burp.api.montoya.http.handler.HttpResponseReceived; 12 | 13 | import javax.swing.table.AbstractTableModel; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | public class MyTableModel extends AbstractTableModel 18 | { 19 | private final List log; 20 | 21 | public MyTableModel() 22 | { 23 | this.log = new ArrayList<>(); 24 | } 25 | 26 | @Override 27 | public synchronized int getRowCount() 28 | { 29 | return log.size(); 30 | } 31 | 32 | @Override 33 | public int getColumnCount() 34 | { 35 | return 2; 36 | } 37 | 38 | @Override 39 | public String getColumnName(int column) 40 | { 41 | return switch (column) 42 | { 43 | case 0 -> "Tool"; 44 | case 1 -> "URL"; 45 | default -> ""; 46 | }; 47 | } 48 | 49 | @Override 50 | public synchronized Object getValueAt(int rowIndex, int columnIndex) 51 | { 52 | HttpResponseReceived responseReceived = log.get(rowIndex); 53 | 54 | return switch (columnIndex) 55 | { 56 | case 0 -> responseReceived.toolSource().toolType(); 57 | case 1 -> responseReceived.initiatingRequest().url(); 58 | default -> ""; 59 | }; 60 | } 61 | 62 | public synchronized void add(HttpResponseReceived responseReceived) 63 | { 64 | int index = log.size(); 65 | log.add(responseReceived); 66 | fireTableRowsInserted(index, index); 67 | } 68 | 69 | public synchronized HttpResponseReceived get(int rowIndex) 70 | { 71 | return log.get(rowIndex); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /contextmenu/src/main/java/example/contextmenu/MyContextMenuItemsProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.contextmenu; 10 | 11 | import burp.api.montoya.MontoyaApi; 12 | import burp.api.montoya.core.ToolType; 13 | import burp.api.montoya.http.message.HttpRequestResponse; 14 | import burp.api.montoya.ui.contextmenu.ContextMenuEvent; 15 | import burp.api.montoya.ui.contextmenu.ContextMenuItemsProvider; 16 | 17 | import javax.swing.*; 18 | import java.awt.*; 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | public class MyContextMenuItemsProvider implements ContextMenuItemsProvider 23 | { 24 | 25 | private final MontoyaApi api; 26 | 27 | public MyContextMenuItemsProvider(MontoyaApi api) 28 | { 29 | this.api = api; 30 | } 31 | 32 | @Override 33 | public List provideMenuItems(ContextMenuEvent event) 34 | { 35 | if (event.isFromTool(ToolType.PROXY, ToolType.TARGET, ToolType.LOGGER)) 36 | { 37 | List menuItemList = new ArrayList<>(); 38 | 39 | JMenuItem retrieveRequestItem = new JMenuItem("Print request"); 40 | JMenuItem retrieveResponseItem = new JMenuItem("Print response"); 41 | 42 | HttpRequestResponse requestResponse = event.messageEditorRequestResponse().isPresent() ? event.messageEditorRequestResponse().get().requestResponse() : event.selectedRequestResponses().get(0); 43 | 44 | retrieveRequestItem.addActionListener(l -> api.logging().logToOutput("Request is:\r\n" + requestResponse.request().toString())); 45 | menuItemList.add(retrieveRequestItem); 46 | 47 | if (requestResponse.response() != null) 48 | { 49 | retrieveResponseItem.addActionListener(l -> api.logging().logToOutput("Response is:\r\n" + requestResponse.response().toString())); 50 | menuItemList.add(retrieveResponseItem); 51 | } 52 | 53 | return menuItemList; 54 | } 55 | 56 | return null; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /persistence/src/main/java/example/persistence/PersistenceExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.persistence; 10 | 11 | import burp.api.montoya.BurpExtension; 12 | import burp.api.montoya.MontoyaApi; 13 | import burp.api.montoya.persistence.PersistedObject; 14 | 15 | //Burp will auto-detect and load any class that extends BurpExtension. 16 | public class PersistenceExample implements BurpExtension { 17 | 18 | static final String STARTUP_COUNT_KEY = "Startup Count"; 19 | 20 | @Override 21 | public void initialize(MontoyaApi api) { 22 | //Extension data will use the extension name to save/load for that specific extension 23 | api.extension().setName("Persistence example extension"); 24 | 25 | PersistedObject myExtensionData = api.persistence().extensionData(); 26 | 27 | //Retrieve an integer value from the project file 28 | Integer startupCount = myExtensionData.getInteger(STARTUP_COUNT_KEY); 29 | 30 | //If a value is null, it does not exist in the project file. 31 | //We could also check if the key exists 32 | //e.g. myExtensionData.integerKeys().contains(STARTUP_COUNT_KEY) 33 | if (startupCount == null) { 34 | startupCount = 0; 35 | } 36 | 37 | //Set an integer value in the project file 38 | myExtensionData.setInteger(STARTUP_COUNT_KEY, startupCount + 1); 39 | 40 | //Retrieve the updated value and create a info event. 41 | api.logging().raiseInfoEvent("Startup count is: " + myExtensionData.getInteger(STARTUP_COUNT_KEY)); 42 | 43 | advancedExamples(api); 44 | } 45 | 46 | private static void advancedExamples(MontoyaApi api) { 47 | //Advanced example saving and loading requests. 48 | SavingLoadingRequests savingLoadingRequests = new SavingLoadingRequests(api); 49 | savingLoadingRequests.runExample(); 50 | 51 | //More advanced example working with Lists of HttpRequestResponse. 52 | RequestResponseLogging requestLogging = new RequestResponseLogging(api); 53 | requestLogging.runExample(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /collaborator/src/main/java/example/collaborator/poller/Poller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.collaborator.poller; 10 | 11 | import burp.api.montoya.collaborator.CollaboratorClient; 12 | import burp.api.montoya.collaborator.Interaction; 13 | 14 | import java.time.Duration; 15 | import java.util.LinkedList; 16 | import java.util.List; 17 | import java.util.concurrent.ScheduledFuture; 18 | import java.util.concurrent.ScheduledThreadPoolExecutor; 19 | import java.util.concurrent.TimeUnit; 20 | 21 | public class Poller 22 | { 23 | private final CollaboratorClient collaboratorClient; 24 | private final Duration pollInterval; 25 | private final List interactionHandlers; 26 | private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor; 27 | private ScheduledFuture schedule; 28 | 29 | public Poller(CollaboratorClient collaboratorClient, Duration pollInterval) 30 | { 31 | this.collaboratorClient = collaboratorClient; 32 | this.pollInterval = pollInterval; 33 | this.interactionHandlers = new LinkedList<>(); 34 | } 35 | 36 | public void registerInteractionHandler(InteractionHandler interactionHandler) 37 | { 38 | interactionHandlers.add(interactionHandler); 39 | } 40 | 41 | public void start() 42 | { 43 | scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1); 44 | schedule = scheduledThreadPoolExecutor.scheduleAtFixedRate(new PollingRunnable(), 0, pollInterval.getSeconds(), TimeUnit.SECONDS); 45 | } 46 | 47 | public void shutdown() 48 | { 49 | schedule.cancel(true); 50 | scheduledThreadPoolExecutor.shutdown(); 51 | } 52 | 53 | private class PollingRunnable implements Runnable 54 | { 55 | @Override 56 | public void run() 57 | { 58 | List interactionList = collaboratorClient.getAllInteractions(); 59 | 60 | for (Interaction interaction : interactionList) 61 | { 62 | for (InteractionHandler interactionHandler : interactionHandlers) 63 | { 64 | interactionHandler.handleInteraction(interaction); 65 | } 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /eventlisteners/src/main/java/example/eventlisteners/EventListeners.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.eventlisteners; 10 | 11 | import burp.api.montoya.BurpExtension; 12 | import burp.api.montoya.MontoyaApi; 13 | import burp.api.montoya.extension.Extension; 14 | import burp.api.montoya.extension.ExtensionUnloadingHandler; 15 | import burp.api.montoya.http.Http; 16 | import burp.api.montoya.logging.Logging; 17 | import burp.api.montoya.proxy.Proxy; 18 | import burp.api.montoya.scanner.Scanner; 19 | import burp.api.montoya.scanner.audit.AuditIssueHandler; 20 | import burp.api.montoya.scanner.audit.issues.AuditIssue; 21 | 22 | 23 | //Burp will auto-detect and load any class that extends BurpExtension. 24 | public class EventListeners implements BurpExtension { 25 | private Logging logging; 26 | 27 | @Override 28 | public void initialize(MontoyaApi api) { 29 | logging = api.logging(); 30 | 31 | Http http = api.http(); 32 | Proxy proxy = api.proxy(); 33 | Extension extension = api.extension(); 34 | Scanner scanner = api.scanner(); 35 | 36 | // set extension name 37 | extension.setName("Event listeners"); 38 | 39 | // register a new HTTP handler 40 | http.registerHttpHandler(new MyHttpHandler(api)); 41 | 42 | // register new Proxy handlers 43 | proxy.registerRequestHandler(new MyProxyRequestHandler(api)); 44 | proxy.registerResponseHandler(new MyProxyResponseHandler(api)); 45 | 46 | // register a new Audit Issue handler 47 | scanner.registerAuditIssueHandler(new MyAuditIssueListenerHandler()); 48 | 49 | // register a new extension unload handler 50 | extension.registerUnloadingHandler(new MyExtensionUnloadHandler()); 51 | } 52 | 53 | private class MyAuditIssueListenerHandler implements AuditIssueHandler { 54 | @Override 55 | public void handleNewAuditIssue(AuditIssue auditIssue) { 56 | logging.logToOutput("New scan issue: " + auditIssue.name()); 57 | } 58 | } 59 | 60 | private class MyExtensionUnloadHandler implements ExtensionUnloadingHandler { 61 | @Override 62 | public void extensionUnloaded() { 63 | logging.logToOutput("Extension was unloaded."); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /customsessiontokens/src/main/java/example/customsessiontokens/MySessionHandlingAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.customsessiontokens; 10 | 11 | import burp.api.montoya.http.message.HttpHeader; 12 | import burp.api.montoya.http.message.HttpRequestResponse; 13 | import burp.api.montoya.http.message.requests.HttpRequest; 14 | import burp.api.montoya.http.sessions.ActionResult; 15 | import burp.api.montoya.http.sessions.SessionHandlingAction; 16 | import burp.api.montoya.http.sessions.SessionHandlingActionData; 17 | 18 | import java.util.List; 19 | 20 | import static burp.api.montoya.http.sessions.ActionResult.actionResult; 21 | 22 | public class MySessionHandlingAction implements SessionHandlingAction 23 | { 24 | @Override 25 | public String name() 26 | { 27 | return "Use session token from macro"; 28 | } 29 | 30 | @Override 31 | public ActionResult performAction(SessionHandlingActionData actionData) 32 | { 33 | ActionResult result = actionResult(actionData.request(), actionData.annotations()); 34 | 35 | List macroRequestResponseList = actionData.macroRequestResponses(); 36 | 37 | if (macroRequestResponseList.isEmpty()) 38 | { 39 | return result; 40 | } 41 | 42 | // Extract the response headers 43 | List headers = macroRequestResponseList.get(macroRequestResponseList.size()-1).response().headers(); 44 | 45 | // Find session header 46 | HttpHeader sessionHeader = findSessionHeader(headers); 47 | 48 | // If we failed to find a session token, stop doing work 49 | if (sessionHeader == null) 50 | { 51 | return result; 52 | } 53 | 54 | // Create an HTTP request with updated session header 55 | HttpRequest updatedRequest = actionData.request().withUpdatedHeader(sessionHeader); 56 | 57 | return actionResult(updatedRequest, actionData.annotations()); 58 | } 59 | 60 | private HttpHeader findSessionHeader(List headers) 61 | { 62 | HttpHeader sessionHeader = null; 63 | 64 | for(HttpHeader header : headers) 65 | { 66 | // Skip any header that isn't an "X-Custom-Session-Id" 67 | if (!header.name().equals("X-Custom-Session-Id")) 68 | { 69 | continue; 70 | } 71 | 72 | // Grab the session token 73 | sessionHeader = header; 74 | } 75 | 76 | return sessionHeader; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /httphandler/src/main/java/example/httphandler/MyHttpHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.httphandler; 10 | 11 | import burp.api.montoya.MontoyaApi; 12 | import burp.api.montoya.core.Annotations; 13 | import burp.api.montoya.core.HighlightColor; 14 | import burp.api.montoya.http.handler.*; 15 | import burp.api.montoya.http.message.requests.HttpRequest; 16 | import burp.api.montoya.logging.Logging; 17 | 18 | import static burp.api.montoya.http.handler.RequestToBeSentAction.continueWith; 19 | import static burp.api.montoya.http.handler.ResponseReceivedAction.continueWith; 20 | import static burp.api.montoya.http.message.params.HttpParameter.urlParameter; 21 | 22 | class MyHttpHandler implements HttpHandler { 23 | private final Logging logging; 24 | 25 | public MyHttpHandler(MontoyaApi api) { 26 | this.logging = api.logging(); 27 | } 28 | 29 | 30 | @Override 31 | public RequestToBeSentAction handleHttpRequestToBeSent(HttpRequestToBeSent requestToBeSent) { 32 | Annotations annotations = requestToBeSent.annotations(); 33 | 34 | // If the request is a post, log the body and add notes. 35 | if (isPost(requestToBeSent)) { 36 | annotations = annotations.withNotes("Request was a post"); 37 | logging.logToOutput(requestToBeSent.bodyToString()); 38 | } 39 | 40 | //Modify the request by adding url param. 41 | HttpRequest modifiedRequest = requestToBeSent.withAddedParameters(urlParameter("foo", "bar")); 42 | 43 | //Return the modified request to burp with updated annotations. 44 | return continueWith(modifiedRequest, annotations); 45 | } 46 | 47 | @Override 48 | public ResponseReceivedAction handleHttpResponseReceived(HttpResponseReceived responseReceived) { 49 | Annotations annotations = responseReceived.annotations(); 50 | //Highlight all responses where the request had a Content-Length header. 51 | if (responseHasContentLengthHeader(responseReceived)) { 52 | annotations = annotations.withHighlightColor(HighlightColor.BLUE); 53 | } 54 | 55 | return continueWith(responseReceived, annotations); 56 | } 57 | 58 | private static boolean isPost(HttpRequestToBeSent httpRequestToBeSent) { 59 | return httpRequestToBeSent.method().equalsIgnoreCase("POST"); 60 | } 61 | 62 | private static boolean responseHasContentLengthHeader(HttpResponseReceived httpResponseReceived) { 63 | return httpResponseReceived.initiatingRequest().headers().stream().anyMatch(header -> header.name().equalsIgnoreCase("Content-Length")); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /customlogger/src/main/java/example/customlogger/CustomLogger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.customlogger; 10 | 11 | import burp.api.montoya.BurpExtension; 12 | import burp.api.montoya.MontoyaApi; 13 | import burp.api.montoya.http.handler.HttpResponseReceived; 14 | import burp.api.montoya.ui.UserInterface; 15 | import burp.api.montoya.ui.editor.HttpRequestEditor; 16 | import burp.api.montoya.ui.editor.HttpResponseEditor; 17 | 18 | import javax.swing.*; 19 | import java.awt.*; 20 | 21 | import static burp.api.montoya.ui.editor.EditorOptions.READ_ONLY; 22 | 23 | public class CustomLogger implements BurpExtension 24 | { 25 | private MontoyaApi api; 26 | 27 | @Override 28 | public void initialize(MontoyaApi api) 29 | { 30 | this.api = api; 31 | api.extension().setName("Custom logger"); 32 | 33 | MyTableModel tableModel = new MyTableModel(); 34 | api.userInterface().registerSuiteTab("Custom logger", constructLoggerTab(tableModel)); 35 | api.http().registerHttpHandler(new MyHttpHandler(tableModel)); 36 | } 37 | 38 | private Component constructLoggerTab(MyTableModel tableModel) 39 | { 40 | // main split pane 41 | JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); 42 | 43 | // tabs with request/response viewers 44 | JTabbedPane tabs = new JTabbedPane(); 45 | 46 | UserInterface userInterface = api.userInterface(); 47 | 48 | HttpRequestEditor requestViewer = userInterface.createHttpRequestEditor(READ_ONLY); 49 | HttpResponseEditor responseViewer = userInterface.createHttpResponseEditor(READ_ONLY); 50 | 51 | tabs.addTab("Request", requestViewer.uiComponent()); 52 | tabs.addTab("Response", responseViewer.uiComponent()); 53 | 54 | splitPane.setRightComponent(tabs); 55 | 56 | // table of log entries 57 | JTable table = new JTable(tableModel) 58 | { 59 | @Override 60 | public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) 61 | { 62 | // show the log entry for the selected row 63 | HttpResponseReceived responseReceived = tableModel.get(rowIndex); 64 | requestViewer.setRequest(responseReceived.initiatingRequest()); 65 | responseViewer.setResponse(responseReceived); 66 | 67 | super.changeSelection(rowIndex, columnIndex, toggle, extend); 68 | } 69 | }; 70 | 71 | JScrollPane scrollPane = new JScrollPane(table); 72 | 73 | splitPane.setLeftComponent(scrollPane); 74 | 75 | return splitPane; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /collaborator/src/main/java/example/collaborator/MyInteractionHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.collaborator; 10 | 11 | import burp.api.montoya.MontoyaApi; 12 | import burp.api.montoya.collaborator.Interaction; 13 | import burp.api.montoya.http.message.HttpRequestResponse; 14 | import burp.api.montoya.proxy.ProxyHttpRequestResponse; 15 | import burp.api.montoya.scanner.audit.issues.AuditIssue; 16 | import burp.api.montoya.scanner.audit.issues.AuditIssueConfidence; 17 | import burp.api.montoya.scanner.audit.issues.AuditIssueSeverity; 18 | import example.collaborator.poller.InteractionHandler; 19 | 20 | import java.util.List; 21 | 22 | public class MyInteractionHandler implements InteractionHandler 23 | { 24 | private final MontoyaApi api; 25 | private final InteractionLogger interactionLogger; 26 | 27 | public MyInteractionHandler(MontoyaApi api, InteractionLogger interactionLogger) 28 | { 29 | this.api = api; 30 | this.interactionLogger = interactionLogger; 31 | } 32 | 33 | @Override 34 | public void handleInteraction(Interaction interaction) 35 | { 36 | interactionLogger.logInteraction(interaction); 37 | 38 | List proxyHttpRequestResponseList = api.proxy().history(requestResponse -> requestResponse.finalRequest().toString().contains(interaction.id().toString())); 39 | 40 | proxyHttpRequestResponseList.forEach(item -> api.siteMap().add( 41 | AuditIssue.auditIssue( 42 | "Collaborator example issue", 43 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", 44 | "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.", 45 | item.finalRequest().url(), 46 | AuditIssueSeverity.HIGH, 47 | AuditIssueConfidence.CERTAIN, 48 | "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", 49 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", 50 | AuditIssueSeverity.HIGH, 51 | HttpRequestResponse.httpRequestResponse(item.finalRequest(), item.originalResponse()) 52 | ) 53 | )); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /intruderpayloads/src/main/java/example/intruderpayloads/MyPayloadProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.intruderpayloads; 10 | 11 | import burp.api.montoya.MontoyaApi; 12 | import burp.api.montoya.core.ByteArray; 13 | import burp.api.montoya.intruder.PayloadData; 14 | import burp.api.montoya.intruder.PayloadProcessingResult; 15 | import burp.api.montoya.intruder.PayloadProcessor; 16 | import burp.api.montoya.utilities.Base64Utils; 17 | import burp.api.montoya.utilities.URLUtils; 18 | 19 | import static burp.api.montoya.intruder.PayloadProcessingResult.usePayload; 20 | 21 | public class MyPayloadProcessor implements PayloadProcessor 22 | { 23 | public static final String INPUT_PREFIX = "input="; 24 | private final MontoyaApi api; 25 | 26 | public MyPayloadProcessor(MontoyaApi api) 27 | { 28 | this.api = api; 29 | } 30 | 31 | @Override 32 | public String displayName() 33 | { 34 | return "Serialized input wrapper"; 35 | } 36 | 37 | @Override 38 | public PayloadProcessingResult processPayload(PayloadData payloadData) 39 | { 40 | Base64Utils base64Utils = api.utilities().base64Utils(); 41 | URLUtils urlUtils = api.utilities().urlUtils(); 42 | 43 | // Decode the base value 44 | String dataParameter = base64Utils.decode(urlUtils.decode(payloadData.insertionPoint().baseValue())).toString(); 45 | 46 | // Parse the location of the input string in the decoded data 47 | String prefix = findPrefix(dataParameter); 48 | if (prefix == null) 49 | { 50 | return usePayload(payloadData.currentPayload()); 51 | } 52 | 53 | String suffix = findSuffix(dataParameter); 54 | 55 | // Rebuild serialized data with the new payload 56 | String rebuiltDataParameter = prefix + payloadData.currentPayload() + suffix; 57 | ByteArray reserializedDataParameter = urlUtils.encode(base64Utils.encode(rebuiltDataParameter)); 58 | 59 | return usePayload(reserializedDataParameter); 60 | } 61 | 62 | private String findPrefix(String dataParameter) 63 | { 64 | int start = dataParameter.indexOf(INPUT_PREFIX); 65 | 66 | if (start == -1) 67 | { 68 | return null; 69 | } 70 | 71 | start += INPUT_PREFIX.length(); 72 | 73 | return dataParameter.substring(0, start); 74 | } 75 | 76 | private String findSuffix(String dataParameter) 77 | { 78 | int start = dataParameter.indexOf(INPUT_PREFIX); 79 | 80 | int end = dataParameter.indexOf("&", start); 81 | 82 | if (end == -1) 83 | { 84 | end = dataParameter.length(); 85 | } 86 | 87 | return dataParameter.substring(end); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /ai/src/main/java/example/ai/MyProxyRequestHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.ai; 10 | 11 | import burp.api.montoya.ai.Ai; 12 | import burp.api.montoya.ai.chat.PromptException; 13 | import burp.api.montoya.ai.chat.PromptResponse; 14 | import burp.api.montoya.logging.Logging; 15 | import burp.api.montoya.proxy.http.InterceptedRequest; 16 | import burp.api.montoya.proxy.http.ProxyRequestHandler; 17 | import burp.api.montoya.proxy.http.ProxyRequestReceivedAction; 18 | import burp.api.montoya.proxy.http.ProxyRequestToBeSentAction; 19 | 20 | import java.util.concurrent.ExecutorService; 21 | 22 | import static burp.api.montoya.core.HighlightColor.GREEN; 23 | import static java.util.Locale.US; 24 | 25 | class MyProxyRequestHandler implements ProxyRequestHandler 26 | { 27 | private final Ai ai; 28 | private final Logging logging; 29 | private final MyPromptMessage promptMessageHandler; 30 | private final ExecutorService executorService; 31 | 32 | public MyProxyRequestHandler(Ai ai, Logging logging, ExecutorService executorService, MyPromptMessage promptMessageHandler) 33 | { 34 | this.ai = ai; 35 | this.logging = logging; 36 | this.promptMessageHandler = promptMessageHandler; 37 | this.executorService = executorService; 38 | } 39 | 40 | @Override 41 | public ProxyRequestReceivedAction handleRequestReceived(InterceptedRequest interceptedRequest) 42 | { 43 | if (ai.isEnabled() && interceptedRequest.isInScope()) 44 | { 45 | // AI requests are slow, so should be run on a separate thread. 46 | executorService.submit(() -> processRequest(interceptedRequest)); 47 | } 48 | 49 | return ProxyRequestReceivedAction.continueWith(interceptedRequest); 50 | } 51 | 52 | @Override 53 | public ProxyRequestToBeSentAction handleRequestToBeSent(InterceptedRequest interceptedRequest) 54 | { 55 | return ProxyRequestToBeSentAction.continueWith(interceptedRequest); 56 | } 57 | 58 | private void processRequest(InterceptedRequest request) 59 | { 60 | try 61 | { 62 | PromptResponse promptResponse = ai.prompt().execute(promptMessageHandler.build(request.toString())); 63 | 64 | if (promptResponse.content().toLowerCase(US).contains("yes")) 65 | { 66 | request.annotations().setHighlightColor(GREEN); 67 | } 68 | } catch (PromptException e) 69 | { 70 | if (e.getMessage().contains("Not enough credits")) 71 | { 72 | logging.logToOutput("Please increase your credit balance."); 73 | } else 74 | { 75 | logging.logToError("Issue executing prompt", e); 76 | } 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /ai/README.md: -------------------------------------------------------------------------------- 1 | AI Example Extension 2 | ============================ 3 | 4 | ###### Demonstrates using AI functionality. 5 | 6 | --- 7 | This extension demonstrates using Burp's built-in functionality to issue requests to an LLM and process the responses. 8 | 9 | This extension uses an LLM to analyze in-scope requests and determine whether they are related to authentication. 10 | 11 | The sample extension demonstrates the following techniques: 12 | - Marking an extension as AI-compatible. 13 | - The implementation of `BurpExtension` overrides `BurpExtension.enhancedCapabilities()` 14 | - `MyPromptMessage` provides an easy way to provide the `Message.systemMessage()` with the `Message.userMessage()`. This allows you to provide context at the same time as the user message when sending prompts to the LLM. 15 | 16 | > When sending prompts to the LLM, `Message.systemMessage()` needs to be sent each time to provide the context. 17 | > 18 | > Conversations between the LLM and the user can be continued by chaining `Message.userMessage()` and `Message.assistantMessage()` within `Prompt.execute()`. 19 | 20 | - By registering a `ProxyRequestHandler`, the extension can analyze all outgoing Proxy requests. 21 | - For each request, the extension first checks if AI functionality is enabled using `Ai.isEnabled()`. 22 | - To minimize unnecessary data sent to the LLM, the extension checks if the traffic is in scope. 23 | - Provided the previous conditions are met, the extension will submit a task to the configured thread pool to execute the prompt. 24 | 25 | > LLM queries are slow and should be performed on their own thread to reduce impact on browsing speed. 26 | 27 | - The task will issue a request to the LLM using `Prompt.execute()`. 28 | - The `PromptResponse` is analyzed. Due to our `Message.systemMessage()`, the output should contain "yes" or "no". 29 | - If the outcome of the analysis is "yes", the extension highlights the request in the Proxy History table. 30 | - If the outcome of the analysis is "no", no action is taken. 31 | - If a `PromptException` is thrown, additional handling has been put in place. 32 | - If the user does not have sufficient credits, a message is logged to the output stream of the extension. 33 | - If the prompt execution fails for a different reason, a message and the exception is logged to the error stream of the extension. 34 | 35 | Further references: 36 | - [Creating AI extensions](https://portswigger.net/burp/documentation/desktop/extensions/creating/creating-ai-extensions) 37 | - [Best practices for writing AI extensions](https://portswigger.net/burp/documentation/desktop/extensions/creating/creating-ai-extensions/best-practices) 38 | - [Developing AI features in extensions](https://portswigger.net/burp/documentation/desktop/extensions/creating/creating-ai-extensions/developing-ai-features) 39 | - [Using AI extensions](https://portswigger.net/burp/documentation/desktop/extensions/using-ai-extensions) 40 | - [AI security, privacy and data handling](https://portswigger.net/burp/documentation/desktop/extensions/ai-security-privacy-data-handling) -------------------------------------------------------------------------------- /collaborator/src/main/java/example/collaborator/CollaboratorExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.collaborator; 10 | 11 | import burp.api.montoya.BurpExtension; 12 | import burp.api.montoya.MontoyaApi; 13 | import burp.api.montoya.collaborator.CollaboratorClient; 14 | import burp.api.montoya.collaborator.SecretKey; 15 | import burp.api.montoya.persistence.PersistedObject; 16 | import example.collaborator.poller.Poller; 17 | 18 | import java.time.Duration; 19 | 20 | public class CollaboratorExample implements BurpExtension 21 | { 22 | private MontoyaApi api; 23 | 24 | @Override 25 | public void initialize(MontoyaApi api) 26 | { 27 | this.api = api; 28 | 29 | api.extension().setName("Collaborator example extension"); 30 | 31 | CollaboratorClient collaboratorClient = createCollaboratorClient(api.persistence().extensionData()); 32 | 33 | // Log any stored interactions. 34 | InteractionLogger interactionLogger = new InteractionLogger(api); 35 | interactionLogger.logInteractions(collaboratorClient.getAllInteractions()); 36 | 37 | api.proxy().registerRequestHandler(new MyProxyRequestHandler(collaboratorClient)); 38 | 39 | // Periodically poll the CollaboratorClient to retrieve any new interactions. 40 | Poller collaboratorPoller = new Poller(collaboratorClient, Duration.ofSeconds(10)); 41 | collaboratorPoller.registerInteractionHandler(new MyInteractionHandler(api, interactionLogger)); 42 | collaboratorPoller.start(); 43 | 44 | api.extension().registerUnloadingHandler(() -> 45 | { 46 | // Stop polling the CollaboratorClient. 47 | collaboratorPoller.shutdown(); 48 | 49 | api.logging().logToOutput("Extension unloading..."); 50 | }); 51 | } 52 | 53 | private CollaboratorClient createCollaboratorClient(PersistedObject persistedData) 54 | { 55 | CollaboratorClient collaboratorClient; 56 | 57 | String existingCollaboratorKey = persistedData.getString("persisted_collaborator"); 58 | 59 | if (existingCollaboratorKey != null) 60 | { 61 | api.logging().logToOutput("Creating Collaborator client from key."); 62 | collaboratorClient = api.collaborator().restoreClient(SecretKey.secretKey(existingCollaboratorKey)); 63 | } 64 | else 65 | { 66 | api.logging().logToOutput("No previously found Collaborator client. Creating new client..."); 67 | collaboratorClient = api.collaborator().createClient(); 68 | 69 | // Save the secret key of the CollaboratorClient so that you can retrieve it later. 70 | api.logging().logToOutput("Saving Collaborator secret key."); 71 | persistedData.setString("persisted_collaborator", collaboratorClient.getSecretKey().toString()); 72 | } 73 | 74 | return collaboratorClient; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /persistence/src/main/java/example/persistence/SavingLoadingRequests.java: -------------------------------------------------------------------------------- 1 | package example.persistence; 2 | 3 | import burp.api.montoya.MontoyaApi; 4 | import burp.api.montoya.http.message.requests.HttpRequest; 5 | import burp.api.montoya.persistence.PersistedObject; 6 | 7 | import static burp.api.montoya.http.message.requests.HttpRequest.httpRequest; 8 | import static burp.api.montoya.http.message.requests.HttpRequest.httpRequestFromUrl; 9 | import static example.persistence.PersistenceExample.STARTUP_COUNT_KEY; 10 | 11 | public class SavingLoadingRequests { 12 | public static final String SIMPLE_REQUEST_KEY = "simpleRequest"; 13 | public static final String REQUEST_WITH_HEADERS_KEY = "requestWithHeaders"; 14 | public static final String REQUEST_FROM_URL_KEY = "requestFromUrl"; 15 | private final MontoyaApi api; 16 | private final PersistedObject myExtensionData; 17 | 18 | public SavingLoadingRequests(MontoyaApi api) { 19 | this.api = api; 20 | this.myExtensionData = api.persistence().extensionData(); 21 | } 22 | 23 | public void runExample() { 24 | //Check if we have example requests saved 25 | if (!checkForRequests()) { 26 | api.logging().raiseInfoEvent("No Requests saved, creating requests"); 27 | createAndSaveExampleRequests(); 28 | } 29 | 30 | sendExampleRequestsToRepeaterWithStartupCount(); 31 | } 32 | 33 | private boolean checkForRequests() { 34 | // We can get a list of keys for each type of data type saved. 35 | return myExtensionData.httpRequestKeys().contains(SIMPLE_REQUEST_KEY) && 36 | myExtensionData.httpRequestKeys().contains(REQUEST_WITH_HEADERS_KEY) && 37 | myExtensionData.httpRequestKeys().contains(REQUEST_FROM_URL_KEY); 38 | } 39 | 40 | //Build example requests and save them to their own key 41 | private void createAndSaveExampleRequests() { 42 | HttpRequest simpleRequest = httpRequest("GET / HTTP1.0\r\n\r\n"); 43 | HttpRequest requestWithHeaders = httpRequest("GET / HTTP1.1\r\nHost: localhost\r\nMyHeader: Example\r\n\r\n"); 44 | HttpRequest requestFromUrl = httpRequestFromUrl("http://localhost"); 45 | 46 | //Save each request to its own key 47 | myExtensionData.setHttpRequest(SIMPLE_REQUEST_KEY, simpleRequest); 48 | myExtensionData.setHttpRequest(REQUEST_WITH_HEADERS_KEY, requestWithHeaders); 49 | myExtensionData.setHttpRequest(REQUEST_FROM_URL_KEY, requestFromUrl); 50 | } 51 | 52 | //Add our requests to repeater with startup count in the tab name 53 | private void sendExampleRequestsToRepeaterWithStartupCount() { 54 | HttpRequest simpleRequest = myExtensionData.getHttpRequest(SIMPLE_REQUEST_KEY); 55 | HttpRequest requestWithHeaders = myExtensionData.getHttpRequest(REQUEST_WITH_HEADERS_KEY); 56 | HttpRequest requestFromUrl = myExtensionData.getHttpRequest(REQUEST_FROM_URL_KEY); 57 | 58 | Integer startupCount = myExtensionData.getInteger(STARTUP_COUNT_KEY); 59 | 60 | api.repeater().sendToRepeater(simpleRequest, "Simple Request " + startupCount); 61 | api.repeater().sendToRepeater(requestWithHeaders, "Request With Headers " + startupCount); 62 | api.repeater().sendToRepeater(requestFromUrl, "Request From Url " + startupCount); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /persistence/src/main/java/example/persistence/RequestResponseLogging.java: -------------------------------------------------------------------------------- 1 | package example.persistence; 2 | 3 | import burp.api.montoya.MontoyaApi; 4 | import burp.api.montoya.http.handler.*; 5 | import burp.api.montoya.http.message.HttpRequestResponse; 6 | import burp.api.montoya.persistence.PersistedList; 7 | import burp.api.montoya.persistence.PersistedObject; 8 | 9 | import static burp.api.montoya.http.handler.RequestToBeSentAction.continueWith; 10 | import static burp.api.montoya.http.handler.ResponseReceivedAction.continueWith; 11 | import static burp.api.montoya.http.message.HttpRequestResponse.httpRequestResponse; 12 | 13 | public class RequestResponseLogging { 14 | private static final String REQUEST_RESPONSE_LIST_KEY = "last5"; 15 | 16 | private final MontoyaApi api; 17 | private final PersistedObject myExtensionData; 18 | 19 | public RequestResponseLogging(MontoyaApi api) { 20 | this.api = api; 21 | this.myExtensionData = api.persistence().extensionData(); 22 | } 23 | 24 | public void runExample() { 25 | ensurePersistedListIsPresent(); 26 | 27 | //Load our request/response list from the project file. 28 | PersistedList myPersistedList = myExtensionData.getHttpRequestResponseList(REQUEST_RESPONSE_LIST_KEY); 29 | printToOutput(myPersistedList); 30 | 31 | api.http().registerHttpHandler(new HttpHandler() { 32 | @Override 33 | public RequestToBeSentAction handleHttpRequestToBeSent(HttpRequestToBeSent requestToBeSent) { 34 | return continueWith(requestToBeSent); 35 | } 36 | 37 | @Override 38 | public synchronized ResponseReceivedAction handleHttpResponseReceived(HttpResponseReceived responseReceived) { 39 | //Keep a list of the last 5 40 | if (myPersistedList.size() >= 5) { 41 | myPersistedList.remove(0); 42 | } 43 | 44 | //We don't need the body for our log. 45 | myPersistedList.add(httpRequestResponse(responseReceived.initiatingRequest().withBody(""), responseReceived.withBody(""))); 46 | 47 | return continueWith(responseReceived); 48 | } 49 | }); 50 | } 51 | 52 | private void printToOutput(PersistedList myPersistedList) { 53 | //Print the loaded list to the output log 54 | for (HttpRequestResponse httpRequestResponse : myPersistedList) { 55 | api.logging().logToOutput(httpRequestResponse.request().toString()); 56 | api.logging().logToOutput("\n========================\n"); 57 | api.logging().logToOutput(httpRequestResponse.response().toString()); 58 | api.logging().logToOutput("\n**************************".repeat(2)); 59 | } 60 | } 61 | 62 | private void ensurePersistedListIsPresent() { 63 | //Create a persisted request/response list 64 | if (myExtensionData.getHttpRequestResponseList(REQUEST_RESPONSE_LIST_KEY) == null) { 65 | //Create a new empty list and save it to our key 66 | PersistedList emptyPersistedList = PersistedList.persistedHttpRequestResponseList(); 67 | myExtensionData.setHttpRequestResponseList(REQUEST_RESPONSE_LIST_KEY, emptyPersistedList); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /multiapi/src/main/java/example/multiapi/MultiApiExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.multiapi; 10 | 11 | import burp.IBurpExtender; 12 | import burp.IBurpExtenderCallbacks; 13 | import burp.api.montoya.BurpExtension; 14 | import burp.api.montoya.MontoyaApi; 15 | 16 | import javax.swing.*; 17 | import java.awt.*; 18 | import java.net.MalformedURLException; 19 | import java.net.URL; 20 | 21 | //Burp will auto-detect and load any class that extends BurpExtension / IBurpExtender 22 | //When a class extends both BurpExtension AND IBurpExtender Burp will inject both of the relevant API implementations 23 | //It will inject IBurpExtender first, then BurpExtension. 24 | //This will BurpExtension precedence over IBurpExtender 25 | public class MultiApiExample implements BurpExtension, IBurpExtender 26 | { 27 | private MontoyaApi montoyaApi; 28 | private IBurpExtenderCallbacks wienerApi; 29 | 30 | //Invoked Last 31 | @Override 32 | public void initialize(MontoyaApi api) 33 | { 34 | this.montoyaApi = api; 35 | 36 | //Register a suite tab that has a button that uses both api's 37 | api.userInterface().registerSuiteTab("My Suite Tab", new MySuiteTab()); 38 | 39 | api.extension().setName("Montoya Name"); //Replaces name set by Wiener Api. 40 | 41 | if (api.scope().isInScope("http://test.url")) //Is true because Wiener API added it to scope. 42 | { 43 | wienerApi.issueAlert("test.url is in scope"); //Wiener api has been set, so we can use it. 44 | } 45 | else 46 | { 47 | api.extension().unload(); //Should never happen 48 | } 49 | } 50 | 51 | //Invoked First 52 | @Override 53 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) 54 | { 55 | this.wienerApi = callbacks; 56 | 57 | callbacks.setExtensionName("Wiener Name"); //Will be replaced by Montoya version. 58 | 59 | try 60 | { 61 | URL url = new URL("http://test.url"); 62 | callbacks.includeInScope(url); //Include test.url in the scope 63 | } 64 | catch (MalformedURLException e) 65 | { 66 | throw new RuntimeException(e); 67 | } 68 | } 69 | 70 | private class MySuiteTab extends JComponent 71 | { 72 | public MySuiteTab() 73 | { 74 | setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); 75 | 76 | JPanel customTabContent = new JPanel(); 77 | customTabContent.setName("The One Ring Custom Tab Panel"); 78 | customTabContent.setBackground(Color.GRAY); 79 | 80 | JButton button = new JButton("Print filename to log file"); 81 | button.addActionListener(e -> { 82 | montoyaApi.logging().logToOutput("Montoya API used to log:" + montoyaApi.extension().filename()); 83 | wienerApi.printOutput("Wiener API used to log:" + wienerApi.getExtensionFilename()); 84 | }); 85 | 86 | customTabContent.add(button); 87 | add(customTabContent); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /customscaninsertionpoints/src/main/java/example/customscaninsertionpoints/MyAuditInsertionPoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.customscaninsertionpoints; 10 | 11 | import burp.api.montoya.MontoyaApi; 12 | import burp.api.montoya.core.ByteArray; 13 | import burp.api.montoya.core.Range; 14 | import burp.api.montoya.http.message.HttpRequestResponse; 15 | import burp.api.montoya.http.message.params.HttpParameter; 16 | import burp.api.montoya.http.message.params.ParsedHttpParameter; 17 | import burp.api.montoya.http.message.requests.HttpRequest; 18 | import burp.api.montoya.scanner.audit.insertionpoint.AuditInsertionPoint; 19 | import burp.api.montoya.utilities.Utilities; 20 | 21 | import java.util.List; 22 | 23 | import static burp.api.montoya.http.message.params.HttpParameter.parameter; 24 | 25 | class MyAuditInsertionPoint implements AuditInsertionPoint 26 | { 27 | private final String insertionPointPrefix; 28 | private final String insertionPointSuffix; 29 | private final HttpRequestResponse requestResponse; 30 | private final ParsedHttpParameter parameter; 31 | private final String baseValue; 32 | private final Utilities utilities; 33 | 34 | MyAuditInsertionPoint(MontoyaApi api, HttpRequestResponse baseHttpRequestResponse, ParsedHttpParameter parameter) 35 | { 36 | this.requestResponse = baseHttpRequestResponse; 37 | this.parameter = parameter; 38 | this.utilities = api.utilities(); 39 | 40 | String paramValue = parameter.value(); 41 | 42 | // URL and base-64 decode the data 43 | String urlDecoded = utilities.urlUtils().decode(paramValue); 44 | ByteArray byteData = utilities.base64Utils().decode(urlDecoded); 45 | 46 | String data = byteData.toString(); 47 | 48 | // Parse the location of the input string within the decoded data 49 | int start = data.indexOf("input=") + 6; 50 | int end = data.indexOf("&", start); 51 | 52 | if (end == -1) 53 | { 54 | end = data.length(); 55 | } 56 | 57 | baseValue = data.substring(start, end); 58 | 59 | insertionPointPrefix = data.substring(0, start); 60 | insertionPointSuffix = data.substring(end); 61 | } 62 | 63 | @Override 64 | public String name() 65 | { 66 | return "Base64-wrapped input"; 67 | } 68 | 69 | @Override 70 | public String baseValue() 71 | { 72 | return baseValue; 73 | } 74 | 75 | @Override 76 | public HttpRequest buildHttpRequestWithPayload(ByteArray payload) 77 | { 78 | // build the raw data using the specified payload 79 | String input = insertionPointPrefix + payload.toString() + insertionPointSuffix; 80 | 81 | // Base-64 and URL-encode the data 82 | String updatedParameterValue = utilities.urlUtils().encode(utilities.base64Utils().encodeToString(input)); 83 | 84 | HttpParameter updatedParameter = parameter(parameter.name(), updatedParameterValue, parameter.type()); 85 | 86 | return requestResponse.request().withUpdatedParameters(updatedParameter); 87 | } 88 | 89 | @Override 90 | public List issueHighlights(ByteArray payload) 91 | { 92 | return null; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /customrequesteditortab/src/main/java/example/customrequesteditortab/MyExtensionProvidedHttpRequestEditor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.customrequesteditortab; 10 | 11 | import burp.api.montoya.MontoyaApi; 12 | import burp.api.montoya.core.ByteArray; 13 | import burp.api.montoya.http.message.HttpRequestResponse; 14 | import burp.api.montoya.http.message.params.HttpParameter; 15 | import burp.api.montoya.http.message.params.ParsedHttpParameter; 16 | import burp.api.montoya.http.message.requests.HttpRequest; 17 | import burp.api.montoya.ui.Selection; 18 | import burp.api.montoya.ui.editor.EditorOptions; 19 | import burp.api.montoya.ui.editor.RawEditor; 20 | import burp.api.montoya.ui.editor.extension.EditorCreationContext; 21 | import burp.api.montoya.ui.editor.extension.EditorMode; 22 | import burp.api.montoya.ui.editor.extension.ExtensionProvidedHttpRequestEditor; 23 | import burp.api.montoya.utilities.Base64EncodingOptions; 24 | import burp.api.montoya.utilities.Base64Utils; 25 | import burp.api.montoya.utilities.URLUtils; 26 | 27 | import java.awt.*; 28 | import java.util.Optional; 29 | 30 | import static burp.api.montoya.core.ByteArray.byteArray; 31 | 32 | class MyExtensionProvidedHttpRequestEditor implements ExtensionProvidedHttpRequestEditor 33 | { 34 | private final RawEditor requestEditor; 35 | private final Base64Utils base64Utils; 36 | private final URLUtils urlUtils; 37 | private HttpRequestResponse requestResponse; 38 | private final MontoyaApi api; 39 | 40 | private ParsedHttpParameter parsedHttpParameter; 41 | 42 | MyExtensionProvidedHttpRequestEditor(MontoyaApi api, EditorCreationContext creationContext) 43 | { 44 | this.api = api; 45 | base64Utils = api.utilities().base64Utils(); 46 | urlUtils = api.utilities().urlUtils(); 47 | 48 | if (creationContext.editorMode() == EditorMode.READ_ONLY) 49 | { 50 | requestEditor = api.userInterface().createRawEditor(EditorOptions.READ_ONLY); 51 | } 52 | else { 53 | requestEditor = api.userInterface().createRawEditor(); 54 | } 55 | } 56 | 57 | @Override 58 | public HttpRequest getRequest() 59 | { 60 | HttpRequest request; 61 | 62 | if (requestEditor.isModified()) 63 | { 64 | // reserialize data 65 | String base64Encoded = base64Utils.encodeToString(requestEditor.getContents(), Base64EncodingOptions.URL); 66 | String encodedData = urlUtils.encode(base64Encoded); 67 | 68 | request = requestResponse.request().withUpdatedParameters(HttpParameter.parameter(parsedHttpParameter.name(), encodedData, parsedHttpParameter.type())); 69 | } 70 | else 71 | { 72 | request = requestResponse.request(); 73 | } 74 | 75 | return request; 76 | } 77 | 78 | @Override 79 | public void setRequestResponse(HttpRequestResponse requestResponse) 80 | { 81 | this.requestResponse = requestResponse; 82 | 83 | String urlDecoded = urlUtils.decode(parsedHttpParameter.value()); 84 | 85 | ByteArray output; 86 | 87 | try 88 | { 89 | output = base64Utils.decode(urlDecoded); 90 | } 91 | catch (Exception e) 92 | { 93 | output = byteArray(urlDecoded); 94 | } 95 | 96 | this.requestEditor.setContents(output); 97 | } 98 | 99 | @Override 100 | public boolean isEnabledFor(HttpRequestResponse requestResponse) 101 | { 102 | Optional dataParam = requestResponse.request().parameters().stream().filter(p -> p.name().equals("data")).findFirst(); 103 | 104 | dataParam.ifPresent(httpParameter -> parsedHttpParameter = httpParameter); 105 | 106 | return dataParam.isPresent(); 107 | } 108 | 109 | @Override 110 | public String caption() 111 | { 112 | return "Serialized input"; 113 | } 114 | 115 | @Override 116 | public Component uiComponent() 117 | { 118 | return requestEditor.uiComponent(); 119 | } 120 | 121 | @Override 122 | public Selection selectedData() 123 | { 124 | return requestEditor.selection().isPresent() ? requestEditor.selection().get() : null; 125 | } 126 | 127 | @Override 128 | public boolean isModified() 129 | { 130 | return requestEditor.isModified(); 131 | } 132 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Example Extensions 2 | ============================ 3 | 4 | | Extension | Description | 5 | |-----------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------| 6 | | [Hello World](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/helloworld) | Prints output to various locations in Burp | 7 | | [HTTP Handlers](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/httphandler) | Demonstrates performing various actions on requests passing through any tool in Burp | 8 | | [Proxy Handlers](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/proxyhandler) | Demonstrates performing various actions on requests passing through the Proxy | 9 | | [Event Listeners](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/eventlisteners) | Registers handlers for various runtime events, and prints a message when each event occurs | 10 | | [Traffic Redirector](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/trafficredirector) | Redirects all outbound requests from one host to another | 11 | | [Custom Logger](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/customlogger) | Adds a new tab to Burp's UI and displays a log of HTTP traffic for all Burp tools | 12 | | [Custom Request Editor Tab](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/customrequesteditortab) | Adds a new tab to Burp's HTTP message editor, in order to handle a data serialization format | 13 | | [Custom Scan Insertion Points](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/customscaninsertionpoints) | Provides custom attack insertion points for active scanning | 14 | | [Custom Scan Checks](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/customscanchecks) | Implements custom checks to extend the capabilities of Burp's passive and active scan checks | 15 | | [Custom Session Tokens](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/customsessiontokens) | Demonstrates working with custom session tokens that Burp doesn't normally understand | 16 | | [Intruder Payloads](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/intruderpayloads) | Provides custom Intruder payloads and payload processing | 17 | | [Multi-API](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/multiapi) | Demonstrates using both the Montoya API and the legacy Wiener API in one extension | 18 | | [Persistence](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/persistence) | Demonstrates saving and loading data to the project file | 19 | | [WebSocket Handlers](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/websockethandler) | Demonstrates performing various actions on web socket messages passing through any tool in Burp | 20 | | [Proxy WebSocket Handlers](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/proxywebsockethandler) | Demonstrates performing various actions on web socket messages passing through the Proxy | 21 | | [Menu Bar](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/menubar) | Registers a top level menu bar with actions | 22 | | [Context Menu](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/contextmenu) | Registers new context menu items to print requests and responses | 23 | | [Collaborator](https://github.com/PortSwigger/burp-extensions-montoya-api-examples/blob/main/collaborator) | Demonstrates using Collaborator and Persistence functionality | 24 | -------------------------------------------------------------------------------- /customscanchecks/src/main/java/example/customscanchecks/MyScanCheck.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. PortSwigger Ltd. All rights reserved. 3 | * 4 | * This code may be used to extend the functionality of Burp Suite Community Edition 5 | * and Burp Suite Professional, provided that this usage does not violate the 6 | * license terms for those products. 7 | */ 8 | 9 | package example.customscanchecks; 10 | 11 | import burp.api.montoya.MontoyaApi; 12 | import burp.api.montoya.core.Marker; 13 | import burp.api.montoya.http.message.HttpRequestResponse; 14 | import burp.api.montoya.http.message.requests.HttpRequest; 15 | import burp.api.montoya.scanner.AuditResult; 16 | import burp.api.montoya.scanner.ConsolidationAction; 17 | import burp.api.montoya.scanner.ScanCheck; 18 | import burp.api.montoya.scanner.audit.insertionpoint.AuditInsertionPoint; 19 | import burp.api.montoya.scanner.audit.issues.AuditIssue; 20 | import burp.api.montoya.scanner.audit.issues.AuditIssueConfidence; 21 | import burp.api.montoya.scanner.audit.issues.AuditIssueSeverity; 22 | 23 | import java.util.LinkedList; 24 | import java.util.List; 25 | 26 | import static burp.api.montoya.core.ByteArray.byteArray; 27 | import static burp.api.montoya.scanner.AuditResult.auditResult; 28 | import static burp.api.montoya.scanner.ConsolidationAction.KEEP_BOTH; 29 | import static burp.api.montoya.scanner.ConsolidationAction.KEEP_EXISTING; 30 | import static burp.api.montoya.scanner.audit.issues.AuditIssue.auditIssue; 31 | import static java.util.Collections.emptyList; 32 | import static java.util.Collections.singletonList; 33 | 34 | class MyScanCheck implements ScanCheck 35 | { 36 | private static final String GREP_STRING = "Page generated by:"; 37 | private static final String INJ_TEST = "|"; 38 | private static final String INJ_ERROR = "Unexpected pipe"; 39 | 40 | private final MontoyaApi api; 41 | 42 | MyScanCheck(MontoyaApi api) 43 | { 44 | this.api = api; 45 | } 46 | 47 | @Override 48 | public AuditResult activeAudit(HttpRequestResponse baseRequestResponse, AuditInsertionPoint auditInsertionPoint) 49 | { 50 | HttpRequest checkRequest = auditInsertionPoint.buildHttpRequestWithPayload(byteArray(INJ_TEST)).withService(baseRequestResponse.httpService()); 51 | 52 | HttpRequestResponse checkRequestResponse = api.http().sendRequest(checkRequest); 53 | 54 | List responseHighlights = getResponseHighlights(checkRequestResponse, INJ_ERROR); 55 | 56 | List auditIssueList = responseHighlights.isEmpty() ? emptyList() : singletonList( 57 | auditIssue( 58 | "Pipe injection", 59 | "Submitting a pipe character returned the string: " + INJ_ERROR, 60 | null, 61 | baseRequestResponse.request().url(), 62 | AuditIssueSeverity.HIGH, 63 | AuditIssueConfidence.CERTAIN, 64 | null, 65 | null, 66 | AuditIssueSeverity.HIGH, 67 | checkRequestResponse.withResponseMarkers(responseHighlights) 68 | ) 69 | ); 70 | 71 | return auditResult(auditIssueList); 72 | } 73 | 74 | @Override 75 | public AuditResult passiveAudit(HttpRequestResponse baseRequestResponse) 76 | { 77 | List responseHighlights = getResponseHighlights(baseRequestResponse, GREP_STRING); 78 | 79 | List auditIssueList = responseHighlights.isEmpty() ? emptyList() : singletonList( 80 | auditIssue( 81 | "CMS Info Leakage", 82 | "The response contains the string: " + GREP_STRING, 83 | null, 84 | baseRequestResponse.request().url(), 85 | AuditIssueSeverity.HIGH, 86 | AuditIssueConfidence.CERTAIN, 87 | null, 88 | null, 89 | AuditIssueSeverity.HIGH, 90 | baseRequestResponse.withResponseMarkers(responseHighlights) 91 | ) 92 | ); 93 | 94 | return auditResult(auditIssueList); 95 | } 96 | 97 | @Override 98 | public ConsolidationAction consolidateIssues(AuditIssue newIssue, AuditIssue existingIssue) 99 | { 100 | return existingIssue.name().equals(newIssue.name()) ? KEEP_EXISTING : KEEP_BOTH; 101 | } 102 | 103 | private static List getResponseHighlights(HttpRequestResponse requestResponse, String match) 104 | { 105 | List highlights = new LinkedList<>(); 106 | String response = requestResponse.response().toString(); 107 | 108 | int start = 0; 109 | 110 | while (start < response.length()) 111 | { 112 | start = response.indexOf(match, start); 113 | 114 | if (start == -1) 115 | { 116 | break; 117 | } 118 | 119 | Marker marker = Marker.marker(start, start+match.length()); 120 | highlights.add(marker); 121 | 122 | start += match.length(); 123 | } 124 | 125 | return highlights; 126 | } 127 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Burp Suite Professional Licence Agreement 2 | 3 | This licence agreement (Licence) is a legal agreement between you (Licensee or 4 | you) and PORTSWIGGER LTD of Victoria Court, Bexton Road, Knutsford, WA16 0PF 5 | England (Licensor or we) for a suite of tools designed for web application 6 | security testers (Burp Suite Professional or Software), which includes computer 7 | software, and the online documentation current at the date of the download of 8 | this Licence (Documentation). 9 | 10 | BURP SUITE PROFESSIONAL REQUIRES A COMPUTER WITH A MINIMUM OF 4GB OF MEMORY AND 11 | THE OFFICIAL JAVA RUNTIME ENVIRONMENT (64-BIT EDITION, VERSION 1.7 OR LATER). IF 12 | YOU INTEND TO USE THE SOFTWARE ON ANY OTHER PLATFORM YOU SHOULD FIRST TEST THE 13 | FREE VERSION OF BURP SUITE ON THAT PLATFORM TO SATISFY YOURSELF THAT IT WORKS 14 | CORRECTLY. INTERNET ACCESS IS REQUIRED DURING INSTALLATION TO ACTIVATE THE 15 | SOFTWARE. BY INSTALLING THE SOFTWARE YOU AGREE TO THE TERMS OF THIS LICENCE AND 16 | THE TERMS AND CONDITIONS OF THE LICENSOR WHICH WILL BIND YOU AND YOUR EMPLOYEES. 17 | IF YOU DO NOT AGREE TO THE TERMS OF THIS LICENCE AND THE TERMS AND CONDITIONS, 18 | WE ARE UNWILLING TO LICENSE THE SOFTWARE TO YOU AND YOU MUST DISCONTINUE THE 19 | ORDERING OR INSTALLATION PROCESS NOW. IN THIS CASE THE ORDERING PROCESS OR 20 | INSTALLATION WILL TERMINATE. 21 | 22 | WARNING: BURP SUITE PROFESSIONAL IS DESIGNED TO TEST FOR SECURITY FLAWS AND CAN 23 | DO DAMAGE TO TARGET SYSTEMS DUE TO THE NATURE OF ITS FUNCTIONALITY. TESTING FOR 24 | SECURITY FLAWS INHERENTLY INVOLVES INTERACTING WITH TARGETS IN NON-STANDARD WAYS 25 | WHICH CAN CAUSE PROBLEMS IN SOME VULNERABLE TARGETS. YOU MUST TAKE DUE CARE WHEN 26 | USING THE SOFTWARE, YOU MUST READ ALL DOCUMENTATION BEFORE USE, YOU SHOULD BACK 27 | UP TARGET SYSTEMS BEFORE USE AND YOU SHOULD NOT USE THE SOFTWARE ON PRODUCTION 28 | SYSTEMS OR OTHER SYSTEMS FOR WHICH THE RISK OF DAMAGE IS NOT ACCEPTED BY YOU. 29 | 30 | 1. GRANT AND SCOPE OF LICENCE 31 | 32 | 1.1 In consideration of payment by you of any agreed licence fee and you 33 | agreeing to abide by the terms of this Licence, the Licensor hereby grants to 34 | you a non-exclusive, non-transferable licence for the period (the "Licence 35 | Period") specified in your order confirmation for the number of individual users 36 | specified therein to use the Software and the Documentation on the terms of this 37 | Licence. 38 | 39 | 1.2 Each installation of Burp Suite Professional on an individual computer 40 | needs to be activated before it will operate. It is recognised that in the 41 | course of ordinary usage of the Software, individual users may need to install 42 | the product on more than one computer. The number of activations performed for 43 | each licence is monitored. The Licensor reserves the right to limit the number 44 | of activations allowed per licence, and to prevent further activations if this 45 | limit is exceeded. 46 | 47 | 1.3 You may either: 48 | 49 | 1.3.1 download, install and use the Software and Burp Apps (as defined in 50 | condition 4) for your internal business purposes (which includes bespoke client 51 | consultancy, if appropriate) only; and 52 | 53 | 1.3.1.1 make one copy of the Software for back-up purposes only, provided 54 | that this is necessary for the activities permitted under condition 1.3.1; 55 | 56 | 1.3.1.2 receive and use any free supplementary software code or update of the 57 | Software incorporating "patches" and corrections of errors as may be provided by 58 | the Licensor from time to time on the basis that they are governed by the terms 59 | of this Licence; 60 | 61 | 1.3.1.3 use any Documentation in support of the use permitted under condition 62 | 1.3.1 and make such numbers of copies of the Documentation as are reasonably 63 | necessary for its lawful use; and 64 | 65 | 1.3.1.4 analyse the behaviour and performance of the documented functionality 66 | of the Software and any Burp Apps (defined as aforesaid) and disclose the 67 | findings of such analysis to any party provided that such findings are provided 68 | simultaneously and in identical form to the Licensor; or 69 | 70 | 1.3.2 resell the Software provided that you procure that the purchaser is 71 | bound by the terms of this Licence Agreement for the benefit of the Licensor and 72 | that you indemnify the Licensor against all costs (including legal costs) 73 | charges and expenses incurred by the Licensor as a result of the failure by you 74 | to comply with the provisions of this paragraph and/or the resale by you of the 75 | Software to the purchaser. 76 | 77 | 1.4 If you are a purchaser who has obtained lawfully the Software other than 78 | by direct purchase from the Licensor you may carry out the functions on the 79 | terms specified in paragraph 1.3.1 above and, in consideration of the Licensor 80 | agreeing to provide updates of the Software to you during the Licence Period, 81 | either directly or via the relevant intermediary or intermediaries, you agree to 82 | be bound by this Licence Agreement directly in favour of the Licensor. 83 | 84 | 2. LICENSEE'S WARRANTY AND UNDERTAKINGS 85 | 86 | 2.1 You warrant that you are not purchasing the Software as a consumer, but 87 | will be using the Software in your business and that you are duly authorised by 88 | your business to purchase the Software. 89 | 90 | 2.2 Except as expressly set out in this Licence or as permitted by any local 91 | law, you undertake: 92 | 93 | 2.2.1 not to use the Software, the Documentation or any Burp Apps for any 94 | unlawful purposes, particularly as Burp Suite Professional contains 95 | functionality that can be used to attack and compromise computer systems. 96 | 97 | 2.2.2 to obtain all necessary authorisations from system owners prior to 98 | using Burp Suite Professional or any Burp Apps thereon; 99 | 100 | 2.2.3 to keep confidential any credentials provided by the Licensor enabling 101 | you to log in to the Licensor's server (for the purposes of downloading product 102 | builds and licence keys and to perform product activation, to create Extensions 103 | (as defined in condition 4)), or to access the Burp Collaborator server; 104 | 105 | 2.2.4 not to copy the Software or Documentation except where such copying is 106 | incidental to normal use of the Software, or where it is necessary for the 107 | purpose of back-up or operational security; 108 | 109 | 2.2.5 subject to the provisions of condition 4, not to rent, lease, 110 | sub-license, loan, translate, merge, adapt, vary or modify the Software or 111 | Documentation; 112 | 113 | 2.2.6 subject to the provisions of condition 4, not to make alterations to, or 114 | modifications of, the whole or any part of the Software, nor permit the Software 115 | or any part of it to be combined with, or become incorporated in, any other 116 | programs; 117 | 118 | 2.2.7 not to disassemble, decompile, reverse engineer or create derivative 119 | works based on, the whole or any part of the Software nor attempt to do any such 120 | thing except to the extent that (by virtue of section 296A of the Copyright, 121 | Designs and Patents Act 1988) such actions cannot be prohibited because they are 122 | essential for the purpose of achieving inter-operability of the Software with 123 | another software program, and provided that the information obtained by you 124 | during such activities: 125 | 126 | 2.2.7.1 is used only for the purpose of achieving inter-operability of the 127 | Software with another software program; and 128 | 129 | 2.2.7.2 is not unnecessarily disclosed or communicated without the Licensor's 130 | prior written consent to any third party; and 131 | 132 | 2.2.7.3 is not used to create any software which is substantially similar to 133 | the Software; 134 | 135 | 2.2.8 to keep all copies of the Software secure and to maintain accurate and 136 | up-to-date records of the number and locations of all copies of the Software; 137 | 138 | 2.2.9 to supervise and control use of the Software and ensure that the 139 | Software is used by your employees and representatives in accordance with the 140 | terms of this Licence; 141 | 142 | 2.2.10 to replace the current version of the Software with any updated or 143 | upgraded version or new release provided by the Licensor under the terms of this 144 | Licence immediately on receipt; 145 | 146 | 2.2.11 to include the copyright notice of the Licensor on all entire and 147 | partial copies you make of the Software on any medium; 148 | 149 | 2.2.12 not to provide or otherwise make available the Software in whole or in 150 | part (including but not limited to program listings, object and source program 151 | listings, object code and source code), in any form to any person other than 152 | your employees without prior written consent from the Licensor; 153 | 154 | 2.2.13 unless specifically authorised by us in writing, not to use the 155 | Software as part of an automated service offering to third parties; 156 | 157 | 2.2.14 not to engage in any activity, practice or conduct which would 158 | constitute an offence under sections 1, 2, or 6 of the Bribery Act 2010, if such 159 | activity, practice or conduct had been carried out in the UK; 160 | 161 | 2.2.15 to be responsible for all liability claims, actions, or causes of 162 | action, together with the legal costs of the Licensor in bringing the same, 163 | arising by reason of or in any way relating to your actions or activities of 164 | yourself, your employees, agents, or contractors under this Licence Agreement. 165 | 166 | 3. SUPPORT AND UPGRADES 167 | 168 | 3.1 Purchase of a licence for Burp Suite Professional entitles you to free 169 | product support at the Licensor's sole discretion. 170 | 171 | 3.2 If new releases of Burp Suite Professional are offered for sale, these 172 | may be made available free of charge to you for the duration of your Licence 173 | provided that you enter into a new licence agreement in respect of such new 174 | release. 175 | 176 | 4. EXTENSIONS 177 | 178 | 4.1 In this Licence Agreement "Extension" means all programming additions 179 | made by a Licensee or on his behalf or with his concurrence to the Software 180 | using the Burp Extensions API (as hereinafter defined) to either 181 | 182 | 4.1.1 extend the functionality of the Software or any other software produced 183 | by the Licensor; or 184 | 185 | 4.1.2 enable the Software or any other software produced by the Licensor to 186 | inter-operate with other software; 187 | 188 | but not to copy, clone, reproduce or emulate any existing feature of any 189 | software produced by the Licensor; 190 | 191 | and "Burp App" or "BApp" means an Extension adopted by the Licensor pursuant to 192 | this clause. 193 | 194 | 4.2 "Burp Extensions API" means the official Burp Extensions application 195 | programming interface available as part of the Documentation. 196 | 197 | 4.3 Extensions may be created for the use of the Licensee Provided that if 198 | any such Extension is published (which, for the avoidance of doubt, shall 199 | include sharing such Extension with another Licensee or a third party unless the 200 | party to which the Extension is provided is either a client of the Licensee and 201 | the relevant Extension has been created for use on an engagement for that or 202 | another client of the Licensee, or another Licensee within your organisation) 203 | the Licensee shall notify the Licensor and provide to it a copy of such 204 | Extension and the Licensee agrees that any such Extension shall, at the option 205 | of the Licensor, become either 206 | 207 | 4.3.1 a Burp App; or 208 | 209 | 4.3.2 part of the Software. 210 | 211 | 4.4 When the creation of an Extension is notified to the Licensor or 212 | shared publicly and comes to the attention of the Licensor the Licensor has the 213 | option to make the Extension a Burp App (Burp App, or BApp) after having carried 214 | out the necessary checks to ensure that the Extension is efficacious and 215 | suitable for use with the Software. 216 | 217 | 4.5 The Licensor has established the BApp Store product feature where Burp 218 | Apps are described and may be downloaded without charge for use as an Extension. 219 | 220 | 4.6 By designating an Extension a Burp App the Licensor warrants that the 221 | Extension has been checked by the Licensor and has been deemed suitable for use 222 | with the Software. 223 | 224 | 4.7 All Extensions and Burp Apps remain the property of the author but by 225 | creating such Extension, the author has granted an irrevocable perpetual licence 226 | free of charge to the Licensor to incorporate such Extension in the Software at 227 | the Licensor's option and an irrevocable perpetual licence free of charge to all 228 | Licensees who download the Burp App from the BApp Store. 229 | 230 | 4.8 If, at the sole option of the Licensor, the Licensor incorporates an 231 | Extension into the Software a notice will be placed on the BApp Store to that 232 | effect. 233 | 234 | 4.9 The Licensor retains the right without incurring any liability to the 235 | Licensee to disable without notice any Burp App being used by the Licensee where 236 | the Licensor considers in its sole discretion that use of such Burp App with the 237 | Software is problematical. 238 | 239 | 5. BURP COLLABORATOR 240 | 241 | 5.1 The Licensor has developed Burp Collaborator which is a component of the 242 | Software’s automated and manual testing tools. Burp Collaborator involves the 243 | Licensee deploying a system on the public web (the "Collaborator Server") which 244 | acts as the recipient of third-system interactions that may be triggered by 245 | payloads that the Software sends to target systems enabling the detection of 246 | certain types of vulnerability. A full description of the functionality of Burp 247 | Collaborator forms part of the Documentation. 248 | 249 | 5.2 The functionality of Burp Collaborator gives rise to issues that require 250 | careful consideration by the Licensee as fully set out in the Documentation. By 251 | utilising any features of the Software that may cause interaction with Burp 252 | Collaborator, the Licensee will be deemed to have read the relevant 253 | Documentation, fully understood the functionality and the alternative methods of 254 | utilisation of Burp Collaborator and considered the consequences of utilisation 255 | for its organisation and as a result of such consideration has decided that Burp 256 | Collaborator, in the form utilised by it, is suitable and appropriate for use by 257 | it. The Licensor considers Burp Collaborator to be efficacious in identifying 258 | vulnerabilities of the target website in connection with third-system 259 | interactions, but the Licensee must make its own evaluation before using the 260 | Burp Collaborator Server in one of the alternative manners set out in the 261 | Documentation. 262 | 263 | 6. BURP INFILTRATOR 264 | 265 | 6.1 The Licensor has developed Burp Infiltrator which is a component of the 266 | Software for instrumenting deployed applications in order to facilitate testing 267 | using the Software. Burp Infiltrator involves the Licensee deploying or 268 | procuring deployment of the Infiltrator component within the target system which 269 | enhances the ability of the Software to detect certain types of vulnerability. A 270 | full description of the functionality of Burp Infiltrator forms part of the 271 | Documentation. 272 | 273 | 6.2 The functionality of Burp Infiltrator gives rise to issues that require 274 | careful consideration by the user as fully set out in the Documentation. By 275 | deploying or procuring deployment of the Infiltrator tool, the Licensee will be 276 | deemed to have read the relevant Documentation, fully understood the 277 | functionality of Burp Infiltrator and considered the consequences of utilisation 278 | for its organisation and any bespoke consultancy clients of the Licensee and, as 279 | a result of such consideration, has decided that Burp Infiltrator is suitable 280 | and appropriate for use by it and by any client of the Licensee. The Licensor 281 | considers Burp Infiltrator to be efficacious in helping to identify 282 | vulnerabilities of the target website, but the Licensee must make its own 283 | evaluation before utilising Burp Infiltrator in the manner set out in the 284 | Documentation. 285 | 286 | 6.3 If the Licensee causes its client to install Burp Infiltrator as part of 287 | a bespoke consultancy permitted pursuant to clause 1.3.1 above, by so doing it 288 | warrants to the Licensor that it has recommended to the client to install Burp 289 | Infiltrator on its system and has discussed with the client the contents of the 290 | Documentation relating thereto and the potential consequences of such 291 | installation. 292 | 293 | 7. INTELLECTUAL PROPERTY RIGHTS 294 | 295 | 7.1 You acknowledge that all intellectual property rights in the Software and 296 | the Documentation anywhere in the world belong to the Licensor, that rights in 297 | the Software are licensed (not sold) to you, and that you have no rights in, or 298 | to, the Software or the Documentation other than the right to use them in 299 | accordance with the terms of this Licence. 300 | 301 | 7.2 You acknowledge that you have no right to have access to the Software in 302 | source code form. 303 | 304 | 7.3 The integrity of this Software is protected by technical protection 305 | measures (TPM) so that the intellectual property rights, including copyright, in 306 | the Software of the Licensor are not misappropriated. You must not attempt in 307 | any way to remove or circumvent any such TPM, nor apply or manufacture for sale 308 | or hire, import, distribute, sell or let for hire, offer or expose for sale or 309 | hire, advertise for sale or hire or have in your possession for private or 310 | commercial purposes any means the sole intended purpose of which is to 311 | facilitate the unauthorised removal or circumvention of such TPM. 312 | 313 | 8. LICENSOR'S WARRANTY 314 | 315 | 8.1 The Licensor warrants that for a period of 90 days from the date of 316 | purchase of the Software (Warranty Period) the Software will, when properly 317 | used, perform substantially in accordance with the functions described in the 318 | Documentation (provided that the Software is properly used on the computer and 319 | with the runtime environment for which it was designed as referred to herein). 320 | Burp Apps do not have the benefit of this warranty and the warranty in relation 321 | to Burp Collaborator is limited as set out in the Documentation as it relates to 322 | Burp Collaborator. 323 | 324 | 8.2 You acknowledge that the Software and the Burp Apps have not been 325 | developed to meet your individual requirements, and that it is therefore your 326 | responsibility to ensure that the facilities and functions of the Software as 327 | described in the Documentation and the facilities and functions of any Burp App 328 | meet your requirements. 329 | 330 | 8.3 You acknowledge that the Software and the Burp Apps may not be free of 331 | bugs or errors, and agree that the existence of minor errors shall not 332 | constitute a breach of this Licence. 333 | 334 | 8.4 If, within the Warranty Period, you notify the Licensor in writing of any 335 | defect or fault in the Software in consequence of which it fails to perform 336 | substantially in accordance with the Documentation, and such defect or fault 337 | does not result from you having amended the Software or used it in contravention 338 | of the terms of this Licence, the Licensor will, at its sole option, either 339 | repair or replace the Software, provided that you make available all the 340 | information that may be necessary to help the Licensor to remedy the defect or 341 | fault, including sufficient information to enable the Licensor to recreate the 342 | defect or fault. 343 | 344 | 9. LICENSOR'S LIABILITY 345 | 346 | YOUR ATTENTION IS DRAWN PARTICULARLY TO THE PROVISIONS OF THIS CONDITION 347 | 348 | 9.1 Nothing in this Licence shall limit or exclude the liability of either 349 | party for death or personal injury resulting from negligence, fraud, fraudulent 350 | misrepresentation. 351 | 352 | 9.2 Subject to condition 9.1, the Licensor's liability for losses suffered by 353 | you arising out of or in connection with this agreement (including any liability 354 | for the acts or omissions of its employees, agents and subcontractors), whether 355 | arising in contract, tort (including negligence), misrepresentation or 356 | otherwise, shall not include liability for: 357 | 358 | 9.2.1 loss of turnover, sales or income; 359 | 360 | 9.2.2 loss of business profits or contracts; 361 | 362 | 9.2.3 business interruption; 363 | 364 | 9.2.4 loss of the use of money or anticipated savings; 365 | 366 | 9.2.5 loss of information; 367 | 368 | 9.2.6 loss of opportunity, goodwill or reputation; 369 | 370 | 9.2.7 loss of, damage to or corruption of software or data; or 371 | 372 | 9.2.8 any indirect or consequential loss or damage of any kind howsoever 373 | arising and whether caused by tort (including negligence), breach of contract or 374 | otherwise; 375 | 376 | provided that this condition 9.2 shall not prevent claims for loss of or damage 377 | to your tangible property that fall within the terms of condition 8 or any other 378 | claims for direct financial loss that are not excluded by any of categories 379 | 9.2.1 to 9.2.8 inclusive of this condition 9.2. 380 | 381 | 9.3 Subject to condition 9.1, the Licensor's maximum aggregate liability 382 | under or in connection with this Licence, or any collateral contract, whether in 383 | contract, tort (including negligence) or otherwise, shall be limited to a sum 384 | equal to 100% of the Licence Fee. 385 | 386 | 9.4 Subject to condition 9.1, condition 9.2 and condition 9.3, the Licensor's 387 | liability for infringement of third-party intellectual property rights shall be 388 | limited to breaches of rights subsisting in the UK. 389 | 390 | 9.5 This Licence sets out the full extent of the Licensor's obligations and 391 | liabilities in respect of the supply of the Software and Burp Apps. In 392 | particular, there are no conditions, warranties, representations or other terms, 393 | express or implied, that are binding on the Licensor except as specifically 394 | stated in this Licence. Any condition, warranty, representation or other term 395 | concerning the supply of the Software and Burp Apps which might otherwise be 396 | implied into, or incorporated in, this Licence, or any collateral contract, 397 | whether by statute, common law or otherwise, is hereby excluded to the fullest 398 | extent permitted by law. 399 | 400 | 10. PUBLICITY AND COMMUNICATION 401 | 402 | 10.1 By entering into this Licence Agreement you agree that we may refer 403 | to you as one of our customers internally and in externally published media and, 404 | where relevant, you grant your consent to the use of your logo for this purpose, 405 | unless you notify us in writing that we may not refer to you for such purpose. 406 | Any additional disclosure by us with respect to you shall be subject to your 407 | prior written consent. 408 | 409 | 10.2 By entering into this Licence Agreement you consent that we may 410 | process the personal data that we collect from you in accordance with our 411 | Privacy Policy. In particular, we may use information we hold about you for the 412 | purposes of, inter alia, sending out renewal reminders, questionnaires to 413 | certain categories of users including non-renewers and feedback requests. 414 | 415 | 10.3 In limited circumstances as described in the Documentation as it 416 | relates to Burp Collaborator it is possible that data may be collected by us in 417 | respect of the Licensee and the target systems against which they are using 418 | Burp. We shall deal with all such data in accordance with the Documentation 419 | relating to Burp Collaborator and our Privacy Policy. 420 | 421 | 10.4 Any questions, comments and requests regarding our data processing 422 | practices may be addressed to office@portswigger.net. 423 | 424 | 11. TERMINATION 425 | 426 | 11.1 The Licensor may terminate this Licence immediately by written notice to 427 | you if you commit a material or persistent breach of this Licence which you fail 428 | to remedy (if remediable) within 14 days after the service of written notice 429 | requiring you to do so. 430 | 431 | 11.2 Upon termination for any reason: 432 | 433 | 11.2.1 all rights granted to you under this Licence shall cease; 434 | 435 | 11.2.2 you must cease all activities authorised by this Licence; 436 | 437 | 11.2.3 you must immediately pay to the Licensor any sums due to the Licensor 438 | under this Licence; and 439 | 440 | 11.2.4 you must immediately delete or remove the Software and any Burp Apps 441 | from all computer equipment in your possession, and immediately destroy or 442 | return to the Licensor (at the Licensor's option) all copies of the Software and 443 | Burp Apps then in your possession, custody or control and, in the case of 444 | destruction, certify to the Licensor that you have done so. 445 | 446 | 12. TRANSFER OF RIGHTS AND OBLIGATIONS 447 | 448 | 12.1 This Licence is binding on you and us, and on our respective successors 449 | and assigns. 450 | 451 | 12.2 You may not transfer, assign, charge or otherwise dispose of this 452 | Licence, or any of your rights or obligations arising under it, without our 453 | prior written consent. 454 | 455 | 12.3 We may transfer, assign, charge, sub-contract or otherwise dispose of 456 | this Licence, or any of our rights or obligations arising under it, at any time 457 | during the term of the Licence. 458 | 459 | 13. NOTICES 460 | 461 | All notices given by you to us must be given to PortSwigger Ltd at 462 | office@portswigger.net or Victoria Court, Bexton Road, Knutsford, WA16 0PF 463 | England. We may give notice to you at either the e-mail or postal address you 464 | provided to us when purchasing the Software. Notice will be deemed received and 465 | properly served immediately when posted on our website, 24 hours after an e-mail 466 | is sent, or three days after the date of posting of any letter. In proving the 467 | service of any notice, it will be sufficient to prove, in the case of a letter, 468 | that such letter was properly addressed, stamped and placed in the post and, in 469 | the case of an e-mail, that such e-mail was sent to the specified e-mail address 470 | of the addressee. 471 | 472 | 14. EVENTS OUTSIDE OUR CONTROL 473 | 474 | 14.1 We will not be liable or responsible for any failure to perform, or 475 | delay in performance of, any of our obligations under this Licence that is 476 | caused by events outside our reasonable control (Force Majeure Event). 477 | 478 | 14.2 A Force Majeure Event includes any act, event, non-happening, omission 479 | or accident beyond our reasonable control and includes in particular (without 480 | limitation) the following: 481 | 482 | 14.2.1 strikes, lock-outs or other industrial action; 483 | 484 | 14.2.2 civil commotion, riot, invasion, terrorist attack or threat of 485 | terrorist attack, war (whether declared or not) or threat or preparation for 486 | war; 487 | 488 | 14.2.3 fire, explosion, storm, flood, earthquake, subsidence, epidemic or 489 | other natural disaster; 490 | 491 | 14.2.4 impossibility of the use of railways, shipping, aircraft, motor 492 | transport or other means of public or private transport; 493 | 494 | 14.2.5 impossibility of the use of public or private telecommunications 495 | networks; 496 | 497 | 14.2.6 the acts, decrees, legislation, regulations or restrictions of any 498 | government. 499 | 500 | 14.3 Our performance under this Licence is deemed to be suspended for the 501 | period that the Force Majeure Event continues, and we will have an extension of 502 | time for performance for the duration of that period. We will use our reasonable 503 | endeavours to bring the Force Majeure Event to a close or to find a solution by 504 | which our obligations under this Licence may be performed despite the Force 505 | Majeure Event. 506 | 507 | 15. WAIVER 508 | 509 | 15.1 If we fail, at any time during the term of this Licence, to insist upon 510 | strict performance of any of your obligations under this Licence, or if we fail 511 | to exercise any of the rights or remedies to which we are entitled under this 512 | Licence, this shall not constitute a waiver of such rights or remedies and shall 513 | not relieve you from compliance with such obligations. 514 | 515 | 15.2 A waiver by us of any default shall not constitute a waiver of any 516 | subsequent default. 517 | 518 | 15.3 No waiver by us of any of these terms and conditions shall be effective 519 | unless it is expressly stated to be a waiver and is communicated to you in 520 | writing. 521 | 522 | 16. SEVERABILITY 523 | 524 | If any of the terms of this Licence are determined by any competent authority to 525 | be invalid, unlawful or unenforceable to any extent, such term, condition or 526 | provision will to that extent be severed from the remaining terms, conditions 527 | and provisions which will continue to be valid to the fullest extent permitted 528 | by law. 529 | 530 | 17. ENTIRE AGREEMENT 531 | 532 | 17.1 This Licence and any document expressly referred to in it represents the 533 | entire agreement between us in relation to the licensing of the Software, the 534 | Documentation and any Burp Apps and supersedes any prior agreement, 535 | understanding or arrangement between us, whether oral or in writing. 536 | 537 | 17.2 We each acknowledge that, in entering into this Licence, neither of us 538 | has relied on any representation, undertaking or promise given by the other or 539 | implied from anything said or written in negotiations between us prior to 540 | entering into this Licence except as expressly stated in this Licence. 541 | 542 | 17.3 Neither of us shall have any remedy in respect of any untrue statement 543 | made by the other, whether orally or in writing, prior to the date we entered 544 | into this Licence (unless such untrue statement was made fraudulently) and the 545 | other party's only remedy shall be for breach of contract as provided in these 546 | terms and conditions. 547 | 548 | 18. LAW AND JURISDICTION This Licence, its subject matter or its formation 549 | (including non-contractual disputes or claims) shall be governed by and 550 | construed in accordance with English law and submitted to the exclusive 551 | jurisdiction of the English courts. 552 | --------------------------------------------------------------------------------