-
Notifications
You must be signed in to change notification settings - Fork 0
/
jsprobex.py
222 lines (189 loc) · 12 KB
/
jsprobex.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
import requests
import re
import json
import os
import sys
import argparse
import random
from urllib.parse import urlparse
from colorama import Fore, Style, init
from requests.packages.urllib3.exceptions import InsecureRequestWarning
# Suppress InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
# Initialize Colorama
init(autoreset=True)
def print_banner():
"""Prints a banner with a random color every time it's used."""
banner = """
▄█ ▄████████ ▄███████▄ ▄████████ ▄██████▄ ▀█████████▄ ▄████████ ▀████ ▐████▀
███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███▌ ████▀
███ ███ █▀ ███ ███ ███ ███ ███ ███ ███ ███ ███ █▀ ███ ▐███
███ ███ ███ ███ ▄███▄▄▄▄██▀ ███ ███ ▄███▄▄▄██▀ ▄███▄▄▄ ▀███▄███▀
███ ▀███████████ ▀█████████▀ ▀▀███▀▀▀▀▀ ███ ███ ▀▀███▀▀▀██▄ ▀▀███▀▀▀ ████▀██▄
███ ███ ███ ▀███████████ ███ ███ ███ ██▄ ███ █▄ ▐███ ▀███
███ ▄█ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ▄███ ███▄
█▄ ▄███ ▄████████▀ ▄████▀ ███ ███ ▀██████▀ ▄█████████▀ ██████████ ████ ███▄
▀▀▀▀▀▀ ███ ███
Developed by Mayank Rajput (hackelite01)
"""
# List of colors to choose from
colors = [
"\033[91m", # Red
"\033[92m", # Green
"\033[93m", # Yellow
"\033[94m", # Blue
"\033[95m", # Magenta
"\033[96m", # Cyan
"\033[97m", # White
]
# Select a random color from the list
color = random.choice(colors)
# Print the banner with the selected color
print(color + banner)
def extract_links_from_js(js_content):
"""Extracts URLs from JavaScript content."""
url_pattern = r'(https?://[^\s\'"<>]+)'
return re.findall(url_pattern, js_content)
def extract_secrets(js_content):
"""Extracts potential secrets from JavaScript content."""
secret_patterns = {
'API Key': r'(?i)API_Key\s*:\s*[\'"]?([A-Za-z0-9_-]{32,})[\'"]?',
'Algolia API Key': r'(?i)algolia_api_key\s*[:=]\s*[\'"]?([a-f0-9]{32})[\'"]?',
'Algolia Admin Key': r'(?i)algolia_admin_key\s*[:=]\s*[\'"]?([a-f0-9]{32})[\'"]?',
'API Key': r'(?i)api_key\s*[:=]\s*[\'"]?([A-Za-z0-9/_+=\-]{32,})[\'"]?',
'Auth Domain': r'(?i)Auth_Domain\s*:\s*[\'"]?([A-Za-z0-9\-]+\.[a-z]{2,})[\'"]?',
'AWS Access Key': r'(?i)AWS_Access_Key\s*:\s*[\'"]?([A-Z0-9]{20})[\'"]?',
'AWS Secret Key': r'(?i)AWS_Secret_Key\s*:\s*[\'"]?([A-Za-z0-9/+=]{40})[\'"]?',
'AWS Session Token': r'(?i)aws_session_token\s*[:=]\s*[\'"]?([A-Za-z0-9/+=]{16,})[\'"]?',
'Basic Auth Credentials': r'[a-zA-Z0-9_\-]+:[a-zA-Z0-9_\-]+@[a-zA-Z0-9_\-]+\.[a-zA-Z]{2,}',
'Cloudflare API Key': r'(?i)cloudflare_api_key\s*[:=]\s*[\'"]?([A-Za-z0-9]{37})[\'"]?',
'Database URL': r'(?i)Database_URL\s*:\s*[\'"]?([a-z0-9\-]+\.[a-z]{2,})[\'"]?',
'Dropbox API Key': r'dbx_[A-Za-z0-9]{64}',
'Facebook Access Token': r'(?i)EAACEdEose0cBA[0-9A-Za-z]+',
'Facebook Secret Key': r'(?i)fb_secret_key\s*[:=]\s*[\'"]?([a-f0-9]{32})[\'"]?',
'Facebook Token': r'(?i)Facebook_Token\s*:\s*[\'"]?([A-Za-z0-9\.]+)[\'"]?',
'Firebase API Key': r'(?i)firebase_api_key\s*:\s*[\'"]?([A-Za-z0-9_]{32})[\'"]?',
'Firebase Database URL': r'https:\/\/[a-z0-9-]+\.firebaseio\.com',
'Firebase Storage Bucket': r'(?i)"storageBucket"\s*:\s*"([A-Za-z0-9\-_]+\.appspot\.com)"',
'GitHub Access Token': r'ghp_[A-Za-z0-9_]{36}',
'GitHub OAuth Token': r'gho_[A-Za-z0-9_]{36}',
'GitHub Secret Key': r'(?i)github_secret_key\s*:\s*[\'"]?([A-Za-z0-9_]{40})[\'"]?',
'GitHub Token': r'(?i)GitHub Token\s*:\s*[\'"]?([A-Za-z0-9]{36})[\'"]?',
'Google Cloud API Key': r'(?i)AIza[0-9A-Za-z-_]{35}',
'Google Cloud Secret Key': r'(?i)"private_key"\s*:\s*"-----BEGIN PRIVATE KEY-----[A-Za-z0-9/+=\s]+-----END PRIVATE KEY-----"',
'Google Maps API Key': r'(?i)Google Maps API Key\s*:\s*[\'"]?([A-Za-z0-9_-]+)[\'"]?',
'Google OAuth Access Token': r'ya29\.[0-9A-Za-z\-_]+',
'Google reCAPTCHA Key': r'(?i)Google reCAPTCHA Key\s*:\s*[\'"]?([A-Za-z0-9_-]+)[\'"]?',
'Heroku API Key': r'(?i)heroku_api_key\s*:\s*[\'"]?([A-Za-z0-9]{32})[\'"]?',
'Instagram Access Token': r'(?i)instagram_access_token\s*:\s*[\'"]?([A-Za-z0-9\-._]+)[\'"]?',
'JWT Token': r'ey[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+',
'LinkedIn Secret Key': r'(?i)linkedin_secret_key\s*[:=]\s*[\'"]?([A-Za-z0-9_]{32})[\'"]?',
'Mailgun API Key': r'(?i)mailgun_api_key\s*:\s*[\'"]?([A-Za-z0-9]{32})[\'"]?',
'Microsoft Client ID': r'(?i)microsoft_client_id\s*[:=]\s*[\'"]?([0-9a-fA-F\-]{36})[\'"]?',
'Microsoft Client Secret': r'(?i)microsoft_client_secret\s*[:=]\s*[\'"]?([A-Za-z0-9/_+=]{32,})[\'"]?',
'OAuth Token': r'(?i)OAuth_Token\s*:\s*[\'"]?([A-Za-z0-9_-]+)[\'"]?',
'PayPal Client ID': r'(?i)paypal_client_id\s*:\s*[\'"]?([A-Za-z0-9-_]{15,})[\'"]?',
'PayPal Secret': r'(?i)paypal_secret\s*:\s*[\'"]?([A-Za-z0-9-_]{15,})[\'"]?',
'Private Key': r'(?i)"private_key"\s*:\s*"-----BEGIN PRIVATE KEY-----[A-Za-z0-9/+=\s]+-----END PRIVATE KEY-----"',
'Secret Key': r'(?i)Secret_Key\s*:\s*[\'"]?([A-Za-z0-9_-]{32,})[\'"]?',
'Secret Key': r'(?i)secret_key\s*[:=]\s*[\'"]?([A-Za-z0-9/_+=\-]{32,})[\'"]?',
'Secret Token': r'[A-Za-z0-9]{64}',
'Shopify API Key': r'(?i)shopify_api_key\s*[:=]\s*[\'"]?([A-Za-z0-9]{32})[\'"]?',
'Shopify Access Token': r'(?i)shopify_access_token\s*[:=]\s*[\'"]?([A-Za-z0-9]{32})[\'"]?',
'Slack API Key': r'(?i)xox[baprs]-[A-Za-z0-9]{10,48}',
'Slack Webhook URL': r'https:\/\/hooks\.slack\.com\/services\/[A-Za-z0-9_\/-]+',
'Square Access Token': r'sq0atp-[A-Za-z0-9\-_]{22,43}',
'Stripe API Key': r'(?i)sk_live_[0-9a-zA-Z]{24}',
'Stripe Publishable Key': r'(?i)pk_live_[0-9a-zA-Z]{24}',
'Stripe Secret Key': r'(?i)Stripe_Secret_Key\s*:\s*[\'"]?([A-Za-z0-9]{24})[\'"]?',
'Telegram Bot Token': r'(?i)Telegram Bot Token\s*:\s*[\'"]?([A-Za-z0-9:]+)[\'"]?',
'Twilio Account SID': r'(?i)twilio_account_sid\s*:\s*[\'"]?([A-Za-z0-9]{34})[\'"]?',
'Twilio Auth Token': r'(?i)twilio_auth_token\s*:\s*[\'"]?([A-Za-z0-9]{32})[\'"]?',
}
found_secrets = {}
for key, pattern in secret_patterns.items():
matches = re.findall(pattern, js_content)
if matches:
found_secrets[key] = list(set(matches))
return found_secrets
def process_js_content(js_url, cookies=None, extract_urls=True, extract_secrets_flag=True):
"""Fetches and processes JavaScript content for URLs and secrets."""
headers = {'Cookie': cookies} if cookies else {}
try:
response = requests.get(js_url, headers=headers, verify=False)
if response.status_code == 200:
links = extract_links_from_js(response.text) if extract_urls else []
secrets = extract_secrets(response.text) if extract_secrets_flag else {}
return links, secrets
else:
print(f"{Fore.RED}[ERROR]{Style.RESET_ALL} Failed to fetch {js_url}. Status Code: {response.status_code}")
except requests.RequestException as e:
print(f"{Fore.RED}[ERROR]{Style.RESET_ALL} Could not fetch {js_url}: {e}")
return [], {}
def process_file(input_file, output_url_file, output_secret_file, cookies=None, extract_urls=True, extract_secrets_flag=True):
"""Processes a file containing JavaScript URLs."""
if not os.path.exists(input_file):
print(f"{Fore.RED}[ERROR]{Style.RESET_ALL} File not found: {input_file}")
return
url_results = []
secret_results = []
with open(input_file, 'r') as file:
js_links = file.readlines()
for js_url in js_links:
js_url = js_url.strip()
if not js_url:
continue
print(f"{Fore.BLUE}[INFO]{Style.RESET_ALL} Processing {js_url}...")
links, secrets = process_js_content(js_url, cookies, extract_urls, extract_secrets_flag)
if extract_urls and links:
url_results.append(f"{js_url}:\n" + '\n'.join(links) + '\n')
if extract_secrets_flag and secrets:
secret_results.append(f"Secrets from {js_url}:\n" + json.dumps(secrets, indent=2) + '\n')
# Write the URL results to the output URL file
if url_results:
with open(output_url_file, 'w') as output:
output.writelines(url_results)
print(f"{Fore.GREEN}[INFO]{Style.RESET_ALL} URL results saved to {output_url_file}")
# Write the secret results to the output secret file
if secret_results:
with open(output_secret_file, 'w') as output:
output.writelines(secret_results)
print(f"{Fore.GREEN}[INFO]{Style.RESET_ALL} Secret results saved to {output_secret_file}")
else:
print(f"{Fore.YELLOW}[INFO]{Style.RESET_ALL} No secrets found.")
def main():
"""Main function to parse arguments and run the script."""
print_banner() # Print the banner at the start of the script
parser = argparse.ArgumentParser(description="JavaScript Analyzer for URLs and Secrets.")
parser.add_argument("-f", "--file", help="Specify a file containing JavaScript URLs.")
parser.add_argument("-o", "--output_file", default="extracted.txt", help="Specify the output file to save results.")
parser.add_argument("-u", "--url", help="Analyze a single JavaScript URL.")
parser.add_argument("--secrets", action="store_true", help="Look for sensitive secrets in JavaScript content.")
parser.add_argument("--urls", action="store_true", help="Extract URLs from JavaScript content.")
parser.add_argument("--cookies", help="Specify cookies for authentication (optional).")
args = parser.parse_args()
if len(sys.argv) == 1:
# If no arguments are passed, show the help menu
parser.print_help()
sys.exit(0)
cookies = args.cookies
extract_urls_flag = args.urls or not args.secrets # Default to extracting URLs if no flag is set.
extract_secrets_flag = args.secrets or not args.urls # Default to extracting secrets if no flag is set.
# If analyzing a single URL, process it
if args.url:
print(f"{Fore.BLUE}[INFO]{Style.RESET_ALL} Processing single URL: {args.url}")
links, secrets = process_js_content(args.url, cookies, extract_urls_flag, extract_secrets_flag)
with open(args.output_file, 'w') as output:
if extract_urls_flag and links:
output.write(f"{args.url}:\n" + '\n'.join(links) + '\n')
if extract_secrets_flag and secrets:
output.write(f"Secrets from {args.url}:\n" + json.dumps(secrets, indent=2) + '\n')
print(f"{Fore.GREEN}[INFO]{Style.RESET_ALL} Results saved to {args.output_file}")
# If analyzing a file with multiple URLs, process it
if args.file:
print(f"{Fore.BLUE}[INFO]{Style.RESET_ALL} Processing file: {args.file}")
output_url_file = "extracted_links.txt" # Default output file for URLs
output_secret_file = "extracted_secrets.txt" # Default output file for secrets
process_file(args.file, output_url_file, output_secret_file, cookies, extract_urls_flag, extract_secrets_flag)
if __name__ == "__main__":
main()