# Xkeys - Burp Suite Extension to extract interesting strings (key, secret, token, or etc.) from a webpage.
# Type : Passive Scanner
# By: Verry Darmawan (github.com/vsec7)
# Twitter: https://twitter.com/verry__d
# Code Credits:
# PortSwigger example-scanner-checks: https://github.com/PortSwigger/example-scanner-checks
# Redhunlabs Asset_Discover: https://github.com/redhuntlabs/BurpSuite-Asset_Discover
from burp import IBurpExtender
from burp import IScannerCheck
from burp import IScanIssue
from array import array
import re
class BurpExtender(IBurpExtender, IScannerCheck):
def registerExtenderCallbacks(self, callbacks):
self._callbacks = callbacks
self._callbacks.setExtensionName("Xkeys")
self._callbacks.registerScannerCheck(self)
print("Thank you for installing xkeys")
print("Passive scanner to extract interesting strings (key, secret, token, or etc.)")
print("By : Verry Darmawan (github.com/vsec7)")
print("Twitter : https://twitter.com/verry__d\n")
return
def consolidateDuplicateIssues(self, existingIssue, newIssue):
if (existingIssue.getIssueDetail() == newIssue.getIssueDetail()):
return -1
else:
return 0
def doPassiveScan(self, baseRequestResponse):
scan_issues = []
tmp_issues = []
self._CustomScans = CustomScans(baseRequestResponse, self._callbacks)
# Add your keywords for pattern
keywords = [
"access_key",
"access_token",
"accessKey",
"accessToken",
"account_sid",
"accountsid",
"admin_pass",
"admin_user",
"api_key",
"api_secret",
"apikey",
"app_key",
"app_secret",
"app_url",
"application_id",
"aws_secret_token",
"authsecret",
"aws_access",
"aws_access_key_id",
"aws_bucket",
"aws_config",
"aws_default_region",
"aws_key",
"aws_secret",
"aws_secret_access_key",
"aws_secret_key",
"aws_token",
"bucket_password",
"client_secret",
"cloudinary_api_key",
"cloudinary_api_secret",
"cloudinary_name",
"connectionstring",
"consumer_secret",
"database_dialect",
"database_host",
"database_logging",
"database_password",
"database_schema",
"database_schema_test",
"database_url",
"database_username",
"db_connection",
"db_database",
"db_dialect",
"db_host",
"db_password",
"db_port",
"db_server",
"db_username",
"dbpasswd",
"dbpassword",
"dbuser",
"django_password",
"elastica_host",
"elastica_port",
"elastica_prefix",
"email_host_password",
"facebook_app_secret",
"facebook_secret",
"fb_app_secret",
"fb_id",
"fb_secret",
"gatsby_wordpress_base_url",
"gatsby_wordpress_client_id",
"gatsby_wordpress_client_secret",
"gatsby_wordpress_password",
"gatsby_wordpress_protocol",
"gatsby_wordpress_user",
"github_id",
"github_secret",
"google_id",
"google_oauth",
"google_oauth_client_id",
"google_oauth_client_secret",
"google_oauth_secret",
"google_secret",
"google_server_key",
"gsecr",
"heroku_api_key",
"heroku_key",
"heroku_oauth",
"heroku_oauth_secret",
"heroku_oauth_token",
"heroku_secret",
"heroku_secret_token",
"htaccess_pass",
"htaccess_user",
"incident_bot_name",
"incident_channel_name",
"jwt_passphrase",
"jwt_password",
"jwt_public_key",
"jwt_secret",
"jwt_secret_key",
"jwt_secret_token",
"jwt_token",
"jwt_user",
"keyPassword",
"mail_driver",
"mail_encryption",
"mail_from_address",
"mail_from_name",
"mail_host",
"mail_password",
"mail_port",
"mail_username",
"mailgun_key",
"mailgun_secret",
"maps_api_key",
"mix_pusher_app_cluster",
"mix_pusher_app_key",
"mysql_password",
"oauth_discord_id",
"oauth_discord_secret",
"oauth_key",
"oauth_token",
"oauth2_secret",
"password",
"paypal_identity_token",
"paypal_sandbox",
"paypal_secret",
"paypal_token",
"playbooks_url",
"postgres_password",
"private_key",
"pusher_app_cluster",
"pusher_app_id",
"pusher_app_key",
"pusher_app_secret",
"queue_driver",
"redis_host",
"redis_password",
"redis_port",
"response_auth_jwt_secret",
"response_data_secret",
"response_data_url",
"root_password",
"sa_password",
"secret",
"secret_access_key",
"secret_bearer",
"secret_key",
"secret_token",
"secretKey",
"security_credentials",
"send_keys",
"sentry_dsn",
"session_driver",
"session_lifetime",
"sf_username",
"sid twilio",
"sid_token",
"sid_twilio",
"slack_channel",
"slack_incoming_webhook",
"slack_key",
"slack_outgoing_token",
"slack_secret",
"slack_signing_secret",
"slack_token",
"slack_url",
"slack_webhook",
"slack_webhook_url",
"square_access_token",
"square_apikey",
"square_app",
"square_app_id",
"square_appid",
"square_secret",
"square_token",
"squareSecret",
"squareToken",
"ssh2_auth_password",
"sshkey",
"storePassword",
"strip_key",
"strip_secret",
"strip_secret_token",
"strip_token",
"stripe_key",
"stripe_secret",
"stripe_secret_token",
"stripe_token",
"stripSecret",
"stripToken",
"stripe_publishable_key",
"token_twilio",
"trusted_hosts",
"twi_auth",
"twi_sid",
"twilio_account_id",
"twilio_account_secret",
"twilio_account_sid",
"twilio_accountsid",
"twilio_api",
"twilio_api_auth",
"twilio_api_key",
"twilio_api_secret",
"twilio_api_sid",
"twilio_api_token",
"twilio_auth",
"twilio_auth_token",
"twilio_secret",
"twilio_secret_token",
"twilio_sid",
"twilio_token",
"twilioapiauth",
"twilioapisecret",
"twilioapisid",
"twilioapitoken",
"TwilioAuthKey",
"TwilioAuthSid",
"twilioauthtoken",
"TwilioKey",
"twiliosecret",
"TwilioSID",
"twiliotoken",
"twitter_api_secret",
"twitter_consumer_key",
"twitter_consumer_secret",
"twitter_key",
"twitter_secret",
"twitter_token",
"twitterKey",
"twitterSecret",
"wordpress_password",
"zen_key",
"zen_tkn",
"zen_token",
"zendesk_api_token",
"zendesk_key",
"zendesk_token",
"zendesk_url",
"zendesk_username",
"zendesk_password"
]
for key in keywords:
regex = "(?i)"+key+"['\"]?\s?(=|:)?\s?['\"]?([^\s\"'&]+)"
issuename = "Xkeys ["+key+"]"
issuelevel = "Information"
issuedetail = """[$key$] : $value$
Info: Maybe sensitive data exposure"""
tmp_issues = self._CustomScans.findRegEx(regex, key, issuename, issuelevel, issuedetail)
scan_issues = scan_issues + tmp_issues
if len(scan_issues) > 0:
return scan_issues
else:
return None
class CustomScans:
def __init__(self, requestResponse, callbacks):
self._requestResponse = requestResponse
self._callbacks = callbacks
self._helpers = self._callbacks.getHelpers()
self._params = self._helpers.analyzeRequest(requestResponse.getRequest()).getParameters()
return
def findRegEx(self, regex, key, issuename, issuelevel, issuedetail):
scan_issues = []
offset = array('i', [0, 0])
response = self._requestResponse.getResponse()
responseLength = len(response)
rg = re.compile(regex, re.DOTALL)
matchs = rg.findall(self._helpers.bytesToString(response))
for out in matchs:
url = self._helpers.analyzeRequest(self._requestResponse).getUrl()
value = out[1]
offsets = []
start = self._helpers.indexOf(response, value, True, 0, responseLength)
offset[0] = start
offset[1] = start + len(value)
offsets.append(offset)
try:
print "[Xkeys] "+key+" : "+value
scan_issues.append(ScanIssue(self._requestResponse.getHttpService(),
self._helpers.analyzeRequest(self._requestResponse).getUrl(),
[self._callbacks.applyMarkers(self._requestResponse, None, offsets)],
issuename, issuelevel, issuedetail.replace("$key$", key).replace("$value$", value)))
except:
continue
return (scan_issues)
class ScanIssue(IScanIssue):
def __init__(self, httpservice, url, requestresponsearray, name, severity, detailmsg):
self._url = url
self._httpservice = httpservice
self._requestresponsearray = requestresponsearray
self._name = name
self._severity = severity
self._detailmsg = detailmsg
def getUrl(self):
return self._url
def getHttpMessages(self):
return self._requestresponsearray
def getHttpService(self):
return self._httpservice
def getRemediationDetail(self):
return None
def getIssueDetail(self):
return self._detailmsg
def getIssueBackground(self):
return None
def getRemediationBackground(self):
return None
def getIssueType(self):
return 0
def getIssueName(self):
return self._name
def getSeverity(self):
return self._severity
def getConfidence(self):
return "Certain"