{"id":2290,"date":"2023-07-05T11:39:53","date_gmt":"2023-07-05T09:39:53","guid":{"rendered":"https:\/\/security.humanativaspa.it\/?p=2290"},"modified":"2025-12-10T09:01:16","modified_gmt":"2025-12-10T09:01:16","slug":"extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2","status":"publish","type":"post","link":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\/","title":{"rendered":"Extending Burp Suite for fun and profit &#8211; The Montoya way &#8211; Part 2"},"content":{"rendered":"<ol>\n<li><a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-1\">Setting up the environment + Hello World<\/a><\/li>\n<li><strong>-&gt; Inspecting and tampering HTTP requests and responses<\/strong><\/li>\n<li><a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-3\/\">Inspecting and tampering WebSocket messages<\/a><\/li>\n<li><a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-4\/\">Creating new tabs for processing HTTP requests and responses<\/a><\/li>\n<li><a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-5\/\">Adding new functionalities to the context menu (accessible by right-clicking)<\/a><\/li>\n<li><a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-6\">Adding new checks to Burp Suite Active and Passive Scanner<\/a><\/li>\n<li><a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-7\/\">Using the Collaborator in Burp Suite plugins<\/a><\/li>\n<li><a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-8\/\">BChecks &#8211; A quick way to extend Burp Suite Active and Passive Scanner<\/a><\/li>\n<li><a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\/\">Custom scan checks &#8211; An improved quick way to extend Burp Suite Active and Passive Scanner<\/a><\/li>\n<li>&#8230; and much more!<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p>Hi there!<\/p>\n<p>Today we will cover how to develop the type of extension most commonly used during a penetration test, namely <strong>HttpHandler<\/strong> plugins (or <strong>HttpListener<\/strong> in the old APIs). These plugins allow us to inspect or modify all HTTP requests exiting from every tool in Burp Suite and all incoming responses. It is possible to inspect and modify the traffic of specific tools in Burp Suite through other types of plugins as well, but these HttpHandler plugins provide access to all outgoing and incoming traffic.<\/p>\n<p>With the new Montoya API, we can also inspect and modify <strong>WebSocket<\/strong> traffic, one of the features I have been eagerly awaiting for a long time (or better, <strong>the <\/strong>feature I have been waiting for the most). Before Montoya API we could write great plugin to handle encryption, signature, encodings, etc. in HTTP requests and responses and we had to keep our fingers crossed that the application didn&#8217;t use WebSockets. Otherwise, we could use Burp Suite only in standard scenarios and we had to switch to much more inconvenient tools in more complex ones.<\/p>\n<p>Let&#8217;s consider the following example scenario: we have an application that adds a SHA256 hash of the body in an HTTP Header (usually things are a little more complex with for example a HMAC-SHA but let&#8217;s keep things simple). If we intercept a request and modify a parameter in the body without regenerating the hash, the request will be rejected by the backend. In the <strong>Proxy<\/strong> and <strong>Repeater<\/strong>, we can consider manually regenerating the SHA256 for each request we send, but this could significantly slow down the testing process and be quite annoying&#8230;<\/p>\n<p><img decoding=\"async\" class=\"size-full wp-image-2300 aligncenter\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2023\/06\/monkey-laptop-2.gif\" alt=\"\" width=\"498\" height=\"309\" \/><\/p>\n<p>Additionally, if we were to use the <strong>Intruder <\/strong>or\u00a0the <strong>Scanner<\/strong>, every request generated by Burp would be rejected by the backend as it would have an incorrect hash. The best way to handle this type of situation is to create an HttpHandler plugin that transparently regenerates the signatures of all the requests that require it.<\/p>\n<p>Let&#8217;s see how we can do that. First, let&#8217;s code a simple demo backend with Python and Flask.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">import flask\r\nfrom flask import request\r\nfrom hashlib import sha256\r\n\r\napp = flask.Flask(__name__)\r\n\r\n@app.route('\/', methods=['GET', 'POST'])\r\ndef handle_request():\r\n    hash = request.headers.get('Hash')\r\n    body = request.get_data()\r\n    calculated_hash = sha256(body).hexdigest()\r\n    if(hash.strip() == calculated_hash):\r\n        data = request.form.get('data')\r\n        return data\r\n    else:\r\n        return(\"Invalid signature!\")\r\n\r\napp.run(host=\"127.0.0.1\", port=5000, debug=True)<\/pre>\n<p>The code simply extracts the hash contained in the &#8220;Hash&#8221; header, calculates the hash of the body and then compares the two values. If they are equal, the backend returns the values sent in the &#8220;data&#8221; body parameter, otherwise it returns an error. Very simple.<\/p>\n<p>The following request has the <strong>correct SHA256 hash<\/strong>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">POST \/ HTTP\/1.1\r\nHost: localhost\r\nContent-Length: 19\r\nHash: 0bae7db0e4ee21521569abf0b881349c7d1da125a49435f8ea0a733b1ef4be78\r\nContent-Type: application\/x-www-form-urlencoded\r\n\r\ndata=Attack+vector!<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">HTTP\/1.1 200 OK\r\nServer: Werkzeug\/2.3.6 Python\/3.11.3\r\nDate: Mon, 12 Jun 2023 16:05:29 GMT\r\nContent-Type: text\/html; charset=utf-8\r\nContent-Length: 14\r\nConnection: close\r\n\r\nAttack vector!<\/pre>\n<p>The following one has an <strong>invalid hash<\/strong>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">POST \/ HTTP\/1.1\r\nHost: localhost\r\nContent-Length: 21\r\nHash: 0bae7db0e4ee21521569abf0b881349c7d1da125a49435f8ea0a733b1ef4be78\r\nContent-Type: application\/x-www-form-urlencoded\r\n\r\ndata=Attack+vector+2!<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">HTTP\/1.1 200 OK\r\nServer: Werkzeug\/2.3.6 Python\/3.11.3\r\nDate: Mon, 12 Jun 2023 16:10:17 GMT\r\nContent-Type: text\/html; charset=utf-8\r\nContent-Length: 18\r\nConnection: close\r\n\r\nInvalid signature!<\/pre>\n<p>Let&#8217;s run our IDE and create the skeleton for an empty plugin (refer to <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-1\">part 1<\/a> for the tutorial on how to setup the IDE and create the skeleton).<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">package org.fd.montoyatutorial;\r\n\r\nimport burp.api.montoya.BurpExtension;\r\nimport burp.api.montoya.MontoyaApi;\r\nimport burp.api.montoya.logging.Logging;\r\n\r\npublic class HttpHandlerExample implements BurpExtension {\r\n\r\n    MontoyaApi api;\r\n    Logging logging;\r\n\r\n    @Override\r\n    public void initialize(MontoyaApi api) {\r\n\r\n        \/\/ Save a reference to the MontoyaApi object\r\n        this.api = api;\r\n\r\n        \/\/ api.logging() returns an object that we can use to print messages to stdout and stderr\r\n        this.logging = api.logging();\r\n\r\n        \/\/ Set the name of the extension\r\n        api.extension().setName(\"Montoya API tutorial - HttpHandlerExample\");\r\n\r\n        \/\/ Print a message to the stdout\r\n        this.logging.logToOutput(\"*** Montoya API tutorial - HttpHandlerExample loaded ***\");\r\n\r\n    }\r\n}\r\n<\/pre>\n<p>The APIs that allow to modify requests and responses can be accessed through the <em><strong>http<\/strong><\/em><strong> method<\/strong> of the <em>MontoyaApi<\/em> object passed as an argument to the plugin&#8217;s initialization function (which we saved in a variable to access it anywhere in our plugin).<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-2302\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2023\/06\/api1-2.png\" alt=\"\" width=\"1237\" height=\"608\" \/><\/p>\n<p>In detail, within our <em>initialize<\/em> method, we will declare that we want our plugin to receive outgoing requests and incoming responses by providing an object that will handle processing them. We will do this by calling the <em>registerHttpHandler<\/em>\u00a0method of the <em>Http<\/em> object obtained in the previous step.<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-2303\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2023\/06\/api2-2.png\" alt=\"\" width=\"1269\" height=\"708\" \/><\/p>\n<p>We need to provide to the <em>registerHttpHandler<\/em> method an object constructed by us that implements the <em>HttpHandler<\/em> interface, which means it offers the methods <em>handleHttpRequestToBeSent<\/em> and <em>handleHttpResponseReceived<\/em>.<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-2304\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2023\/06\/api3-2.png\" alt=\"\" width=\"1252\" height=\"403\" \/><\/p>\n<p>Well, first we define our <em>HttpHandler<\/em> object responsible to handle requests and responses and then we will pass this object in the initialization method. <strong>Little hint:<\/strong> IDEs are perfect for automatically fixing issues and avoiding writing &#8220;boilerplate&#8221; code. For example, they can automatically create the skeleton of functions defined in an interface implemented in the current class, correct imports, add constructors and getter\/setter methods, saving you time from writing tedious code. Example:<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-2306\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2023\/06\/api4-2.png\" alt=\"\" width=\"1449\" height=\"354\" \/><\/p>\n<p>This is the skeleton of our <em>HttpHandler <\/em>(that probably blocks every exiting request and entering response or simply throws exceptions when they are processed):<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">package org.fd.montoyatutorial;\r\n\r\nimport burp.api.montoya.http.handler.*;\r\n\r\npublic class CustomHttpHandler implements HttpHandler {\r\n    @Override\r\n    public RequestToBeSentAction handleHttpRequestToBeSent(HttpRequestToBeSent requestToBeSent) {\r\n        return null;\r\n    }\r\n\r\n    @Override\r\n    public ResponseReceivedAction handleHttpResponseReceived(HttpResponseReceived responseReceived) {\r\n        return null;\r\n    }\r\n}<\/pre>\n<p>First, let&#8217;s fix the plugin in order to simply let requests and responses pass without modifications. As we can see, <em>handleHttpRequestToBeSent <\/em>should return an object of type <em>RequestToBeSentAction <\/em>while <em>handleHttpResponseReceived\u00a0<\/em>should return a <em>ResponseReceivedAction <\/em>object<em>. <\/em>So, we need a way to create or get objects of types <em>RequestToBeSentAction<\/em> and <em>ResponseReceivedAction.\u00a0<\/em><\/p>\n<p>When you find yourself in such situations, the first thing you should do is consult the documentation of the interface for which you need an object (I said &#8220;interface&#8221; because in Burp Suite API there ale almost only interfaces and rarely classes or abstract classes). In most cases, in the Montoya APIs, you will find static methods (which can be called directly from the interface itself rather than from an instance of a class that implements it) that allow you to obtain an instance of an object implementing that interface (defined somewhere in Burp Suite code). This was not always the case in previous APIs, where sometimes it was necessary to write classes that implemented certain interfaces, often used only as &#8220;containers&#8221; (thanks, Burp! I really appreciate it!).<\/p>\n<p>The <em>RequestToBeSentAction\u00a0<\/em>contains two static methods that we can use for the purpose (the same applies also for <em>ResponseReceivedAction<\/em>):<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-2309\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2023\/06\/api5-2.png\" alt=\"\" width=\"1251\" height=\"510\" \/><\/p>\n<p>The\u00a0<em>continueWith<\/em> method takes as argument a request (and if we want also an\u00a0<em>Annotation <\/em>object, that allows to add notes to the request in Burp Suite and\/or highlight the request) and returns the container object we need. We can fix our class as follows:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">package org.fd.montoyatutorial;\r\n\r\nimport burp.api.montoya.http.handler.*;\r\n\r\npublic class CustomHttpHandler implements HttpHandler {\r\n    @Override\r\n    public RequestToBeSentAction handleHttpRequestToBeSent(HttpRequestToBeSent requestToBeSent) {\r\n        return RequestToBeSentAction.continueWith(requestToBeSent);\r\n    }\r\n\r\n    @Override\r\n    public ResponseReceivedAction handleHttpResponseReceived(HttpResponseReceived responseReceived) {\r\n        return ResponseReceivedAction.continueWith(responseReceived);\r\n    }\r\n}<\/pre>\n<p>Now our\u00a0<em>HttpHandler<\/em> simply forwards requests and responses without executing any operation on them. We can now register our listener in the main class of the plugin with the registration method <em>registerHttpHandler<\/em> we saw before in the documentation:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">package org.fd.montoyatutorial;\r\n\r\nimport burp.api.montoya.BurpExtension;\r\nimport burp.api.montoya.MontoyaApi;\r\nimport burp.api.montoya.logging.Logging;\r\n\r\npublic class HttpHandlerExample implements BurpExtension {\r\n\r\n    MontoyaApi api;\r\n    Logging logging;\r\n\r\n    @Override\r\n    public void initialize(MontoyaApi api) {\r\n\r\n        ...\r\n\r\n        \/\/ Register our HttpHandler\r\n        api.http().registerHttpHandler(new CustomHttpHandler());\r\n\r\n    }\r\n}<\/pre>\n<p>Now it&#8217;s time to implement the logic of our plugin. We add a small constructor to our HttpListener class, in order to save also here a reference to the <em>MontoyaApi<\/em> object, essential for interacting with just about anything.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">public class CustomHttpHandler implements HttpHandler {\r\n\r\n    MontoyaApi api;\r\n    Logging logging;\r\n\r\n    public CustomHttpHandler(MontoyaApi api) {\r\n        \/\/ Save a reference to the MontoyaApi object\r\n        this.api = api;\r\n        \/\/ api.logging() returns an object that we can use to print messages to stdout and stderr\r\n        this.logging = api.logging();\r\n    }\r\n[...]\r\n<\/pre>\n<p>Then, we can implement the real purpose of the plugin. Burp Suite provides many convenient features for extracting data and modifying requests and responses that we can use for our tasks, <a href=\"https:\/\/portswigger.github.io\/burp-extensions-montoya-api\/javadoc\/burp\/api\/montoya\/http\/handler\/HttpRequestToBeSent.html\">detailed in the documentation<\/a>.<\/p>\n<p>The plugin will:<\/p>\n<ol>\n<li>Check if the request contains the header <em>Hash<\/em>. If not, it will returns the original request<\/li>\n<li>Extract the body of the request<\/li>\n<li>Sign the body of the request with SHA-256 (Burp Suite Montoya API offers also a <a href=\"https:\/\/portswigger.github.io\/burp-extensions-montoya-api\/javadoc\/burp\/api\/montoya\/utilities\/CryptoUtils.html\">function to generate digests<\/a>)<\/li>\n<li>Replace the old value of the header <em>Hash <\/em>with the new digest<\/li>\n<li>Send the edited request<\/li>\n<\/ol>\n<p>Extracting the body, extracting the headers and updating the headers are all operations offered by the <em>HttpRequestToBeSent <\/em>interfaced, of which we have an object supplied as argument to the <em>handleHttpRequestToBeSent <\/em>function.<\/p>\n<p>The SHA256 digest can be computed using the <a href=\"https:\/\/portswigger.github.io\/burp-extensions-montoya-api\/javadoc\/burp\/api\/montoya\/utilities\/Utilities.html\">Burp Suite utilities API<\/a>. We can obtain the reference from the usual <em>MontoyaApi<\/em> object. The utilities API includes various functions to handle common operations, like number operations, string operations, HTML and URL encoding, hashing, compression, random, and so on.<\/p>\n<p>The final code of the <em>handleHttpRequestToBeSent <\/em>is the following:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">@Override\r\npublic RequestToBeSentAction handleHttpRequestToBeSent(HttpRequestToBeSent requestToBeSent) {\r\n\r\n    \/\/ Get a list of HTTP headers of the request\r\n    List&lt;HttpHeader&gt; headers = requestToBeSent.headers();\r\n\r\n    \/\/ 1 - Check if the list contains an header named \"Hash\" (using Java streams, introduced in Java 8)\r\n    if(headers.stream().map(HttpHeader::name).anyMatch(h -&gt; h.trim().equals(\"Hash\"))) {\r\n\r\n        \/\/ 2 - Extract the body of the request, using \"body\" function of the HttpRequestToBeSent object\r\n        \/\/ https:\/\/portswigger.github.io\/burp-extensions-montoya-api\/javadoc\/burp\/api\/montoya\/http\/handler\/HttpRequestToBeSent.html\r\n        ByteArray body = requestToBeSent.body();\r\n\r\n        \/\/ Get a reference to the CryptoUtils offered by Burp Suite\r\n        \/\/ https:\/\/portswigger.github.io\/burp-extensions-montoya-api\/javadoc\/burp\/api\/montoya\/utilities\/CryptoUtils.html\r\n        CryptoUtils cryptoUtils = api.utilities().cryptoUtils();\r\n\r\n        \/\/ 3 - Calculate SHA256 hash\r\n        ByteArray sha256hash = cryptoUtils.generateDigest(body, DigestAlgorithm.SHA_256);\r\n\r\n        \/\/ Convert SHA256 bytes to a HEX string, using a Java way\r\n        String digest = String.format(\"%064x\", new BigInteger(1, sha256hash.getBytes()));\r\n\r\n        \/\/ 4 - Set the hash in the \"Hash\" HTTP header, using withUpdatedHeader of the HttpRequestToBeSent object\r\n        HttpRequest modifiedRequest = requestToBeSent.withUpdatedHeader(\"Hash\",digest);\r\n\r\n        \/\/ 5 - Return the container object feeded with the modified request\r\n        return RequestToBeSentAction.continueWith(modifiedRequest);\r\n\r\n    }\r\n\r\n    return RequestToBeSentAction.continueWith(requestToBeSent);\r\n\r\n}<\/pre>\n<p>Action 1 (check if the <em>Hash <\/em>header is present) has been executed using Java 8 streams (lambda expressions and similar things). If you are not familiar with these constructs, you can replace that portion of code with something like:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">boolean headerFound = false;\r\nfor(int i=0;i&lt;headers.size();i++) {\r\n    if(headers.get(i).name().trim().equals(\"Hash\")) {\r\n        found = true;\r\n        break;\r\n    }\r\n}\r\nif(headerFound) {\r\n    \/\/ ...\r\n}<\/pre>\n<p>After building the plugin (see <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-1\">part 1<\/a> for reference) and loading it in Burp Suite, we can try it with out test backend by repeating the two requests we sent at the beginning.<\/p>\n<p>The following request has the <strong>correct SHA256 hash<\/strong>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">POST \/ HTTP\/1.1\r\nHost: localhost\r\nContent-Length: 19\r\nHash: 0bae7db0e4ee21521569abf0b881349c7d1da125a49435f8ea0a733b1ef4be78\r\nContent-Type: application\/x-www-form-urlencoded\r\n\r\ndata=Attack+vector!<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">HTTP\/1.1 200 OK\r\nServer: Werkzeug\/2.3.6 Python\/3.11.3\r\nDate: Mon, 12 Jun 2023 16:05:29 GMT\r\nContent-Type: text\/html; charset=utf-8\r\nContent-Length: 14\r\nConnection: close\r\n\r\nAttack vector!<\/pre>\n<p>The following one should have an <strong>invalid hash<\/strong> (we did not manually regenerate the hash):<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">POST \/ HTTP\/1.1\r\nHost: localhost\r\nContent-Length: 21\r\nHash: 0bae7db0e4ee21521569abf0b881349c7d1da125a49435f8ea0a733b1ef4be78\r\nContent-Type: application\/x-www-form-urlencoded\r\n\r\ndata=Attack+vector+2!<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">HTTP\/1.1 200 OK\r\nServer: Werkzeug\/2.3.6 Python\/3.11.3\r\nDate: Mon, 12 Jun 2023 16:10:17 GMT\r\nContent-Type: text\/html; charset=utf-8\r\nContent-Length: 18\r\nConnection: close\r\n\r\nAttack vector 2!<\/pre>\n<p>As we can see, the backend seems to accept the second request even if it appears to have an incorrect hash. <strong>The reason is that our plugin is working correctly and is transparently modifying the hash before the request leaves Burp Suite.<\/strong> That&#8217;s why in the Repeater, we continue to see an incorrect hash even though it&#8217;s not the one actually reaching the backend. We can see the actual request in the <em>Logger <\/em>tab of Burp Suite (that as you can see has a different hash value):<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-2312\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2023\/06\/api6-2.png\" alt=\"\" width=\"1133\" height=\"418\" \/><\/p>\n<div class=\"group w-full text-gray-800 dark:text-gray-100 border-b border-black\/10 dark:border-gray-900\/50 bg-gray-50 dark:bg-[#444654]\">\n<div class=\"flex p-4 gap-4 text-base md:gap-6 md:max-w-2xl lg:max-w-[38rem] xl:max-w-3xl md:py-6 lg:px-0 m-auto\">\n<div class=\"relative flex w-[calc(100%-50px)] flex-col gap-1 md:gap-3 lg:w-[calc(100%-115px)]\">\n<div class=\"flex flex-grow flex-col gap-3\">\n<div class=\"min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap break-words\">\n<p>Similarly, by using our plugin, we can confidently use Burp Suite&#8217;s Intruder or Scanner, as the hash will be recalculated by the plugin before the actual sending of the requests.<\/p>\n<p><img decoding=\"async\" class=\"size-full wp-image-2313 aligncenter\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2023\/06\/api7-2.png\" alt=\"\" width=\"828\" height=\"538\" \/><\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Our plugin will process each request exiting from Burp Suite, but we can also process only requests from specific tools, using the <em>toolSource<\/em> method of the <em>HttpRequestToBeSent<\/em> obejct. As an example, we edit our plugin to process only Repeater, Scanner, and Intruder traffic as follows:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">@Override\r\npublic RequestToBeSentAction handleHttpRequestToBeSent(HttpRequestToBeSent requestToBeSent) {\r\n\r\n    if(requestToBeSent.toolSource().isFromTool(ToolType.REPEATER, ToolType.SCANNER, ToolType.INTRUDER)) {\r\n\r\n        [...]<\/pre>\n<p><strong>Hint: <\/strong>To process the traffic generated by other extensions, such as a Burp Scanner extension, it is necessary to include <em>ToolType.EXTENSIONS<\/em> as well. Otherwise, the requests made by other extensions will be excluded from processing. In our scenario, the hash should be updated also in requests generated by third-party extensions (like Scanner or Intruder ones), otherwise they checks will fail.<\/p>\n<p><strong>Second hint: <\/strong>Be careful when you have multiple <em>HttpListener<\/em> plugins, as you may need them to be executed <strong>in a specific order<\/strong>. For example, if one plugin modifies the request body and another one computes the hash, if the two plugins are not executed in the correct order, the hash will be incorrect (because the hash should be computed <strong>after<\/strong> any body update). Burp Suite maintains a kind of listener queue, and requests are sent in order through that queue. In the &#8220;Extensions&#8221; -&gt; &#8220;Installed&#8221; tab, you can reorder the extensions by moving them up or down. However, in the past, I have encountered situations where the order in which requests were processed by plugins did not respect that ordering. My advice in this case is not only to arrange them in the correct order in the mentioned tab but also to load them in the order you require to avoid any issues.<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-2315\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2023\/06\/api8-2.png\" alt=\"\" width=\"1186\" height=\"340\" \/><\/p>\n<p>I would have liked to include an example on WebSockets as well, but this article has already become too long. We will explore the topic in next episode.<\/p>\n<p>Full example code (including the backed used for the scenario) can be downloaded in <a href=\"https:\/\/github.com\/federicodotta\/Burp-Suite-Extender-Montoya-Course\">my GitHub repository<\/a>.<\/p>\n<p>Cheers!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Setting up the environment + Hello World -&gt; Inspecting and tampering HTTP requests and responses Inspecting and tampering WebSocket messages [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":159897,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[91,88],"tags":[115,185,186,187,188,189,104],"class_list":["post-2290","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-articles","category-tools","tag-web","tag-extender","tag-extender-course","tag-extending-burp-suite","tag-montoya-api","tag-tutorial","tag-burp-suite"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>HN Security Extending Burp Suite for fun and profit - The Montoya way - Part 2<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\/\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"HN Security Extending Burp Suite for fun and profit - The Montoya way - Part 2\" \/>\n<meta property=\"og:description\" content=\"Setting up the environment + Hello World -&gt; Inspecting and tampering HTTP requests and responses Inspecting and tampering WebSocket messages [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\/\" \/>\n<meta property=\"og:site_name\" content=\"HN Security\" \/>\n<meta property=\"article:published_time\" content=\"2023-07-05T09:39:53+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-12-10T09:01:16+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/BURP.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1600\" \/>\n\t<meta property=\"og:image:height\" content=\"836\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Federico Dotta\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@hnsec\" \/>\n<meta name=\"twitter:site\" content=\"@hnsec\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"Federico Dotta\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minuti\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\\\/\"},\"author\":{\"name\":\"Federico Dotta\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#\\\/schema\\\/person\\\/e0e6046bd2bc829f7d945ad361bce702\"},\"headline\":\"Extending Burp Suite for fun and profit &#8211; The Montoya way &#8211; Part 2\",\"datePublished\":\"2023-07-05T09:39:53+00:00\",\"dateModified\":\"2025-12-10T09:01:16+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\\\/\"},\"wordCount\":1778,\"publisher\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2025\\\/09\\\/BURP.jpg\",\"keywords\":[\"web\",\"Extender\",\"Extender course\",\"Extending Burp Suite\",\"Montoya API\",\"Tutorial\",\"Burp Suite\"],\"articleSection\":[\"Articles\",\"Tools\"],\"inLanguage\":\"it-IT\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\\\/\",\"url\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\\\/\",\"name\":\"HN Security Extending Burp Suite for fun and profit - The Montoya way - Part 2\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2025\\\/09\\\/BURP.jpg\",\"datePublished\":\"2023-07-05T09:39:53+00:00\",\"dateModified\":\"2025-12-10T09:01:16+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\\\/#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\\\/#primaryimage\",\"url\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2025\\\/09\\\/BURP.jpg\",\"contentUrl\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2025\\\/09\\\/BURP.jpg\",\"width\":1600,\"height\":836},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Extending Burp Suite for fun and profit &#8211; The Montoya way &#8211; Part 2\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#website\",\"url\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/\",\"name\":\"HN Security\",\"description\":\"Offensive Security Specialists\",\"publisher\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"it-IT\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#organization\",\"name\":\"HN Security\",\"url\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2026\\\/01\\\/hn-libellula.jpg\",\"contentUrl\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2026\\\/01\\\/hn-libellula.jpg\",\"width\":696,\"height\":696,\"caption\":\"HN Security\"},\"image\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/hnsec\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/hnsecurity\\\/\",\"https:\\\/\\\/github.com\\\/hnsecurity\",\"https:\\\/\\\/infosec.exchange\\\/@hnsec\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#\\\/schema\\\/person\\\/e0e6046bd2bc829f7d945ad361bce702\",\"name\":\"Federico Dotta\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/02d5d800b81f2a125ac23ee31a108ee2404d123bd3b722f2e263f0130cc1df42?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/02d5d800b81f2a125ac23ee31a108ee2404d123bd3b722f2e263f0130cc1df42?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/02d5d800b81f2a125ac23ee31a108ee2404d123bd3b722f2e263f0130cc1df42?s=96&d=mm&r=g\",\"caption\":\"Federico Dotta\"},\"url\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/author\\\/federico-dotta\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"HN Security Extending Burp Suite for fun and profit - The Montoya way - Part 2","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\/","og_locale":"it_IT","og_type":"article","og_title":"HN Security Extending Burp Suite for fun and profit - The Montoya way - Part 2","og_description":"Setting up the environment + Hello World -&gt; Inspecting and tampering HTTP requests and responses Inspecting and tampering WebSocket messages [&hellip;]","og_url":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\/","og_site_name":"HN Security","article_published_time":"2023-07-05T09:39:53+00:00","article_modified_time":"2025-12-10T09:01:16+00:00","og_image":[{"width":1600,"height":836,"url":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/BURP.jpg","type":"image\/jpeg"}],"author":"Federico Dotta","twitter_card":"summary_large_image","twitter_creator":"@hnsec","twitter_site":"@hnsec","twitter_misc":{"Scritto da":"Federico Dotta","Tempo di lettura stimato":"10 minuti"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\/#article","isPartOf":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\/"},"author":{"name":"Federico Dotta","@id":"https:\/\/hnsecurity.it\/it\/#\/schema\/person\/e0e6046bd2bc829f7d945ad361bce702"},"headline":"Extending Burp Suite for fun and profit &#8211; The Montoya way &#8211; Part 2","datePublished":"2023-07-05T09:39:53+00:00","dateModified":"2025-12-10T09:01:16+00:00","mainEntityOfPage":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\/"},"wordCount":1778,"publisher":{"@id":"https:\/\/hnsecurity.it\/it\/#organization"},"image":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\/#primaryimage"},"thumbnailUrl":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/BURP.jpg","keywords":["web","Extender","Extender course","Extending Burp Suite","Montoya API","Tutorial","Burp Suite"],"articleSection":["Articles","Tools"],"inLanguage":"it-IT"},{"@type":"WebPage","@id":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\/","url":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\/","name":"HN Security Extending Burp Suite for fun and profit - The Montoya way - Part 2","isPartOf":{"@id":"https:\/\/hnsecurity.it\/it\/#website"},"primaryImageOfPage":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\/#primaryimage"},"image":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\/#primaryimage"},"thumbnailUrl":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/BURP.jpg","datePublished":"2023-07-05T09:39:53+00:00","dateModified":"2025-12-10T09:01:16+00:00","breadcrumb":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\/#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\/"]}]},{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\/#primaryimage","url":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/BURP.jpg","contentUrl":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/BURP.jpg","width":1600,"height":836},{"@type":"BreadcrumbList","@id":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/hnsecurity.it\/it\/"},{"@type":"ListItem","position":2,"name":"Extending Burp Suite for fun and profit &#8211; The Montoya way &#8211; Part 2"}]},{"@type":"WebSite","@id":"https:\/\/hnsecurity.it\/it\/#website","url":"https:\/\/hnsecurity.it\/it\/","name":"HN Security","description":"Offensive Security Specialists","publisher":{"@id":"https:\/\/hnsecurity.it\/it\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/hnsecurity.it\/it\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"it-IT"},{"@type":"Organization","@id":"https:\/\/hnsecurity.it\/it\/#organization","name":"HN Security","url":"https:\/\/hnsecurity.it\/it\/","logo":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/hnsecurity.it\/it\/#\/schema\/logo\/image\/","url":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2026\/01\/hn-libellula.jpg","contentUrl":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2026\/01\/hn-libellula.jpg","width":696,"height":696,"caption":"HN Security"},"image":{"@id":"https:\/\/hnsecurity.it\/it\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/hnsec","https:\/\/www.linkedin.com\/company\/hnsecurity\/","https:\/\/github.com\/hnsecurity","https:\/\/infosec.exchange\/@hnsec"]},{"@type":"Person","@id":"https:\/\/hnsecurity.it\/it\/#\/schema\/person\/e0e6046bd2bc829f7d945ad361bce702","name":"Federico Dotta","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/secure.gravatar.com\/avatar\/02d5d800b81f2a125ac23ee31a108ee2404d123bd3b722f2e263f0130cc1df42?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/02d5d800b81f2a125ac23ee31a108ee2404d123bd3b722f2e263f0130cc1df42?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/02d5d800b81f2a125ac23ee31a108ee2404d123bd3b722f2e263f0130cc1df42?s=96&d=mm&r=g","caption":"Federico Dotta"},"url":"https:\/\/hnsecurity.it\/it\/blog\/author\/federico-dotta\/"}]}},"jetpack_featured_media_url":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/BURP.jpg","_links":{"self":[{"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts\/2290","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/comments?post=2290"}],"version-history":[{"count":2,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts\/2290\/revisions"}],"predecessor-version":[{"id":161267,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts\/2290\/revisions\/161267"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/media\/159897"}],"wp:attachment":[{"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/media?parent=2290"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/categories?post=2290"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/tags?post=2290"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}