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