
pfSense CE 2.9.0-DEVELOPMENT - Élevé - À distance - RCE - CARP VHID résiduel
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · pfsense-carp-vhid
Write-up : https://abraxaslabs.tech/research/pfsense-carp-vhid
Classe : RCE Portée : Distante
pfSense CE 2.9.0-DEVELOPMENT (9363ac5) - pfsense.org
L'édition d'une IP virtuelle stocke le VHID CARP depuis le POST sans vérification 1-255. Les options de Form_Select ne sont que du HTML. L'application CARP applique escapeshellarg sur le VHID. L'application d'un IP Alias empilé interpole vhid {$carpvip['vhid']} en dehors de escapeshellarg. Le statut CARP interpole le même VHID stocké dans un pipeline grep à guillemets doubles ; le point-virgule reste entre guillemets, la substitution de commande s'exécute tout de même sous /bin/sh -c. Le privilège requis est l'édition + application de VIP, pas Diagnostics : Command.
| ID | pas encore de CVE |
| Classe | RCE |
| Portée | Distante (WebGUI authentifiée) |
| CWE | CWE-78 |
| CVSS | Élevé : 8.8 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| Produit | pfSense CE |
| Affecté | 2.9.0-DEVELOPMENT (9363ac5b8651a1c7a333180425ce7719070f95f9) CARP VHID |
| Auth | Session WebGUI avec édition + application de VIP (le statut/widget est un déclencheur ultérieur) |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
J'ai épinglé le master public 9363ac5. Le lab est un gadget PHP composé de interface_carp_configure épinglé, du mwexec de l'ipalias empilé, et de l'exec du statut. Loopback 127.0.0.1:18830.
| Méthode | Sink | Privilège |
|---|---|---|
POST d'une VIP carp avec un VHID non entier, puis application d'un IP Alias empilé sur ce parent _vip{uniqid} | mwexec ifconfig ... alias {$gateway} {$vhid} (interfaces.inc:3238) | Intégrité (prouvé en lab) : shell root. Lab : ipalias-unescaped a écrit le témoin. L'application CARP du même VHID n'a rien écrit (carp-escaped=yes). |
Même VHID stocké, puis GET status_carp.php ou rendu de carp_status.widget.php | pipeline grep exec (pfsense-utils.inc:794) | Intégrité (prouvé en lab) : la substitution de commande à l'intérieur des guillemets doubles s'est exécutée et a écrit le témoin (status-sink=yes, status-subst=yes). Le point-virgule est resté entre guillemets. Le déclencheur widget peut être une autre session GUI. |
| Même shell root | système de fichiers de l'hôte | Reconnaissance (déduit) : config.xml, clés. |
Shell root ou ifconfig cassé | périphériques CARP / alias | Disponibilité (déduit) : perturbation d'interface / CARP / filtre. |
Prouvé en lab vs déduit : carp-escaped, le témoin ipalias-unescaped, et le témoin de substitution de commande du statut sont prouvés en lab. La reconnaissance du système de fichiers et la perturbation du filtre sont déduites du PHP-FPM root.
Nécessite : page-firewall-virtualipaddress-edit (enregistrement) et page-firewall-virtualipaddresses (application). Sink de statut : page-status-carp ou tout tableau de bord avec le widget CARP. CSRF sur le POST.
| Surface | Lab |
|---|---|
| L'application CARP elle-même | escapeshellarg sur le VHID, carp-escaped=yes |
| Mot de passe CARP / advbase / advskew / subnet | is_ipaddr / échappé |
| Non authentifié | fermé |
| Application xmlrpc des mêmes objets sans identifiants HA | liste d'exclusion SA-26_22 |
| Diagnostics : Command | reste fermé sauf si également accordé |
cd lab
./run.sh
Loopback 127.0.0.1:18830. Projet Compose pfsense-carp-vhid. Tag d'image pfsense-carp-vhid:2.9.0-dev. Témoin PFSENSE-CARP-VHID-WITNESS. Dernière ligne :
SUCCESS PFSENSE-CARP-VHID carp-escaped=yes ipalias-unescaped=yes status-sink=yes PFSENSE-CARP-VHID-WITNESS
Restreindre le VHID à une plage d'entiers de 1 à 255 lors de l'enregistrement. Appliquer escapeshellarg au VHID lors de l'application des IP Alias empilés et lors du grep de statut, de la même manière que le fait déjà l'application CARP.
9363ac5b8651a1c7a333180425ce7719070f95f9firewall_virtual_ip.inc saveVIPinterfaces.inc mwexec des ipalias empiléspfsense-utils.inc grep de statut CARP