pfSense CE 2.9.0-DEVELOPMENT - High - Remote - RCE - OpenVPN wizard CRLF
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · pfsense-openvpn-wizard-crlf
Class: RCE Reach: Remote
pfSense CE 2.9.0-DEVELOPMENT (9363ac5) - pfsense.org
OpenVPN wizard copies Default Domain / NetBIOS scope into dns_domain / netbios_scope with no is_domain() check, then openvpn_add_dhcpopts() writes them into a server config.ovpn that already has script-security 3. A quote plus LF closes the push "dhcp-option ..." line and adds server directives including up. Privilege is Wizard Subsystem, not OpenVPN advanced. Sibling of SA-26_07, which named only vpn_openvpn_server.php.
| ID | no CVE yet |
| Class | RCE |
| Reach | Remote (authenticated WebGUI) |
| CWE | CWE-74 / CWE-78 |
| CVSS | High: 8.8 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| Product | pfSense CE |
| Affected | 2.9.0-DEVELOPMENT (9363ac5b8651a1c7a333180425ce7719070f95f9) OpenVPN wizard |
| Auth | WebGUI session with page-pfsensewizardsubsystem |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 only |
I pinned public master 9363ac5. The lab is the pinned wizard assign plus openvpn_add_dhcpopts, then OpenVPN 2.6.14 on tun0. Loopback 127.0.0.1:18820. If 2.9.0-RELEASE escaped the helper, this is the same SA as SA-26_07.
| Method | Sink | Privilege |
|---|---|---|
Complete OpenVPN Remote Access wizard; set Default Domain (or NetBIOS scope) to a value that closes the push line and adds up | openvpn_add_dhcpopts into server config.ovpn (openvpn.inc:697-738) with script-security 3 (:905) | Integrity (lab-proven): OpenVPN 2.6.14 ran that up on tun0 and wrote the witness (up-exec=yes). Control example.com stayed a single DOMAIN push. |
| Same host commands | OpenVPN up as the daemon user (root on pfSense) | Recon (inferred): host filesystem, config.xml, keys. |
| Broken OpenVPN config or host commands | OpenVPN server | Availability (inferred): OpenVPN / firewall disruption. |
Lab-proven vs inferred: wizard assign, dhcpopts up, script-security 3, control-clean, and tun0 up-exec are lab-proven. Filesystem recon is inferred from the up process. Same poison in a CCD blob was not executed (ccd-up-ignored=yes).
Requires: WebGUI session with page-pfsensewizardsubsystem. CSRF token. Does not require page-openvpn-server or page-openvpn-server-advanced.
| Surface | Lab |
|---|---|
Control domain example.com | one DOMAIN push, control-clean=yes |
CCD up (OpenVPN 2.6 subset) | ccd-up-ignored=yes |
| Unauth / CSRF without token | closed |
OpenVPN custom_options | intended advanced privilege |
| Diagnostics: Command | stays closed unless also granted |
cd lab
./run.sh
Loopback 127.0.0.1:18820. Compose project pfsense-openvpn-wizard-crlf. Image tag pfsense-openvpn-wizard-crlf:2.9.0-dev. Witness PFSENSE-OPENVPN-WIZARD-CRLF-WITNESS. Last line:
SUCCESS PFSENSE-OPENVPN-WIZARD-CRLF wizard-assign=yes dhcpopts-up=yes script-security-3=yes control-clean=yes up-exec=yes PFSENSE-OPENVPN-WIZARD-CRLF-WITNESS
is_domain() (or strip CR/LF/quotes) on wizard defaultdomain / nbtscope before they become dns_domain / netbios_scope, same as IPsec mobile already does. Sanitize inside openvpn_add_dhcpopts() so every caller is covered, including the wizard.
9363ac5b8651a1c7a333180425ce7719070f95f9openvpn_wizard.incopenvpn.inc openvpn_add_dhcpoptsfd301381 (not in this public tree)