{"id":161180,"date":"2025-12-10T09:02:32","date_gmt":"2025-12-10T09:02:32","guid":{"rendered":"https:\/\/hnsecurity.it\/?p=161180"},"modified":"2025-12-10T09:02:32","modified_gmt":"2025-12-10T09:02:32","slug":"extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9","status":"publish","type":"post","link":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\/","title":{"rendered":"Extending Burp Suite for fun and profit \u2013 The Montoya way \u2013 Part 9"},"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><a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-2\">Inspecting and tampering HTTP requests and responses<\/a><\/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><strong>Custom scan checks &#8211; An improved quick way to extend Burp Suite Active and Passive Scanner<\/strong><\/li>\n<li>&#8230; and much more!<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p>Hi there!<\/p>\n<p>In the past three articles, we have seen how to <strong>extend Burp&#8217;s Active and Passive scanner<\/strong>, how to use the <strong>Collaborator<\/strong> and how to use <strong>BChecks<\/strong>, a recent feature that allows to add checks to the Active and Passive Scanner without developing dedicated extensions.<\/p>\n<p>BChecks are a very quick way to extend Burp Scanner but they can be used only for a small subset of checks. As we saw in <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-8\/\">Part 8<\/a>, none of the checks implemented for the active scanner in <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-6\/\">Part 6<\/a> and <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-7\/\">Part 7<\/a> could be defined using BChecks. In the case of <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-6\/\">Part 6<\/a>, this is because BChecks currently do not allow to obtain the response time, and in the case of <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-7\/\">Part 7<\/a>, it is not possible to perform operations on byte arrays, which are necessary for constructing the payloads used in that particular extension.<\/p>\n<p>Now, since version 2025.9.5 of Burp Suite, we can also extend Burp Suite Scanner without a dedicated extension with a <strong>Java-like language<\/strong>, in a similar way of what we do with <strong>Bambda<\/strong> filters present in many Burp Suite tools. This new functionality has been grouped with BChecks under the new &#8220;<strong>Custom scan checks&#8221; extension tab. <\/strong>With this new powerful option, we can create a custom scan check with almost all the functionalities we have in a standalone extension. Obviously, for complex scenarios, a full-blown external extension may be the best (or the only viable) option, but if our check is not too complex and does not require external libraries, custom scan checks are a great option (actually, in the Extender settings we can point Burp to a folder where it will look for Java libraries; I don&#8217;t think we can call them from custom scan checks, but to be honest I haven&#8217;t tried yet).<\/p>\n<p>Custom scan checks can be created, enabled\/disabled, imported\/exported, deleted, etc. in the Extensions tab of Burp Suite, in the &#8220;Custom scan check&#8221; tab. This tab has replaced the old &#8220;BChecks&#8221; tab, because now you can create both Java-like scan checks and YAML-like BChecks.<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-161190 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image.png\" alt=\"\" width=\"1340\" height=\"708\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image.png 1340w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-300x159.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-1024x541.png 1024w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-768x406.png 768w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-350x185.png 350w\" sizes=\"(max-width: 1340px) 100vw, 1340px\" \/><\/p>\n<p>The development environment is the same we saw in the <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-8\/\">BChecks article<\/a>. We have a full development environment that can be used to develop, test, and try the custom scan checks. We have tools to <strong>develop the code<\/strong>, <strong>check if syntax is correct,<\/strong> <strong>test on sample requests\/responses<\/strong>, a <strong>dedicated Logger, Issue activity, and Event log tabs. <\/strong>Refer to <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-8\/\">Part 8<\/a>\u00a0for a full description of the development environment.<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-161191 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-2.png\" alt=\"\" width=\"1530\" height=\"950\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-2.png 1530w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-2-300x186.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-2-1024x636.png 1024w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-2-768x477.png 768w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-2-350x217.png 350w\" sizes=\"(max-width: 1530px) 100vw, 1530px\" \/><\/p>\n<p>We can create the following types of Java-like custom scan checks:<\/p>\n<ul>\n<li>Type: <strong>ACTIVE<\/strong> &#8211; &gt; Active checks can make request to actively probe for vulnerabilities\n<ul>\n<li>Check runs: Per insertion point -&gt; Executed once per insertion point; most common type of operation that add payload in parameters, headers, and cookies (e.g., probe for SQL Injection in a GET parameter)<\/li>\n<li>Check runs: Per request -&gt; Executed once per request; commonly used for checks that manipulate the full request or response (e.g., payload that replaces the request body)<\/li>\n<li>Check runs: Per host -&gt; Executed once per host; commonly used for checks that require only host information (e.g., check for the presence of the &#8220;\/manager\/html&#8221; admin interface)<\/li>\n<\/ul>\n<\/li>\n<li>Type: <strong>PASSIVE<\/strong> -&gt; Passive checks should analyze traffic without making any new request\n<ul>\n<li>Check runs: Per request -&gt; Executed once per request; commonly used for checks that analyze the full request or response (e.g., check for the presence of serialized objects in requests\/responses)<\/li>\n<li>Check runs: Per host -&gt; Executed once per host; commonly used for checks that execute analysis on properties that should be consistent across the same host (e.g., security headers or information leakage on &#8220;Server&#8221; header)<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Depending on the plugin type and check run, we have different objects available from our code. We can inspect the available objects as follows:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-161193 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-4.png\" alt=\"\" width=\"1524\" height=\"942\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-4.png 1524w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-4-300x185.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-4-1024x633.png 1024w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-4-768x475.png 768w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-4-350x216.png 350w\" sizes=\"(max-width: 1524px) 100vw, 1524px\" \/><\/p>\n<p>All plugins have:<\/p>\n<ul>\n<li>The <a href=\"https:\/\/portswigger.github.io\/burp-extensions-montoya-api\/javadoc\/burp\/api\/montoya\/http\/message\/HttpRequestResponse.html\">HttpRequestResponse<\/a> object (parameter <em>requestResponse<\/em>), that contains the request\/response currently analyzed<\/li>\n<li>The <a href=\"https:\/\/portswigger.github.io\/burp-extensions-montoya-api\/javadoc\/burp\/api\/montoya\/MontoyaApi.html\">MontoyaApi<\/a> object (parameter <em>api<\/em>), that is the core of each Montoya plugin (as we saw in previous articles) and give access to all Burp Suite tools and instruments<\/li>\n<\/ul>\n<p>Active plugins can also access an <a href=\"https:\/\/portswigger.github.io\/burp-extensions-montoya-api\/javadoc\/burp\/api\/montoya\/http\/Http.html\">Http<\/a> object (parameter <em>http<\/em>) that can be used to send requests (that I think is the same object that we can get directly from the MontoyaApi object with <em>api.http()<\/em> ). Finally, active checks executed per insertion point have also an <a href=\"https:\/\/portswigger.github.io\/burp-extensions-montoya-api\/javadoc\/burp\/api\/montoya\/scanner\/audit\/insertionpoint\/AuditInsertionPoint.html\">AuditInsertionPoint<\/a> object (parameter\u00a0<em>insertionPoint<\/em>) with details on the specific insertion point and useful functions to create copies of the target request with our payload in the current insertion point.<\/p>\n<p>We already saw all these objects in <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-6\/\">Part 6<\/a> and <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-7\/\">Part 7<\/a>, because they are exactly the same objects used in external Montoya scanner extensions. All plugins must return an <a href=\"https:\/\/portswigger.github.io\/burp-extensions-montoya-api\/javadoc\/burp\/api\/montoya\/scanner\/AuditResult.html\">AuditResult<\/a> object, that contains the found issues (and that is again the same object returned in external scanner extensions).<\/p>\n<p>So, in <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-8\/\">Part 8<\/a> we saw some BChecks examples, but we could not implement checks of <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-6\/\">Part 6<\/a> and <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-7\/\">Part 7<\/a> due to some BCheck limitations. Now, <strong>using the new Java-like script engine we can implement those checks<\/strong>. So, let&#8217;s port them! We will use the same target application and environment for this purpose: a <strong>Java application that deserializes the input sent to it<\/strong>, packaged with a vulnerable version of the Apache Commons Collections 3 library, which offers one of these serializable objects that allow for the execution of arbitrary Java code once deserialized. The sample target application can be downloaded from <a href=\"https:\/\/github.com\/federicodotta\/Burp-Suite-Extender-Montoya-Course\/tree\/main\">my Github repository<\/a>. To deploy it, a Java application server is necessary. I used <strong>Apache Tomcat<\/strong>, which is easy to configure (for details on the vulnerable environment refer to <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-6\/\">Part 6<\/a>).<\/p>\n<p>Let&#8217;s start with the <strong>active check<\/strong> we coded in <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-6\/\">Part 6<\/a>, that tries to <strong>detect Java serialization vulnerabilities<\/strong> using a sleep payload for the Apache Commons Collections 3 library. We implemented this check as follows:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">@Override\r\npublic AuditResult activeAudit(HttpRequestResponse baseRequestResponse, AuditInsertionPoint auditInsertionPoint) {\r\n\r\n    \/\/ Inizialize an empty list of audit issues that we will eventually populate and return at the end of the function\r\n    List&lt;AuditIssue&gt; activeAuditIssues = new ArrayList&lt;AuditIssue&gt;();\r\n\r\n    \/\/ For each CommonsCollections 3 payload we defined, we try to exploit the issue\r\n    for(int i = 0; i&lt; StaticItems.apacheCommonsCollections3Payloads.length; i++) {\r\n\r\n        \/\/ We create an HTTP request containing our payload in the current insertion point\r\n        HttpRequest commonsCollectionsCheckRequest = auditInsertionPoint.buildHttpRequestWithPayload(\r\n                ByteArray.byteArray(StaticItems.apacheCommonsCollections3Payloads[i]))\r\n                .withService(baseRequestResponse.httpService());\r\n\r\n        \/\/ We record the current time, execute the request and record the time again\r\n        long startTime = System.nanoTime();\r\n        HttpRequestResponse commonsCollectionsCheckRequestResponse = api.http().sendRequest(commonsCollectionsCheckRequest);\r\n        long endTime = System.nanoTime();\r\n\r\n        \/\/ We calculate the internal between when we sent the request and when we received the response (converted in seconds)\r\n        long duration = TimeUnit.SECONDS.convert((endTime - startTime), TimeUnit.NANOSECONDS);\r\n\r\n        \/\/ If the internval is greater than 9 seconds we may have a vulnerable endpoint (our payloads sleep for 10 seconds)\r\n        if (((int) duration) &gt;= 9) {\r\n\r\n            \/\/ In this case, we create an issue object and adds it to the list of issues to be returned\r\n            AuditIssue auditIssue = AuditIssue.auditIssue(StaticItems.apacheCommonsCollections3IssueName,\r\n                    StaticItems.apacheCommonsCollections3IssueDetail,\r\n                    null, \/\/ remediation\r\n                    baseRequestResponse.request().url(),\r\n                    StaticItems.apacheCommonsCollections3IssueSeverity,\r\n                    StaticItems.apacheCommonsCollections3IssueConfidence,\r\n                    null, \/\/ background\r\n                    null, \/\/ remediationBackground\r\n                    StaticItems.apacheCommonsCollections3IssueTypicalSeverity,\r\n                    commonsCollectionsCheckRequestResponse); \/\/Request\/response can be highlighted\r\n\r\n            activeAuditIssues.add(auditIssue);\r\n\r\n        }\r\n\r\n    }\r\n\r\n    \/\/ Return the list of issues\r\n    return AuditResult.auditResult(activeAuditIssues);\r\n\r\n}<\/pre>\n<p>This is an <strong>active<\/strong> scan check, that should apply to<strong>\u00a0each insertion point<\/strong>. So, we should configure the new custom scan check accordingly.<\/p>\n<p>The code of the ported custom scan check is the following:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">\/**\r\n * Check for exploitable Java serialization issues with Apache Commons Collections 3 library (using time).\r\n * \r\n * @author apps3c\r\n**\/\r\n\r\n\/\/ Serialization attack vectors for Apache Commons Collections 3\r\nString[] apacheCommonsCollections3Payloads = new String[] {\"rO0[...]fgA5\",\r\n\"rO0[...]HEAfgAu\",\r\n\"rO0A[...]AHh4eA==\",\r\n\"rO0[...]J4\"};\r\n\r\n\/\/ List of issues to return\r\nList&lt;AuditIssue&gt; activeAuditIssues = new ArrayList&lt;AuditIssue&gt;();\r\n\r\n\/\/ For each CommonsCollections 3 payload we defined, we try to exploit the issue\r\nfor(int i = 0; i&lt; apacheCommonsCollections3Payloads.length; i++) {\r\n\r\n    \/\/ We create an HTTP request containing our payload in the current insertion point\r\n    HttpRequest commonsCollectionsCheckRequest = insertionPoint.buildHttpRequestWithPayload(\r\n        ByteArray.byteArray(apacheCommonsCollections3Payloads[i]))\r\n    .withService(requestResponse.httpService());\r\n\r\n    \/\/ We execute the request\r\n    HttpRequestResponse commonsCollectionsCheckRequestResponse = http.sendRequest(commonsCollectionsCheckRequest);\r\n\r\n    \/\/ We extract timing information\r\n    Optional&lt;TimingData&gt; requestWithPayloadTiming = commonsCollectionsCheckRequestResponse.timingData();\r\n    if(requestWithPayloadTiming.isPresent()) {\r\n\r\n        \/\/ We get the amount of time that passed from request to response\r\n        Duration requestWithPayloadTimingMs  = requestWithPayloadTiming.get().timeBetweenRequestSentAndStartOfResponse();\r\n        long timingThresholdMs = 9000;\r\n\r\n        \/\/ If this time is more or equals to 9 seconds we report the issue (our payload causes a sleep in the backend of 10 seconds)\r\n        if (requestWithPayloadTimingMs.toMillis() &gt;= timingThresholdMs) {\r\n\r\n            String apacheCommonsCollections3IssueName = \"Remote Code Execution through Java Unsafe Deserialization, vulnerable library: Apache Commons Collections 3\";\r\n            String apacheCommonsCollections3IssueDetail = \"The application deserializes untrusted serialized Java objects,\"+\r\n            \" without first checking the type of the received object and run on an unpatched Java environment. This issue can be\"+\r\n            \" exploited by sending malicious objects that, when deserialized,\"+\r\n            \" execute custom Java code. Several objects defined in popular libraries\"+\r\n            \" can be used for the exploitation.\";\r\n\r\n            \/\/ We create an issue object and adds it to the list of issues to be returned\r\n            activeAuditIssues.add(AuditIssue.auditIssue(apacheCommonsCollections3IssueName,\r\n                apacheCommonsCollections3IssueDetail,\r\n                null, \/\/ remediation\r\n                requestResponse.request().url(),\r\n                AuditIssueSeverity.HIGH,\r\n                AuditIssueConfidence.FIRM,\r\n                null, \/\/ background\r\n                null, \/\/ remediationBackground\r\n                AuditIssueSeverity.HIGH,\r\n                commonsCollectionsCheckRequestResponse)); \/\/Request\/response can be highlighted\r\n\r\n        }\r\n\r\n    }\r\n\r\n}\r\n\r\nreturn AuditResult.auditResult(activeAuditIssues);<\/pre>\n<p>In this check we used the <em>requestReponse<\/em>, the <em>http<\/em> and the <em>insertionPoint<\/em> objects made available to us (in this example we did not use the <em>api<\/em> object because we need only the other objects for this particular check; we will use the <em>api<\/em> object in a later example).<\/p>\n<p>As we can see, <strong>the code is almost the same<\/strong>. I only moved payloads and issue detail directly in the check (while in a structured plugin I can move this information outside to make the code more readable) and I made a little change in the way I calculate the timing of the response. In my previous example, I calculated the time &#8220;manually&#8221;, because the code was partially copied from my <a href=\"https:\/\/github.com\/federicodotta\/Java-Deserialization-Scanner\">Java Deserialization Scanner<\/a> plugin, created with the legacy Burp Extender APIs. With the Montoya API we have a better way to calculate the time of the response, thanks to the <a href=\"https:\/\/portswigger.github.io\/burp-extensions-montoya-api\/javadoc\/burp\/api\/montoya\/http\/handler\/TimingData.html\">timing information recorded in the HttpRequestResponse object<\/a>, not present in the legacy APIs. With the new Montoya API we can easily <strong>extract the milliseconds between request sent and start of response received<\/strong> as follows:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">HttpRequestResponse commonsCollectionsCheckRequestResponse = http.sendRequest(commonsCollectionsCheckRequest);\r\nOptional&lt;TimingData&gt; requestWithPayloadTiming = commonsCollectionsCheckRequestResponse.timingData();\r\nif(requestWithPayloadTiming.isPresent()) {\r\n    Duration requestWithPayloadTimingMs  = requestWithPayloadTiming.get().timeBetweenRequestSentAndStartOfResponse();\r\n    long millis = requestWithPayloadTimingMs.toMillis();\r\n}\r\n<\/pre>\n<p>In a similar way, we can port also the <strong>passive check<\/strong> implemented in <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-6\/\">Part 6<\/a> to find serialized objects in HTTP requests. The original code is the following:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">@Override\r\npublic AuditResult passiveAudit(HttpRequestResponse baseRequestResponse) {\r\n\r\n    \/\/ Inizialize an empty list of audit issues that we will eventually populate and return at the end of the function\r\n    List&lt;AuditIssue&gt; passiveAuditIssues = new ArrayList&lt;AuditIssue&gt;();\r\n\r\n    \/\/Extract request bytes\r\n    ByteArray request = baseRequestResponse.request().toByteArray();\r\n\r\n    \/\/ Check for the magic bytes of Java serialized object (not encoded and Base64 encoded)\r\n    int indexOfSerializationMagicBytes = request.indexOf(ByteArray.byteArray(serializationMagicBytes));\r\n    int indexOfBase64MagicBytes = request.indexOf(ByteArray.byteArray(base64MagicBytes));\r\n\r\n    \/\/ Improvement -&gt; Search all matches with a while instead of an if\r\n\r\n    \/\/ If we found the magic bytes we report the passive issue\r\n    if(indexOfSerializationMagicBytes != -1 || indexOfBase64MagicBytes != -1) {\r\n\r\n        \/\/ Calculate the indexes to highligh the start of the serialized object in the request\r\n        int startIndex;\r\n        if(indexOfSerializationMagicBytes != -1)\r\n            startIndex = indexOfSerializationMagicBytes;\r\n        else\r\n            startIndex = indexOfBase64MagicBytes;\r\n        int endIndex = startIndex+4;\r\n\r\n        \/\/ Create the markers to highlight the request in the reported issue\r\n        List&lt;Marker&gt; highlights = new ArrayList&lt;Marker&gt;();\r\n        Marker marker = Marker.marker(startIndex, endIndex);\r\n        highlights.add(marker);\r\n\r\n        \/\/ Report the passive issue\r\n        AuditIssue auditIssue = AuditIssue.auditIssue(StaticItems.passiveSerializationIssueName,\r\n                StaticItems.passiveSerializationIssueDetail,\r\n                null, \/\/ remediation\r\n                baseRequestResponse.request().url(),\r\n                StaticItems.passiveSerializationIssueSeverity,\r\n                StaticItems.passiveSerializationIssueConfidence,\r\n                null, \/\/ background\r\n                null, \/\/ remediationBackground\r\n                StaticItems.passiveSerializationIssueTypicalSeverity,\r\n                baseRequestResponse.withRequestMarkers(highlights));\r\n\r\n        passiveAuditIssues.add(auditIssue);\r\n\r\n\r\n    }\r\n\r\n    \/\/ Return the list of issues\r\n    return AuditResult.auditResult(passiveAuditIssues);\r\n\r\n}<\/pre>\n<p>This is a <strong>passive<\/strong> scan check that should be executed <strong>for each request<\/strong>. So, we should configure the new custom scan check accordingly.<\/p>\n<p>The code of the ported custom scan check is the following:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">\/**\r\n * Passively detect serialized object (raw or base64 encoded in HTTP requests)\r\n * \r\n * @author apps3c\r\n**\/\r\n\r\n\/\/ Serialization magic bytes\r\nbyte[] serializationMagicBytes = {(byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05};\r\nbyte[] base64MagicBytes = {(byte)0x72, (byte)0x4f, (byte)0x30, (byte)0x41};\r\n\r\n\/\/ Extract request bytes\r\nByteArray request = requestResponse.request().toByteArray();\r\n\r\n\/\/ Check for the magic bytes of Java serialized object (not encoded and Base64 encoded)\r\nint indexOfSerializationMagicBytes = request.indexOf(ByteArray.byteArray(serializationMagicBytes));\r\nint indexOfBase64MagicBytes = request.indexOf(ByteArray.byteArray(base64MagicBytes));\r\n\r\n\/\/ If we found the magic bytes we report the passive issue\r\nif(indexOfSerializationMagicBytes != -1 || indexOfBase64MagicBytes != -1) {\r\n\r\n    \/\/ Calculate the indexes to highligh the start of the serialized object in the request\r\n    int startIndex;\r\n    if(indexOfSerializationMagicBytes != -1)\r\n        startIndex = indexOfSerializationMagicBytes;\r\n    else\r\n        startIndex = indexOfBase64MagicBytes;\r\n    int endIndex = startIndex+4;\r\n\r\n    \/\/ Create the markers to highlight the request in the reported issue\r\n    List&lt;Marker&gt; highlights = new ArrayList&lt;Marker&gt;();\r\n    Marker marker = Marker.marker(startIndex, endIndex);\r\n    highlights.add(marker);        \r\n    \r\n    String passiveSerializationIssueName = \"Serialized Java objects detected\";\r\n    String passiveSerializationIssueDetail = \"Serialized Java objects have been detected in the body\"+\r\n        \" or in the parameters of the request. If the server application does \"+\r\n        \" not check on the type of the received objects before\"+\r\n        \" the deserialization phase, it may be vulnerable to the Java Deserialization\"+\r\n        \" Vulnerability.\";\r\n\r\n    \/\/ Report the passive issue\r\n    return AuditResult.auditResult(AuditIssue.auditIssue(\r\n        passiveSerializationIssueName,\r\n        passiveSerializationIssueDetail,\r\n            null, \/\/ remediation\r\n            requestResponse.request().url(),\r\n            AuditIssueSeverity.INFORMATION,\r\n            AuditIssueConfidence.FIRM,\r\n            null, \/\/ background\r\n            null, \/\/ remediationBackground\r\n            AuditIssueSeverity.INFORMATION,\r\n            requestResponse.withRequestMarkers(highlights)));\r\n\r\n} else {\r\n\r\n    return AuditResult.auditResult();\r\n    \r\n}\r\n<\/pre>\n<p>As before, the code is almost identical. I only moved issue details and other static data inside the check, without any important modification in the code. In this example, I used only the <em>httpRequestReponse<\/em> object.<\/p>\n<p>Finally, we will port the <strong>Collaborator<\/strong> active check that we wrote in <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-7\/\">Part 7<\/a>, that detects serialization issues using different serialized objects that, once deserialized, cause the <strong>DNS resolution of arbitrary domains <\/strong>(so, our detection will be based on external interactions rather than on timing).<\/p>\n<p>Let&#8217;s have a look at the original code:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">\/\/ This method create serialized objects with specific Collaborator URLs. Serialized object are binary\r\n\/\/ and we cannot simply replace a placeholder in the payload but it is necessary to fix a couple\r\n\/\/ of lengths in the binary objects, that depend on the legnth of the Collaborator URL.\r\npublic ByteArray createDnsPayload(ByteArray genericPayload, String collaboratorURL) {\r\n\r\n    String hostTokenString = \"XXXXX\";\r\n\r\n    int indexPlaceholderFirstUrlCharacter = genericPayload.indexOf(hostTokenString, true);\r\n    int indexPlaceholderLastUrlCharacter = indexPlaceholderFirstUrlCharacter + hostTokenString.length() -1;\r\n\r\n    int newCollaboratorVectorLength = collaboratorURL.length();\r\n\r\n    ByteArray payloadPortionBeforeUrl = genericPayload.subArray(0, indexPlaceholderFirstUrlCharacter);\r\n    ByteArray payloadPortionAfterUrl = genericPayload.subArray(indexPlaceholderLastUrlCharacter+1, genericPayload.length());\r\n\r\n    payloadPortionBeforeUrl.setByte(payloadPortionBeforeUrl.length()-1, (byte)newCollaboratorVectorLength);\r\n\r\n    ByteArray payloadWithCollaboratorUrl = payloadPortionBeforeUrl.withAppended(ByteArray.byteArray(collaboratorURL));\r\n    payloadWithCollaboratorUrl = payloadWithCollaboratorUrl.withAppended(payloadPortionAfterUrl);\r\n\r\n    \/\/ Adjust one more length in the serialization process when the TemplateImpl object is used for exploitation\r\n    ByteArray patternTemplateImplToSearch = ByteArray.byteArray(new byte[]{(byte)0xf8,(byte)0x06,(byte)0x08,(byte)0x54,(byte)0xe0,(byte)0x02,(byte)0x00,(byte)0x00,(byte)0x78,(byte)0x70,(byte)0x00,(byte)0x00,(byte)0x06});\r\n    int indexOfPatternTemplateImpl = payloadWithCollaboratorUrl.indexOf(patternTemplateImplToSearch,false);\r\n    if(indexOfPatternTemplateImpl != -1)\r\n        payloadWithCollaboratorUrl.setByte(indexOfPatternTemplateImpl+13, (byte)(payloadWithCollaboratorUrl.getByte(indexOfPatternTemplateImpl+13) + (newCollaboratorVectorLength - 5)));\r\n\r\n    return payloadWithCollaboratorUrl;\r\n\r\n}\r\n\r\n@Override\r\npublic AuditResult activeAudit(HttpRequestResponse baseRequestResponse, AuditInsertionPoint auditInsertionPoint) {\r\n\r\n    \/\/ Inizialize an empty list of audit issues that we will eventually populate and return at the end of the function\r\n    List&lt;AuditIssue&gt; activeAuditIssues = new ArrayList&lt;AuditIssue&gt;();\r\n\r\n    \/\/ For each CommonsCollections 3 payload we defined, we try to exploit the issue\r\n    for(int i = 0; i&lt; StaticItems.apacheCommonsCollections3Payloads.length; i++) {\r\n\r\n        \/\/ We generate a Collaborator URL\r\n        String collaboratorUrl = collaboratorClient.generatePayload().toString();\r\n\r\n        \/\/ We update our serialized object inserting the generated Collaborator URL\r\n        ByteArray payloadWithCollaboratorUrl = utilities.base64Utils().encode(\r\n                createDnsPayload(\r\n                        utilities.base64Utils().decode(StaticItems.apacheCommonsCollections3Payloads[i]),\r\n                        collaboratorUrl));\r\n\r\n        \/\/ We create an HTTP request containing our payload in the current insertion point\r\n        HttpRequest commonsCollectionsCheckRequest = auditInsertionPoint.buildHttpRequestWithPayload(\r\n                payloadWithCollaboratorUrl).withService(baseRequestResponse.httpService());\r\n\r\n        \/\/ We send the request containing the payload\r\n        HttpRequestResponse commonsCollectionsCheckRequestResponse = api.http().sendRequest(commonsCollectionsCheckRequest);\r\n\r\n        \/\/ We retrieve the interactions received by the Collaborator related to our specific Collaborator URL\r\n        List&lt;Interaction&gt; interactionList = collaboratorClient.getInteractions(InteractionFilter.interactionPayloadFilter(collaboratorUrl));\r\n\r\n        if(interactionList.size() &gt; 0) {\r\n\r\n            \/\/ If we have interactions, we create an issue object and adds it to the list of issues to be returned\r\n            AuditIssue auditIssue = AuditIssue.auditIssue(StaticItems.apacheCommonsCollections3IssueName,\r\n                    StaticItems.apacheCommonsCollections3IssueDetail,\r\n                    null, \/\/ remediation\r\n                    baseRequestResponse.request().url(),\r\n                    StaticItems.apacheCommonsCollections3IssueSeverity,\r\n                    StaticItems.apacheCommonsCollections3IssueConfidence,\r\n                    null, \/\/ background\r\n                    null, \/\/ remediationBackground\r\n                    StaticItems.apacheCommonsCollections3IssueTypicalSeverity,\r\n                    commonsCollectionsCheckRequestResponse); \/\/Request\/response can be highlighted\r\n\r\n            activeAuditIssues.add(auditIssue);\r\n\r\n        }\r\n\r\n    }\r\n\r\n    \/\/ Return the list of issues\r\n    return AuditResult.auditResult(activeAuditIssues);\r\n\r\n}<\/pre>\n<p>This is an <strong>active<\/strong> scan check, that should apply to<strong> each insertion point<\/strong>. So, we should configure the new custom scan check accordingly.<\/p>\n<p>The code of the ported custom scan check is the following:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">\/**\r\n * Check for exploitable Java serialization issues with Apache Commons Collections 3 library (using Collaborator).\r\n * \r\n * @author apps3c\r\n**\/\r\n\r\n\/\/ Serialization attack vectors for Apache Commons Collections 3\r\nString[] apacheCommonsCollections3Payloads = new String[] {\"rO0[...]ADc=\",\r\n    \"rO0[...]4ALg==\",\r\n    \"rO0[...]AB4eA==\",\r\n    \"rO0[...]AAAeHh4\",\r\n    \"rO0[...]AAng=\"};\r\n\r\n\/\/ List of issues to return\r\nList&lt;AuditIssue&gt; activeAuditIssues = new ArrayList&lt;AuditIssue&gt;();\r\n\r\n\/\/ Get a reference to the collaborator client\r\nCollaboratorClient collaboratorClient = api.collaborator().createClient();\r\n\r\n\/\/ Get a refence to Burp Suite utilities (we will use them to Base64 encode\/decode)\r\nUtilities utilities = api.utilities();\r\n\r\n\/\/ For each CommonsCollections 3 payload we defined, we try to exploit the issue\r\nfor(int i = 0; i&lt; apacheCommonsCollections3Payloads.length; i++) {\r\n\r\n    \/\/ We generate a Collaborator URL\r\n    String collaboratorURL = collaboratorClient.generatePayload().toString();\r\n\r\n    ByteArray payloadWithCollaboratorUrl;\r\n\r\n    \/\/ *************** PAYLOAD CREATION ****************************\r\n    \/\/ These lines create serialized objects with specific Collaborator URLs. Serialized object are binary\r\n    \/\/ and we cannot simply replace a placeholder in the payload but it is necessary to fix a couple\r\n    \/\/ of lengths in the binary objects, that depend on the legnth of the Collaborator URL.\r\n\r\n    ByteArray genericPayload = utilities.base64Utils().decode(apacheCommonsCollections3Payloads[i]);\r\n    String hostTokenString = \"XXXXX\";\r\n\r\n    int indexPlaceholderFirstUrlCharacter = genericPayload.indexOf(hostTokenString, true);\r\n    int indexPlaceholderLastUrlCharacter = indexPlaceholderFirstUrlCharacter + hostTokenString.length() -1;\r\n\r\n    int newCollaboratorVectorLength = collaboratorURL.length();\r\n\r\n    ByteArray payloadPortionBeforeUrl = genericPayload.subArray(0, indexPlaceholderFirstUrlCharacter);\r\n    ByteArray payloadPortionAfterUrl = genericPayload.subArray(indexPlaceholderLastUrlCharacter+1, genericPayload.length());\r\n\r\n    payloadPortionBeforeUrl.setByte(payloadPortionBeforeUrl.length()-1, (byte)newCollaboratorVectorLength);\r\n\r\n    payloadWithCollaboratorUrl = payloadPortionBeforeUrl.withAppended(ByteArray.byteArray(collaboratorURL));\r\n    payloadWithCollaboratorUrl = payloadWithCollaboratorUrl.withAppended(payloadPortionAfterUrl);\r\n\r\n    \/\/ Adjust one more length in the serialization process when the TemplateImpl object is used for exploitation\r\n    ByteArray patternTemplateImplToSearch = ByteArray.byteArray(new byte[]{(byte)0xf8,(byte)0x06,(byte)0x08,(byte)0x54,(byte)0xe0,(byte)0x02,(byte)0x00,(byte)0x00,(byte)0x78,(byte)0x70,(byte)0x00,(byte)0x00,(byte)0x06});\r\n    int indexOfPatternTemplateImpl = payloadWithCollaboratorUrl.indexOf(patternTemplateImplToSearch,false);\r\n    if(indexOfPatternTemplateImpl != -1)\r\n        payloadWithCollaboratorUrl.setByte(indexOfPatternTemplateImpl+13, (byte)(payloadWithCollaboratorUrl.getByte(indexOfPatternTemplateImpl+13) + (newCollaboratorVectorLength - 5)));\r\n\r\n    payloadWithCollaboratorUrl = utilities.base64Utils().encode(payloadWithCollaboratorUrl);\r\n\r\n    \/\/ *************** END PAYLOAD CREATION ************************\r\n\r\n    \/\/ We create an HTTP request containing our payload in the current insertion point\r\n    HttpRequest commonsCollectionsCheckRequest = insertionPoint.buildHttpRequestWithPayload(\r\n        payloadWithCollaboratorUrl).withService(requestResponse.httpService());\r\n\r\n    \/\/ We execute the request\r\n    HttpRequestResponse commonsCollectionsCheckRequestResponse = http.sendRequest(commonsCollectionsCheckRequest);\r\n\r\n    \/\/ We retrieve the interactions received by the Collaborator related to our specific Collaborator URL\r\n    List&lt;Interaction&gt; interactionList = collaboratorClient.getInteractions(InteractionFilter.interactionPayloadFilter(collaboratorURL));\r\n\r\n    \/\/ If we have some interactions we report the issue\r\n    if(interactionList.size() &gt; 0) {\r\n\r\n        String apacheCommonsCollections3IssueName = \"Remote Code Execution through Java Unsafe Deserialization, vulnerable library: Apache Commons Collections 3\";\r\n        String apacheCommonsCollections3IssueDetail = \"The application deserializes untrusted serialized Java objects,\"+\r\n        \" without first checking the type of the received object and run on an unpatched Java environment. This issue can be\"+\r\n        \" exploited by sending malicious objects that, when deserialized,\"+\r\n        \" execute custom Java code. Several objects defined in popular libraries\"+\r\n        \" can be used for the exploitation.\";\r\n\r\n        \/\/ We create an issue object and adds it to the list of issues to be returned\r\n        activeAuditIssues.add(AuditIssue.auditIssue(apacheCommonsCollections3IssueName,\r\n            apacheCommonsCollections3IssueDetail,\r\n            null, \/\/ remediation\r\n            requestResponse.request().url(),\r\n            AuditIssueSeverity.HIGH,\r\n            AuditIssueConfidence.FIRM,\r\n            null, \/\/ background\r\n            null, \/\/ remediationBackground\r\n            AuditIssueSeverity.HIGH,\r\n            commonsCollectionsCheckRequestResponse)); \/\/Request\/response can be highlighted\r\n\r\n    }\r\n\r\n}\r\n\r\nreturn AuditResult.auditResult(activeAuditIssues);<\/pre>\n<p>As in the previous examples, almost nothing changes. We moved the auxiliary method we used to create the payload inside our check. This method is necessary to create the DNS payload, in which we need to put a variable-length Collaborator URL and consequently we need to fix a couple of binary lengths to avoid breaking the serialized Java object format.<\/p>\n<p>In this example, in addition to\u00a0<em>httpRequestResponse<\/em>, <em>insertionPoint<\/em> and <em>http<\/em>,\u00a0we also used the available <em>api<\/em> object to get a reference to the Collaborator client.<\/p>\n<p>Now, let&#8217;s try our 3 new custom checks on our target like we did in <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-6\/\">Part 6<\/a> and <a href=\"https:\/\/hnsecurity.it\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-7\/\">Part 7<\/a>:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-161192 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-3.png\" alt=\"\" width=\"1345\" height=\"589\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-3.png 1345w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-3-300x131.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-3-1024x448.png 1024w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-3-768x336.png 768w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-3-350x153.png 350w\" sizes=\"(max-width: 1345px) 100vw, 1345px\" \/><\/p>\n<p>As usual, we can <strong>define a custom scan profile that enables only the check we are developing<\/strong>, in order to speed up the scan. In this example, we want to use only the custom scan checks, so we can leave them enabled and disable all built-in checks and all the extension checks (this is another cool feature that is relatively new; in the past we could not disable the extension checks in scan profiles).<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-161194 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-5.png\" alt=\"\" width=\"1160\" height=\"478\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-5.png 1160w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-5-300x124.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-5-1024x422.png 1024w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-5-768x316.png 768w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-5-350x144.png 350w\" sizes=\"(max-width: 1160px) 100vw, 1160px\" \/><\/p>\n<p>After a while, we have our result!<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-161195 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-6.png\" alt=\"\" width=\"1342\" height=\"406\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-6.png 1342w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-6-300x91.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-6-1024x310.png 1024w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-6-768x232.png 768w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/10\/Pasted-image-6-350x106.png 350w\" sizes=\"(max-width: 1342px) 100vw, 1342px\" \/><\/p>\n<p>And for custom scan checks, that&#8217;s a wrap.<\/p>\n<p>As always, the complete code can be downloaded from <a href=\"https:\/\/github.com\/federicodotta\/Burp-Suite-Extender-Montoya-Course\">my GitHub repository.<\/a> Custom scan scripts are present both with Java and Bambda extension. The Java ones should be pasted into the editor, while Bambda scripts can be imported via the &#8220;Import&#8221; functionality.<\/p>\n<p>Official documentation and examples can be found at the following links:<\/p>\n<ul>\n<li><a href=\"https:\/\/portswigger.net\/burp\/documentation\/desktop\/extend-burp\/custom-scan-checks\/creating\/writing-guide\">Custom scan checks writing guide<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/PortSwigger\/bambdas\/tree\/main\/CustomScanChecks\">Custom scan checks official examples<\/a><\/li>\n<li><a href=\"https:\/\/portswigger.github.io\/burp-extensions-montoya-api\/javadoc\/burp\/api\/montoya\/MontoyaApi.html\">Montoya API docs<\/a><\/li>\n<\/ul>\n<p>Cheers!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Setting up the environment + Hello World Inspecting and tampering HTTP requests and responses Inspecting and tampering WebSocket messages Creating [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":159898,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[88,91],"tags":[115,185,186,187,188,189,104],"class_list":["post-161180","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tools","category-articles","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.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>HN Security - Extending Burp Suite for fun and profit \u2013 The Montoya way \u2013 Part 9 - Articles<\/title>\n<meta name=\"description\" content=\"A comprehensive guide on extending Burp Scanner with custom scan checks.\" \/>\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-9\/\" \/>\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 \u2013 The Montoya way \u2013 Part 9 - Articles\" \/>\n<meta property=\"og:description\" content=\"A comprehensive guide on extending Burp Scanner with custom scan checks.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\/\" \/>\n<meta property=\"og:site_name\" content=\"HN Security\" \/>\n<meta property=\"article:published_time\" content=\"2025-12-10T09:02:32+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=\"9 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-9\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\\\/\"},\"author\":{\"name\":\"Federico Dotta\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#\\\/schema\\\/person\\\/e0e6046bd2bc829f7d945ad361bce702\"},\"headline\":\"Extending Burp Suite for fun and profit \u2013 The Montoya way \u2013 Part 9\",\"datePublished\":\"2025-12-10T09:02:32+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\\\/\"},\"wordCount\":1721,\"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-9\\\/#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\":[\"Tools\",\"Articles\"],\"inLanguage\":\"it-IT\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\\\/\",\"url\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\\\/\",\"name\":\"HN Security - Extending Burp Suite for fun and profit \u2013 The Montoya way \u2013 Part 9 - Articles\",\"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-9\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2025\\\/09\\\/BURP.jpg\",\"datePublished\":\"2025-12-10T09:02:32+00:00\",\"description\":\"A comprehensive guide on extending Burp Scanner with custom scan checks.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\\\/#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\\\/#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-9\\\/#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 \u2013 The Montoya way \u2013 Part 9\"}]},{\"@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 \u2013 The Montoya way \u2013 Part 9 - Articles","description":"A comprehensive guide on extending Burp Scanner with custom scan checks.","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-9\/","og_locale":"it_IT","og_type":"article","og_title":"HN Security - Extending Burp Suite for fun and profit \u2013 The Montoya way \u2013 Part 9 - Articles","og_description":"A comprehensive guide on extending Burp Scanner with custom scan checks.","og_url":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\/","og_site_name":"HN Security","article_published_time":"2025-12-10T09:02:32+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":"9 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-9\/#article","isPartOf":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\/"},"author":{"name":"Federico Dotta","@id":"https:\/\/hnsecurity.it\/it\/#\/schema\/person\/e0e6046bd2bc829f7d945ad361bce702"},"headline":"Extending Burp Suite for fun and profit \u2013 The Montoya way \u2013 Part 9","datePublished":"2025-12-10T09:02:32+00:00","mainEntityOfPage":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\/"},"wordCount":1721,"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-9\/#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":["Tools","Articles"],"inLanguage":"it-IT"},{"@type":"WebPage","@id":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\/","url":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\/","name":"HN Security - Extending Burp Suite for fun and profit \u2013 The Montoya way \u2013 Part 9 - Articles","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-9\/#primaryimage"},"image":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\/#primaryimage"},"thumbnailUrl":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/BURP.jpg","datePublished":"2025-12-10T09:02:32+00:00","description":"A comprehensive guide on extending Burp Scanner with custom scan checks.","breadcrumb":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\/#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\/"]}]},{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/hnsecurity.it\/it\/blog\/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-9\/#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-9\/#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 \u2013 The Montoya way \u2013 Part 9"}]},{"@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\/161180","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=161180"}],"version-history":[{"count":19,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts\/161180\/revisions"}],"predecessor-version":[{"id":161260,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts\/161180\/revisions\/161260"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/media\/159898"}],"wp:attachment":[{"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/media?parent=161180"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/categories?post=161180"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/tags?post=161180"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}