
Finde Plex Media Server, die von Plex2Shell (CVE-2026-96652 und drei weiteren) betroffen sind
Findet Plex Media Server, die von Plex2Shell betroffen sind, der Kette aus vier Schwachstellen (CVE-2026-96652, CVE-2026-96654, CVE-2026-96655, CVE-2026-96656), die es Angreifern ermöglicht, einen Plex Media Server älter als 1.43.3.10861 zu übernehmen, ohne sich anzumelden. Teil von shouldipanic.ch.
Plex2Shell wird seit dem 17. Oktober 2026 ausgenutzt (Cryptominer, Proxys) und steht auf der Liste der bekannten ausgenutzten Schwachstellen (Known Exploited Vulnerabilities) von CISA. Jeder Plex Media Server älter als 1.43.3.10861, der aus dem Internet erreichbar ist, ist gefährdet.
plex2scan gibt es in zwei Formen:
plex2scan.py: eine einzelne Python-Datei ohne Abhängigkeiten zum Prüfen
eigener Server: IP-Bereiche, Portscan einschließlich Plex' Port 32400, vhost-
Erkennung und die Plex-Versionsprüfung.
Jeder Plex Media Server beantwortet GET /identity ohne Anmeldung und gibt dort seine
Version an. plex2scan lädt die Startseite (um Plex anhand seines
X-Plex-Protocol-Headers oder der Plex-Webseite zu erkennen) und fragt /identity einmal ab.
Sonst wird nichts gesendet: keine Anmeldung, kein Exploit.
curl -LO https://github.com/akaihigurashi/plex2scan/releases/latest/download/plex2scan.py
python3 plex2scan.py 203.0.113.0/24
Python 3.8 oder neuer, nichts zu installieren. Beispiele:
python3 plex2scan.py 203.0.113.10 # 21 ports incl. 32400 + every vhost on the IP
python3 plex2scan.py 203.0.113.10:32400 # only Plex's own port
python3 plex2scan.py plex.example.ch # a Plex behind a reverse proxy
python3 plex2scan.py 203.0.113.0/24 --names domains.txt # + hostnames from your own data
python3 plex2scan.py 203.0.113.10 -p all -o out.csv # all 65535 ports, CSV output
python3 plex2scan.py -h # all options
| Status | Bedeutung |
|---|---|
VULNERABLE | Plex Media Server älter als 1.43.3.10861 |
POSSIBLY VULNERABLE | Plex Media Server gefunden, Version verborgen |
PATCHED | Plex Media Server 1.43.3.10861 oder neuer |
NOT DETECTED | Kein Plex Media Server sichtbar |
Die Ergebnisse werden mit dem schlechtesten zuerst aufgelistet, jeweils mit einer kurzen Begründung. Verborgene Ergebnisse (geschlossene Ports, Fehler, vhosts, die nur die Standardseite zeigen) erscheinen mit -a, die Belege mit -v.
| Option | Was sie bewirkt |
|---|---|
-p LIST | Ports: web (20 gängige Ports + 32400, Standard), all oder 80,443,32400 |
-n | Kein Portscan, nur 443 und 80 |
--names FILE | Eigene Hostnamen-Liste, die als vhosts geprüft wird |
--no-vhosts | Nicht nach anderen Websites auf derselben IP suchen |
-a / -v | Verborgene Ergebnisse anzeigen / die Belege anzeigen |
-o FILE | Alle Ergebnisse zusätzlich in CSV schreiben |
-d | Debug: jede Anfrage, jeder Header und jeder Treffer |
-q | Kein Banner (für Skripte) |
-V | Die Version ausgeben |
-h | Alle Optionen |
myawesomeproxy,
mylovelyminer oder x12345, unbekannte .so/.dll-Dateien im Codecs-Ordner von Plex,
Verbindungen zu proxystream.st, hohe CPU-Last, während nichts abgespielt wird. Ein Update
entfernt keinen Angreifer, der bereits eingedrungen ist.AlienVault OTX und HackerTarget funktionieren ohne Schlüssel. VirusTotal, Shodan und SecurityTrails benötigen einen API-Schlüssel, der aus Umgebungsvariablen gelesen wird:
| Variable | Quelle |
|---|---|
PANIC_VT_KEY | VirusTotal passive DNS |
PANIC_SHODAN_KEY | Shodan hostnames |
PANIC_SECURITYTRAILS_KEY | SecurityTrails reverse IP |
Bewahre sie in einer .env-Datei auf, die nur du lesen kannst, und lade sie nur für den Scan:
( set -a; . ./.env; set +a; python3 plex2scan.py 203.0.113.10 )
--vt-key, --shodan-key und --securitytrails-key funktionieren ebenfalls, aber Kommandozeilenargumente sind für andere lokale Benutzer sichtbar (ps) und landen in Ihrer Shell-Historie. Schlüsselwerte werden in Fehlermeldungen maskiert. (Danke an Jonas Hüsser dafür.)
docker run -d --name plex2scan --restart unless-stopped \
-p 127.0.0.1:8091:8091 \
-e PANIC_ORIGIN=https://plex2scan.example.ch \
-v plex2scan-data:/data \
ghcr.io/akaihigurashi/plex2scan:latest
Oder mit Compose: Lade docker-compose.yml herunter, setze
PANIC_ORIGIN und führe dann docker compose up -d aus. Der Container lauscht nur auf localhost;
stelle einen Reverse-Proxy mit TLS davor
(nginx-Beispiel).
| Variable | Standard | Zweck |
|---|---|---|
PANIC_ORIGIN | – | Öffentliche Adresse. Anfragen von anderen Origins werden abgelehnt. Setze sie. |
PANIC_OPERATOR / PANIC_CONTACT | – | Optionaler Kontaktbereich am unteren Ende der Seite |
PANIC_IMPRINT_URL | – | Optionaler Link zu einem bestehenden Impressum |
PANIC_TRUSTED_PROXY | 127.0.0.1,::1 | Proxies, deren X-Real-IP-Header vertraut wird |
PANIC_DENY_HOSTS / PANIC_DENY_IPS | – | Diese Domains / Adressen niemals prüfen |
PANIC_AUDIT_DIR | /data/audit | Tägliche Audit-Logdateien |
PANIC_RETENTION_DAYS | 30 | Ältere Audit-Dateien werden gelöscht |
Die Seite bietet dieselben Schutzmaßnahmen wie php2scan: Einwilligungs-Checkbox, Audit-Log, abgelehnte VPN-/Tor-/Rechenzentrums-Clients, Rate-Limit, Ergebnis-Cache, öffentliche Hostnamen nur mit an die geprüfte Adresse gebundener Verbindung, Websites, die niemals geprüft werden (bekannte Dienste, die 100 meistbesuchten Seiten, Regierungsseiten, sanktionierte Länder), und kein Zugriff aus sanktionierten Ländern. Neben der Website selbst (443, dann 80) prüft die Seite nur Port 32400, und zwar nur, wenn dieser offen ist.
Die Scanner-Engine (Abrufen, Fingerprinting, Portscan, Vhost-Discovery, Webserver) befindet sich in panic-core.
Alles, was spezifisch für Plex2Shell ist, steht in check.py.
plex2scan.py und web.py werden aus beiden generiert:
git clone https://github.com/akaihigurashi/panic-core ../panic-core
python3 ../panic-core/bundle.py check.py
GPL-3.0, siehe LICENSE. Schriften: Inter und JetBrains Mono (SIL Open Font License). Nicht mit Plex, Inc. verbunden oder von dieser unterstützt; „Plex" ist deren Marke.