├── Screenshot
├── log.png
├── install.png
└── result.png
├── README.md
└── Xkeys.py
/Screenshot/log.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vsec7/BurpSuite-Xkeys/master/Screenshot/log.png
--------------------------------------------------------------------------------
/Screenshot/install.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vsec7/BurpSuite-Xkeys/master/Screenshot/install.png
--------------------------------------------------------------------------------
/Screenshot/result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vsec7/BurpSuite-Xkeys/master/Screenshot/result.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Xkeys (BurpSuite Extension)
2 |
3 |
4 | ## Description
5 | A Burp Suite Extension to extract interesting strings (key, secret, token, or etc.) from a webpage. and lists them as information issues.
6 |
7 | Type : Passive Scanner
8 |
9 | # Setup
10 |
11 |
12 | - Setup the python environment by providing the Jython.jar file in the 'Options' tab under 'Extender' in Burp Suite.
13 | - Download the BurpSuite-Xkeys.zip.
14 | - In the 'Extensions' tab under 'Extender', select 'Add'.
15 | - Change the extension type to 'Python'.
16 | - Provide the path of the file "Xkeys.py" and click on 'Next'.
17 |
18 | # Usage
19 | - The extension will start identifying assets through passive scan.
20 |
21 | ## Result
22 | - The extension will show on issues box and on output extender
23 |
24 |
25 | ## Possible Value Extraction
26 | ```
27 | {keyword}=
28 | {keyword}=
29 | {keyword} =
30 | {keyword} =
31 | {keyword}'=''
32 | {keyword}'= ''
33 | {keyword}' =''
34 | {keyword}' = ''
35 | {keyword}"=""
36 | {keyword}"= ""
37 | {keyword}" =""
38 | {keyword}" = ""
39 | {keyword}":""
40 | {keyword}": ""
41 | {keyword}" :""
42 | {keyword}" : ""
43 | {keyword}=&
44 | ```
45 |
46 | ## Requirements
47 | - [Jython 2.7.0](https://www.jython.org/download.html)
48 | - [Burp Suite Pro](https://portswigger.net/burp)
49 |
50 | ## Code Credits:
51 | ```
52 | # PortSwigger example-scanner-checks: https://github.com/PortSwigger/example-scanner-checks
53 | # RedHuntLabs BurpSuite-Asset_Discover: https://github.com/redhuntlabs/BurpSuite-Asset_Discover
54 | ```
55 |
56 | - Sec7or Team
57 | - Surabaya Hacker Link
58 |
--------------------------------------------------------------------------------
/Xkeys.py:
--------------------------------------------------------------------------------
1 | # Xkeys - Burp Suite Extension to extract interesting strings (key, secret, token, or etc.) from a webpage.
2 | # Type : Passive Scanner
3 | # By: Verry Darmawan (github.com/vsec7)
4 | # Twitter: https://twitter.com/verry__d
5 |
6 | # Code Credits:
7 | # PortSwigger example-scanner-checks: https://github.com/PortSwigger/example-scanner-checks
8 | # Redhunlabs Asset_Discover: https://github.com/redhuntlabs/BurpSuite-Asset_Discover
9 |
10 | from burp import IBurpExtender
11 | from burp import IScannerCheck
12 | from burp import IScanIssue
13 | from array import array
14 | import re
15 |
16 | class BurpExtender(IBurpExtender, IScannerCheck):
17 |
18 | def registerExtenderCallbacks(self, callbacks):
19 | self._callbacks = callbacks
20 | self._callbacks.setExtensionName("Xkeys")
21 | self._callbacks.registerScannerCheck(self)
22 | print("Thank you for installing xkeys")
23 | print("Passive scanner to extract interesting strings (key, secret, token, or etc.)")
24 | print("By : Verry Darmawan (github.com/vsec7)")
25 | print("Twitter : https://twitter.com/verry__d\n")
26 | return
27 |
28 | def consolidateDuplicateIssues(self, existingIssue, newIssue):
29 | if (existingIssue.getIssueDetail() == newIssue.getIssueDetail()):
30 | return -1
31 | else:
32 | return 0
33 |
34 | def doPassiveScan(self, baseRequestResponse):
35 | scan_issues = []
36 | tmp_issues = []
37 |
38 | self._CustomScans = CustomScans(baseRequestResponse, self._callbacks)
39 |
40 | # Add your keywords for pattern
41 | keywords = [
42 | "access_key",
43 | "access_token",
44 | "accessKey",
45 | "accessToken",
46 | "account_sid",
47 | "accountsid",
48 | "admin_pass",
49 | "admin_user",
50 | "api_key",
51 | "api_secret",
52 | "apikey",
53 | "app_key",
54 | "app_secret",
55 | "app_url",
56 | "application_id",
57 | "aws_secret_token",
58 | "authsecret",
59 | "aws_access",
60 | "aws_access_key_id",
61 | "aws_bucket",
62 | "aws_config",
63 | "aws_default_region",
64 | "aws_key",
65 | "aws_secret",
66 | "aws_secret_access_key",
67 | "aws_secret_key",
68 | "aws_token",
69 | "bucket_password",
70 | "client_secret",
71 | "cloudinary_api_key",
72 | "cloudinary_api_secret",
73 | "cloudinary_name",
74 | "connectionstring",
75 | "consumer_secret",
76 | "database_dialect",
77 | "database_host",
78 | "database_logging",
79 | "database_password",
80 | "database_schema",
81 | "database_schema_test",
82 | "database_url",
83 | "database_username",
84 | "db_connection",
85 | "db_database",
86 | "db_dialect",
87 | "db_host",
88 | "db_password",
89 | "db_port",
90 | "db_server",
91 | "db_username",
92 | "dbpasswd",
93 | "dbpassword",
94 | "dbuser",
95 | "django_password",
96 | "elastica_host",
97 | "elastica_port",
98 | "elastica_prefix",
99 | "email_host_password",
100 | "facebook_app_secret",
101 | "facebook_secret",
102 | "fb_app_secret",
103 | "fb_id",
104 | "fb_secret",
105 | "gatsby_wordpress_base_url",
106 | "gatsby_wordpress_client_id",
107 | "gatsby_wordpress_client_secret",
108 | "gatsby_wordpress_password",
109 | "gatsby_wordpress_protocol",
110 | "gatsby_wordpress_user",
111 | "github_id",
112 | "github_secret",
113 | "google_id",
114 | "google_oauth",
115 | "google_oauth_client_id",
116 | "google_oauth_client_secret",
117 | "google_oauth_secret",
118 | "google_secret",
119 | "google_server_key",
120 | "gsecr",
121 | "heroku_api_key",
122 | "heroku_key",
123 | "heroku_oauth",
124 | "heroku_oauth_secret",
125 | "heroku_oauth_token",
126 | "heroku_secret",
127 | "heroku_secret_token",
128 | "htaccess_pass",
129 | "htaccess_user",
130 | "incident_bot_name",
131 | "incident_channel_name",
132 | "jwt_passphrase",
133 | "jwt_password",
134 | "jwt_public_key",
135 | "jwt_secret",
136 | "jwt_secret_key",
137 | "jwt_secret_token",
138 | "jwt_token",
139 | "jwt_user",
140 | "keyPassword",
141 | "mail_driver",
142 | "mail_encryption",
143 | "mail_from_address",
144 | "mail_from_name",
145 | "mail_host",
146 | "mail_password",
147 | "mail_port",
148 | "mail_username",
149 | "mailgun_key",
150 | "mailgun_secret",
151 | "maps_api_key",
152 | "mix_pusher_app_cluster",
153 | "mix_pusher_app_key",
154 | "mysql_password",
155 | "oauth_discord_id",
156 | "oauth_discord_secret",
157 | "oauth_key",
158 | "oauth_token",
159 | "oauth2_secret",
160 | "password",
161 | "paypal_identity_token",
162 | "paypal_sandbox",
163 | "paypal_secret",
164 | "paypal_token",
165 | "playbooks_url",
166 | "postgres_password",
167 | "private_key",
168 | "pusher_app_cluster",
169 | "pusher_app_id",
170 | "pusher_app_key",
171 | "pusher_app_secret",
172 | "queue_driver",
173 | "redis_host",
174 | "redis_password",
175 | "redis_port",
176 | "response_auth_jwt_secret",
177 | "response_data_secret",
178 | "response_data_url",
179 | "root_password",
180 | "sa_password",
181 | "secret",
182 | "secret_access_key",
183 | "secret_bearer",
184 | "secret_key",
185 | "secret_token",
186 | "secretKey",
187 | "security_credentials",
188 | "send_keys",
189 | "sentry_dsn",
190 | "session_driver",
191 | "session_lifetime",
192 | "sf_username",
193 | "sid twilio",
194 | "sid_token",
195 | "sid_twilio",
196 | "slack_channel",
197 | "slack_incoming_webhook",
198 | "slack_key",
199 | "slack_outgoing_token",
200 | "slack_secret",
201 | "slack_signing_secret",
202 | "slack_token",
203 | "slack_url",
204 | "slack_webhook",
205 | "slack_webhook_url",
206 | "square_access_token",
207 | "square_apikey",
208 | "square_app",
209 | "square_app_id",
210 | "square_appid",
211 | "square_secret",
212 | "square_token",
213 | "squareSecret",
214 | "squareToken",
215 | "ssh2_auth_password",
216 | "sshkey",
217 | "storePassword",
218 | "strip_key",
219 | "strip_secret",
220 | "strip_secret_token",
221 | "strip_token",
222 | "stripe_key",
223 | "stripe_secret",
224 | "stripe_secret_token",
225 | "stripe_token",
226 | "stripSecret",
227 | "stripToken",
228 | "stripe_publishable_key",
229 | "token_twilio",
230 | "trusted_hosts",
231 | "twi_auth",
232 | "twi_sid",
233 | "twilio_account_id",
234 | "twilio_account_secret",
235 | "twilio_account_sid",
236 | "twilio_accountsid",
237 | "twilio_api",
238 | "twilio_api_auth",
239 | "twilio_api_key",
240 | "twilio_api_secret",
241 | "twilio_api_sid",
242 | "twilio_api_token",
243 | "twilio_auth",
244 | "twilio_auth_token",
245 | "twilio_secret",
246 | "twilio_secret_token",
247 | "twilio_sid",
248 | "twilio_token",
249 | "twilioapiauth",
250 | "twilioapisecret",
251 | "twilioapisid",
252 | "twilioapitoken",
253 | "TwilioAuthKey",
254 | "TwilioAuthSid",
255 | "twilioauthtoken",
256 | "TwilioKey",
257 | "twiliosecret",
258 | "TwilioSID",
259 | "twiliotoken",
260 | "twitter_api_secret",
261 | "twitter_consumer_key",
262 | "twitter_consumer_secret",
263 | "twitter_key",
264 | "twitter_secret",
265 | "twitter_token",
266 | "twitterKey",
267 | "twitterSecret",
268 | "wordpress_password",
269 | "zen_key",
270 | "zen_tkn",
271 | "zen_token",
272 | "zendesk_api_token",
273 | "zendesk_key",
274 | "zendesk_token",
275 | "zendesk_url",
276 | "zendesk_username",
277 | "zendesk_password"
278 | ]
279 |
280 | for key in keywords:
281 | regex = "(?i)"+key+"['\"]?\s?(=|:)?\s?['\"]?([^\s\"'&]+)"
282 | issuename = "Xkeys ["+key+"]"
283 | issuelevel = "Information"
284 | issuedetail = """[$key$] : $value$
285 |
Info: Maybe sensitive data exposure"""
286 |
287 | tmp_issues = self._CustomScans.findRegEx(regex, key, issuename, issuelevel, issuedetail)
288 | scan_issues = scan_issues + tmp_issues
289 |
290 | if len(scan_issues) > 0:
291 | return scan_issues
292 | else:
293 | return None
294 |
295 | class CustomScans:
296 | def __init__(self, requestResponse, callbacks):
297 | self._requestResponse = requestResponse
298 | self._callbacks = callbacks
299 |
300 | self._helpers = self._callbacks.getHelpers()
301 |
302 | self._params = self._helpers.analyzeRequest(requestResponse.getRequest()).getParameters()
303 | return
304 |
305 | def findRegEx(self, regex, key, issuename, issuelevel, issuedetail):
306 | scan_issues = []
307 | offset = array('i', [0, 0])
308 | response = self._requestResponse.getResponse()
309 | responseLength = len(response)
310 |
311 | rg = re.compile(regex, re.DOTALL)
312 | matchs = rg.findall(self._helpers.bytesToString(response))
313 |
314 | for out in matchs:
315 | url = self._helpers.analyzeRequest(self._requestResponse).getUrl()
316 |
317 | value = out[1]
318 | offsets = []
319 | start = self._helpers.indexOf(response, value, True, 0, responseLength)
320 | offset[0] = start
321 | offset[1] = start + len(value)
322 | offsets.append(offset)
323 |
324 | try:
325 | print "[Xkeys] "+key+" : "+value
326 | scan_issues.append(ScanIssue(self._requestResponse.getHttpService(),
327 | self._helpers.analyzeRequest(self._requestResponse).getUrl(),
328 | [self._callbacks.applyMarkers(self._requestResponse, None, offsets)],
329 | issuename, issuelevel, issuedetail.replace("$key$", key).replace("$value$", value)))
330 | except:
331 | continue
332 | return (scan_issues)
333 |
334 | class ScanIssue(IScanIssue):
335 | def __init__(self, httpservice, url, requestresponsearray, name, severity, detailmsg):
336 | self._url = url
337 | self._httpservice = httpservice
338 | self._requestresponsearray = requestresponsearray
339 | self._name = name
340 | self._severity = severity
341 | self._detailmsg = detailmsg
342 |
343 | def getUrl(self):
344 | return self._url
345 |
346 | def getHttpMessages(self):
347 | return self._requestresponsearray
348 |
349 | def getHttpService(self):
350 | return self._httpservice
351 |
352 | def getRemediationDetail(self):
353 | return None
354 |
355 | def getIssueDetail(self):
356 | return self._detailmsg
357 |
358 | def getIssueBackground(self):
359 | return None
360 |
361 | def getRemediationBackground(self):
362 | return None
363 |
364 | def getIssueType(self):
365 | return 0
366 |
367 | def getIssueName(self):
368 | return self._name
369 |
370 | def getSeverity(self):
371 | return self._severity
372 |
373 | def getConfidence(self):
374 | return "Certain"
375 |
--------------------------------------------------------------------------------