├── .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
--------------------------------------------------------------------------------