├── .github └── workflows │ └── semgrep.yml ├── Asset_History.py ├── LICENSE ├── README.md └── Screenshots ├── Add Domain to Scope.jpg ├── Add Extension.jpg └── Asset History.jpg /.github/workflows/semgrep.yml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_dispatch: {} 3 | pull_request: {} 4 | push: 5 | branches: 6 | - main 7 | - master 8 | paths: 9 | - .github/workflows/semgrep.yml 10 | schedule: 11 | # random HH:MM to avoid a load spike on GitHub Actions at 00:00 12 | - cron: 11 20 * * * 13 | name: Semgrep 14 | jobs: 15 | semgrep: 16 | name: semgrep/ci 17 | runs-on: ubuntu-20.04 18 | env: 19 | SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} 20 | container: 21 | image: returntocorp/semgrep 22 | steps: 23 | - uses: actions/checkout@v4 24 | - run: semgrep ci 25 | -------------------------------------------------------------------------------- /Asset_History.py: -------------------------------------------------------------------------------- 1 | # Asset Discover: Burp Suite Extension to find related assets (domain, IP, S3 Buckets etc.) from a webpage. #AssetDiscovery 2 | # By: RedHunt Labs (www.redhuntlabs.com) 3 | # Twitter: https://twitter.com/redhuntlabs 4 | 5 | # Code Credits: 6 | # OpenSecurityResearch CustomPassiveScanner: https://github.com/OpenSecurityResearch/CustomPassiveScanner 7 | # PortSwigger example-scanner-checks: https://github.com/PortSwigger/example-scanner-checks 8 | 9 | from burp import IBurpExtender 10 | from burp import IScannerCheck 11 | from burp import IScanIssue 12 | from array import array 13 | import re 14 | import urllib2 15 | import json 16 | # Implement BurpExtender to inherit from multiple base classes 17 | # IBurpExtender is the base class required for all extensions 18 | # IScannerCheck lets us register our extension with Burp as a custom scanner check 19 | class BurpExtender(IBurpExtender, IScannerCheck): 20 | 21 | scopedomains = [] 22 | 23 | # The only method of the IBurpExtender interface. 24 | # This method is invoked when the extension is loaded and registers 25 | # an instance of the IBurpExtenderCallbacks interface 26 | def registerExtenderCallbacks(self, callbacks): 27 | # Put the callbacks parameter into a class variable so we have class-level scope 28 | self._callbacks = callbacks 29 | 30 | # Set the name of our extension, which will appear in the Extender tool when loaded 31 | self._callbacks.setExtensionName("Asset History") 32 | 33 | # Register our extension as a custom scanner check, so Burp will use this extension 34 | # to perform active or passive scanning and report on scan issues returned 35 | self._callbacks.registerScannerCheck(self) 36 | 37 | return 38 | 39 | # This method is called when multiple issues are reported for the same URL 40 | # In this case we are checking if the issue detail is different, as the 41 | # issues from our scans include affected parameters/values in the detail, 42 | # which we will want to report as unique issue instances 43 | def consolidateDuplicateIssues(self, existingIssue, newIssue): 44 | if (existingIssue.getIssueDetail() == newIssue.getIssueDetail()): 45 | return -1 46 | else: 47 | return 0 48 | 49 | # Implement the doPassiveScan method of IScannerCheck interface 50 | # Burp Scanner invokes this method for each base request/response that is passively scanned. 51 | def doPassiveScan(self, baseRequestResponse): 52 | # Local variables used to store a list of ScanIssue objects 53 | scan_issues = [] 54 | tmp_issues = [] 55 | 56 | 57 | # Call the findRegEx method of our CustomScans object to check 58 | # the response for anything matching a specified regular expression 59 | # This one matches an IP 60 | issuename = "Asset History: URL" 61 | issuelevel = "Information" 62 | issuedetail = "Historic URLs Discovered: $asset$" 63 | 64 | # Get an instance of IHelpers, which has lots of useful methods, as a class 65 | # variable, so we have class-level scope to all the helper methods 66 | self._helpers = self._callbacks.getHelpers() 67 | 68 | self._requestResponse = baseRequestResponse 69 | 70 | # Finally, per the interface contract, doPassiveScan needs to return a 71 | # list of scan issues, if any, and None otherwise 72 | if self._callbacks.isInScope(self._helpers.analyzeRequest(self._requestResponse).getUrl()): 73 | url = self._helpers.analyzeRequest(self._requestResponse).getUrl() 74 | domain = str(url).split("//")[-1].split(":")[0].split('?')[0] 75 | global scopedomains 76 | scopedomains = self.scopedomains 77 | print scopedomains 78 | if domain not in scopedomains: 79 | print "Target Domain: "+domain 80 | url = "http://web.archive.org/cdx/search/cdx?url=/"+domain+"/*&output=json" 81 | print url 82 | try: 83 | scopedomains.append(domain) 84 | webarchive = urllib2.urlopen(url) 85 | webarchivejson = json.load(webarchive) 86 | print webarchivejson 87 | urls = [] 88 | for wa in webarchivejson: 89 | urls.append(wa[2]) 90 | if urls: 91 | urls.pop(0) 92 | uniqueurl = '
  • '+'
  • \r\n
  • '.join(set(urls)) 93 | print "URLs Discovered:" 94 | for url in set(urls): 95 | print url 96 | # Create a ScanIssue object and append it to our list of issues, marking 97 | # the matched value in the response. 98 | if uniqueurl: 99 | scan_issues.append(ScanIssue(self._requestResponse.getHttpService(), 100 | self._helpers.analyzeRequest(self._requestResponse).getUrl(), 101 | [self._callbacks.applyMarkers(self._requestResponse, None, None)], 102 | issuename, issuelevel, issuedetail.replace("$asset$", uniqueurl))) 103 | except: 104 | print("Exception Occured") 105 | scopedomains.pop() 106 | 107 | 108 | 109 | 110 | if len(scan_issues) > 0: 111 | return scan_issues 112 | else: 113 | return None 114 | 115 | 116 | 117 | # Implementation of the IScanIssue interface with simple constructor and getter methods 118 | class ScanIssue(IScanIssue): 119 | def __init__(self, httpservice, url, requestresponsearray, name, severity, detailmsg): 120 | self._url = url 121 | self._httpservice = httpservice 122 | self._requestresponsearray = requestresponsearray 123 | self._name = name 124 | self._severity = severity 125 | self._detailmsg = detailmsg 126 | 127 | def getUrl(self): 128 | return self._url 129 | 130 | def getHttpMessages(self): 131 | return self._requestresponsearray 132 | 133 | def getHttpService(self): 134 | return self._httpservice 135 | 136 | def getRemediationDetail(self): 137 | return None 138 | 139 | def getIssueDetail(self): 140 | return self._detailmsg 141 | 142 | def getIssueBackground(self): 143 | return None 144 | 145 | def getRemediationBackground(self): 146 | return None 147 | 148 | def getIssueType(self): 149 | return 0 150 | 151 | def getIssueName(self): 152 | return self._name 153 | 154 | def getSeverity(self): 155 | return self._severity 156 | 157 | def getConfidence(self): 158 | return "Tentative" 159 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 RedHunt Labs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BurpSuite Extension - Asset History[](https://redhuntlabs.com/) 2 | Burp Suite extension to identify the historic URLs of the domains in scope from WayBackMachine. Refer to our blog [Asset History using Burp Suite](https://redhuntlabs.com/blog/asset-history-burp-extension.html) for more details. 3 | 4 | **[`To know more about our Attack Surface Management platform, check out NVADR.`](https://redhuntlabs.com/nvadr)** 5 | 6 | # Description 7 | The extension acts as a passive scanner which extracts the domain(s) that are in scope, identifies their historic URLs from [WayBackMachine](http://web.archive.org/) and lists them under the issues section. The URLs can be easily copied from their and tested further for security issues. 8 | 9 | # Setup 10 | - Setup the python environment by providing the [jython.jar](https://www.jython.org/downloads.html) file in the 'Options' tab under 'Extender' in Burp Suite. 11 | - Download the [extension](https://github.com/redhuntlabs/BurpSuite-Asset_History/archive/master.zip). 12 | - In the 'Extensions' tab under 'Extender', select 'Add'. 13 | - Change the extension type to 'Python'. 14 | - Provide the path of the file ‘Asset_History.py’ and click on 'Next'. 15 | - Add the target domain/URL in Scope. 16 | 17 | 18 | 19 | # Usage 20 | - Add a URL to the 'Scope' under the 'Target' tab. The extension will identify historic URLs for it. 21 | 22 | 23 | 24 | # Requirements 25 | - [Jython 2.7.0](https://www.jython.org/download) 26 | - [Burp Suite Pro v2020.6](https://portswigger.net/burp) [Not tested on older version, however it should work fine] 27 | 28 | # Code Credits 29 | A large portion of the base code has been taken from the following sources: 30 | - [OpenSecurityResearch CustomPassiveScanner](https://github.com/OpenSecurityResearch/CustomPassiveScanner) 31 | - [PortSwigger example-scanner-checks](https://github.com/PortSwigger/example-scanner-checks) 32 | - [BurpSuite Extension - Asset Discover](https://github.com/redhuntlabs/BurpSuite-Asset_Discover) 33 | 34 | # To-Do: 35 | - [ ] Add AlienVault Open Threat Exchange 36 | - [ ] Add Domain History 37 | - [ ] Add IP History 38 | 39 | # License 40 | The project is available under MIT license, see [LICENSE](https://github.com/redhuntlabs/BurpSuite-Asset_History/blob/master/LICENSE) file. 41 | -------------------------------------------------------------------------------- /Screenshots/Add Domain to Scope.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhuntlabs/BurpSuite-Asset_History/d2f701d7d2457fee051603daa89468fdb21d3242/Screenshots/Add Domain to Scope.jpg -------------------------------------------------------------------------------- /Screenshots/Add Extension.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhuntlabs/BurpSuite-Asset_History/d2f701d7d2457fee051603daa89468fdb21d3242/Screenshots/Add Extension.jpg -------------------------------------------------------------------------------- /Screenshots/Asset History.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhuntlabs/BurpSuite-Asset_History/d2f701d7d2457fee051603daa89468fdb21d3242/Screenshots/Asset History.jpg --------------------------------------------------------------------------------