
Erkennungsskript für CVE-2026-11374
Ein Erkennungsskript für die Exploit-Voraussetzung von CVE-2026-11374, eine Schwachstelle mit vorhersagbarem SSO-Ticket, die zu einer nicht authentifizierten Kontoübernahme in der gesamten ManageEngine-AD360-Suite führt. Die vier betroffenen Produkte teilen sich das ManageEngineADSFramework:
| Produkt | Betroffener Build | Fix-Build |
|---|
| ADSelfService Plus | ≤ 6528 | 6529 |
| RecoveryManager Plus | ≤ 6320 | 6321 |
| M365 Manager Plus | ≤ 4816 | 4817 |
| ADAudit Plus | ≤ 8702 | 8703 |
In betroffenen Builds ist das SSO-Ticket lediglich System.currentTimeMillis() (ein vorhersagbarer Zeitstempel), der beim Login des Opfers abgetastet wird, sodass es über das Cookie CUSTOM_SSO_TICKET replaybar ist, um diese Sitzung zu übernehmen. Der Fix ersetzt das Ticket durch UUID.randomUUID() (eine ausreichend zufällige Kennung). Der Replay-Pfad ist nur erreichbar, wenn das Produkt in AD360 integriert ist: ADSFilter macht ihn von isProductIntegrated() abhängig. Diese Hürde ist die Voraussetzung, die dieses Werkzeug prüft.
HINWEIS: Dieser Detektor bestätigt die Voraussetzung, nicht die Schwachstelle selbst. Ein
POTENTIALLY_AFFECTED-Ergebnis ist kein bestätigtes „verwundbar“-Urteil – siehe unten für weitere Informationen.
Ja. Das Werkzeug ist für den Produktions- und Bewertungseinsatz konzipiert.
1700000000000, ein Millisekundenwert, der so weit in der Vergangenheit liegt, dass er nie im Cache liegen kann), sodass niemals eine Sitzung erlangt wird. Der Server teilt uns lediglich mit, die gesendeten Cookies zu löschen.GET, und die einzigen betroffenen Cookies sind die Wegwerf-Cookies, die das Werkzeug sendet.Der Patch für CVE-2026-11374 änderte nur, wie das Ticket erzeugt wird (von Millisekunden zu UUID); er änderte nicht den Cookie-Replay-Pfad, den diese Sonde testet. Daher antwortet eine gepatchte Installation Byte für Byte identisch zu einer anfälligen auf jede nicht authentifizierte Anfrage.
Was das Werkzeug ohne Authentifizierung und nicht destruktiv tun kann:
Was es nicht kann:
POTENTIALLY_AFFECTED-Ergebnis bedeutet, dass die Voraussetzung erfüllt ist und Sie den Patch-Stand überprüfen sollten, nicht dass der Host als verwundbar bestätigt ist.conf/product.conf oder das aktive Auflösen eines Live-Tickets (echte Exploitation, die hier bewusst nicht implementiert ist).?build= ist manchmal der echte Build und manchmal ein eingefrorener Platzhalter, der unterhalb des Fix-Builds liegt. Ein Wert unterhalb des Fix-Builds ist daher mehrdeutig, und das Werkzeug markiert ihn als nicht schlüssig. Ein Wert auf oder über dem Fix-Build ist weiterhin ein vertrauenswürdiges „gepatcht“-Signal, da der Platzhalter immer zu niedrig ist, um ihn zu erreichen.requests. Installation mit
pip install requests.# single host (prefer a URL or host:port; ports differ per product)
./cve_2026_11374_check.py https://adssp.example.com:8888
# multiple hosts (scheme optional: https is tried first, then http)
./cve_2026_11374_check.py host-a:8081 host-b:8365
# scan a list, one target per line ('#' comments allowed), compact output
./cve_2026_11374_check.py -f targets.txt --brief
# machine-readable output for pipelines
./cve_2026_11374_check.py -f targets.txt --json > results.json
Die Standard-Ports unterscheiden sich je nach Produkt (ADSelfService Plus 8888, ADAudit Plus 8081, M365 Manager Plus 8365, RecoveryManager Plus 8090); übergeben Sie daher eine URL oder host:port. Ein bloßer Host verwendet standardmäßig 8888.
| Flag | Beschreibung |
|---|---|
targets | Ein oder mehrere host, host:port oder https://host:port |
-f, --targets-file FILE | Ziele aus einer Datei lesen (eine pro Zeile; #-Kommentare) |
--brief | Eine einzelne ausgerichtete Zeile pro Ziel, gut zum Scannen vieler Hosts |
--json | Strukturierte JSON-Ergebnisse ausgeben |
--timeout SECS | Timeout pro Anfrage (Standard: 15) |
--no-build | Die zusätzliche Build-Nummer-Anfrage bei einem positiven Befund überspringen |
--no-color | Farbige Ausgabe deaktivieren (respektiert auch NO_COLOR und Nicht-TTY) |
Eine in AD360 integrierte Konsole (ausführlich, Standard). Die zweite Zeile stellt klar, dass es sich um die Voraussetzung und nicht um ein „verwundbar“-Urteil handelt; die dritte ist der Best-Effort-Build-Hinweis:
$ ./cve_2026_11374_check.py https://adssp.example.com:8888
[!] https://adssp.example.com:8888: POTENTIALLY_AFFECTED
ADSelfService Plus: AD360-integrated, CustomSSO replay path active - precondition met. Not confirmed vulnerable; verify patch level (fixed build 6529).
build: 6519 (below fixed 6529 - inconclusive: ?build= may be a stale placeholder or a hotfix)
Eine eigenständige Installation desselben Produkts, bei der der Replay-Pfad nicht aktiv ist:
$ ./cve_2026_11374_check.py https://adssp.example.com:8888
[+] https://adssp.example.com:8888: UNAFFECTED
ADSelfService Plus: standalone / not AD360-integrated (no cleanup), so the replay path isn't reachable here. Verify build >= 6529 regardless.
Scannen einer Liste mit einer ausgerichteten Zeile pro Host (--brief). Der Exit-Status ist 1, wenn ein Host POTENTIALLY_AFFECTED ist, andernfalls 0, was in Skripten praktisch ist. Die abschließende Notiz zeigt das identifizierte Produkt sowie bei einem Befund die Build-Nummer:
$ ./cve_2026_11374_check.py -f targets.txt --brief; echo "exit: $?"
POTENTIALLY_AFFECTED https://host-a:8888 ADSelfService Plus 6519
POTENTIALLY_AFFECTED http://host-b:8081 ADAudit Plus 8530
UNAFFECTED http://host-c:8365 M365 Manager Plus
UNAFFECTED https://host-d:443
INCONCLUSIVE http://host-e:8888 ADSelfService Plus
ERROR host-f:8888 timeout
exit: 1
Maschinenlesbare Ausgabe (--json). Jedes Ergebnis enthält das verdict, den zugrunde liegenden state und detail, das identifizierte product sowie – bei einem Befund – ein build-Objekt: build ist die gefundene Nummer, fixed_build der Schwellenwert für dieses Produkt, patch_hint die richtungsweisende Einschätzung (likely_patched bei oder über dem Fix-Build, andernfalls inconclusive) und note eine kurze Erklärung:
$ ./cve_2026_11374_check.py https://host-b:8081 --json
[
{
"target": "https://host-b:8081",
"state": "potentially_affected",
"detail": "ADAudit Plus: AD360-integrated, CustomSSO replay path active - precondition met ...",
"product": "ADAudit Plus",
"build": { "build": "8530", "fixed_build": "8703", "patch_hint": "inconclusive", "note": "below fixed 8703 - inconclusive: may be a hotfix" },
"verdict": "POTENTIALLY_AFFECTED"
}
]
| Bewertung | Bedeutung |
|---|---|
POTENTIALLY_AFFECTED | In AD360 integriertes, in Frage kommendes Produkt; der CustomSSO-Cookie-Replay-Pfad ist aktiv, sodass die Exploit-Voraussetzung für CVE-2026-11374 erfüllt ist. Dies ist kein bestätigtes „verwundbar“-Urteil; verifizieren Sie den Patch-Stand (siehe nächste Schritte). |
UNAFFECTED | Der Replay-Pfad ist nicht erreichbar. Möglich ist: ein eigenständiges in Frage kommendes Produkt (nicht in AD360 integriert – allerdings würde es erreichbar, wenn es später integriert wird, also prüfen Sie den Build trotzdem); ein ManageEngine-ADS-Framework-Produkt, das nicht eines der vier in Frage kommenden ist; oder gar kein in Frage kommendes Produkt in der Antwort (nicht eines der vier CVE-2026-11374-Produkte oder ein Proxy, der das Sitzungs-Cookie entfernt). |
INCONCLUSIVE | Ein HTTP 400 – wahrscheinlich die IAM-Rate-Limit-Sperre, die das Signal maskiert; nach etwa 60 s erneut versuchen. |
ERROR | Verbindungs-/Timeout-/TLS-Fehler. |
| Code | Bedeutung |
|---|---|
0 | Kein Ziel gab POTENTIALLY_AFFECTED zurück |
1 | Mindestens ein Ziel ist POTENTIALLY_AFFECTED |
2 | Nutzungsfehler (ungültige Argumente / nicht lesbare Zieldatei) |
Senden Sie ein ungültiges Ticket plus ein App-Tag an eine beliebige CustomSSO-URL (*.do):
GET /AppsHome.do
Cookie: CUSTOM_SSO_TICKET=1700000000000; CUSTOM_SSO_APP_TAG_NAME=AD360
Bei einer in AD360 integrierten Installation durchläuft die Kette ADSFilter → CustomSSOFilter → CookieSSOImpl ihren Auflösungszweig (das Tag benennt ein anderes Produkt, also appName != prodName), kann das gefälschte Ticket nicht auflösen und sendet Cookie-Aufräum-Response-Header:
Set-Cookie: CUSTOM_SSO_TICKET=removed; Max-Age=0; ...
Set-Cookie: CUSTOM_SSO_APP_NAME=removed; Max-Age=0; ...
Set-Cookie: CUSTOM_SSO_APP_TAG_NAME=removed; Max-Age=0; ...
Eine eigenständige Installation durchläuft diesen Pfad nie und sendet kein Aufräumen. Das Produkt wird anhand seines festen produktspezifischen Tomcat-Sitzungs-Cookies identifiziert (JSESSIONIDADSSP für ADSelfService Plus usw.), das bei jeder Antwort gesetzt wird. Die Prüfung stützt sich auf die Header und nicht auf den Statuscode, da ein integriertes ADSSP ein 302 zurückgibt, während ADAudit, M365 und RMP auf dieselbe Sonde mit 200 antworten.
| Sondenantwort | Bewertung |
|---|---|
| Aufräum-Header und ein bekanntes In-Scope-Produkt-Cookie | POTENTIALLY_AFFECTED |
| Produkt-Cookie, kein Aufräumen, Status ≠ 400 | UNAFFECTED (eigenständig / nicht integriert) |
| kein In-Scope-Produkt-Cookie, Status ≠ 400 | UNAFFECTED (nicht eines der vier Produkte) |
| Aufräum-Header, aber ein unbekanntes Produkt-Cookie | UNAFFECTED (ManageEngine, nicht im Scope) |
HTTP 400 | INCONCLUSIVE (wahrscheinlich die IAM-Rate-Limit-Sperre; siehe Einschränkungen) |
POTENTIALLY_AFFECTED ist nicht „bestätigt verwundbar“. Es ist die Exploit-Voraussetzung. Da der Patch diesen Codepfad nicht berührt hat, antwortet ein gepatchter Build identisch; Sie müssen den Patch-Stand also auf anderem Wege bestätigen (siehe nächste Schritte). Mehr kann ein nicht authentifizierter Beobachter nicht wissen.HTTP 400 kann eine Rate-Limit-Sperre und keine echte Antwort sein. Zoho IAM wendet eine rollierende URL-Drosselung an, die eine Quell-IP auf etwa 40 Anfragen pro 60 s begrenzt und diesen Pfad dann für ~60 s sperrt. Während einer Sperre geben Anfragen HTTP 400 zurück und das Integrationssignal ist maskiert. Das Werkzeug meldet diese als INCONCLUSIVE; versuchen Sie es von dieser IP nach etwa einer Minute erneut.UNAFFECTED gemeldet werden. Bestätigen Sie direkt, wenn Sie dort ein ManageEngine-Produkt erwarten.?v=) und M365 (?bN=) legen immer den echten Build offen; ADSSPs ?build= ist manchmal echt und manchmal ein eingefrorener Platzhalter, der unterhalb des Fix-Builds liegt. Ein ADSSP-Wert unterhalb des Fix-Builds ist daher mehrdeutig; RMP legt keinen offen. In jedem Fall deutet ein Build auf oder über dem Fix-Build stark auf „gepatcht“ hin, und darunter ist er nicht schlüssig.Wenn ein Ziel POTENTIALLY_AFFECTED zurückgibt, behandeln Sie es als exponiert und bestätigenswert. Gehen Sie dann wie folgt vor:
Bestätigen Sie den Patch-Stand direkt (das Werkzeug kann das nicht). Lesen Sie conf/product.conf (build_number) auf dem Host und vergleichen Sie sie mit dem Fix-Build für dieses Produkt (ADSelfService Plus 6529, RecoveryManager Plus 6321, M365 Manager Plus 4817, ADAudit Plus 8703). Interpretieren Sie das richtungsweisend: Ein Build auf oder über dem Fix-Build ist ein starkes Indiz dafür, dass der Host gepatcht ist, da der UUID-Fix in diesem Zweig enthalten ist. Ein Build unterhalb des Fix-Builds ist nicht schlüssig und kein Beweis für eine Verwundbarkeit, da Out-of-Band-Hotfixes und Backports den UUID-Fix anwenden können, ohne die Build-Nummer zu erhöhen; in diesem Fall verwenden Sie die Ticket-Format-Prüfung unten.
Prüfen Sie das Format des ausgestellten Tickets, wenn Sie sich anmelden können. Das Cookie CUSTOM_SSO_TICKET ist nicht HttpOnly. Nach der Authentifizierung können Sie seinen Wert also lesen: Eine 13-stellige Zahl bedeutet verwundbar, eine UUID bedeutet gepatcht. Das ist die klarste positive Prüfung.
Aktualisieren Sie jeden Host, der verwundbar ist oder bei dem Sie nicht bestätigen können, dass er gepatcht ist, auf den Fix-Build (oder später). Der Fix ersetzt das vorhersagbare Ticket durch eine zufällige UUID.
Suchen Sie nach Exploitation-Versuchen. Auf dem Host zeichnet serverOut_<date>.txt die Drosselung als Ausbrüche von Folgendem auf:
IAMSecurityException ErrorCode: URL_ROLLING_THROTTLES_LIMIT_EXCEEDED,
RequestURI: "/showLogin.cc", RemoteAddr: <source IP>
Ein Anstieg von URL_ROLLING_THROTTLES_LIMIT_EXCEEDED auf SSO-/Login-Dispatch-Pfaden von einer einzelnen Quell-IP ist ein starkes Indiz für Ticket-Brute-Forcing. Überprüfen Sie außerdem kürzlich erfolgreiche Logins und Sitzungsaktivität auf Anzeichen einer Übernahme.
Reduzieren Sie in der Zwischenzeit die Angriffsfläche. Beschränken Sie den Netzwerkzugriff auf die AD360-Suite (sie sollte nicht aus dem Internet erreichbar sein), und wenn der Replay-Pfad nicht benötigt wird, entfernt das Deaktivieren der CustomSSO-Integration die Voraussetzung vollständig.
Aktualisieren Sie das betroffene Produkt auf mindestens den Fix-Build (ADSelfService Plus 6529, RecoveryManager Plus 6321, M365 Manager Plus 4817, ADAudit Plus 8703) oder später. Der Fix ersetzt das vorhersagbare SSO-Ticket System.currentTimeMillis() durch UUID.randomUUID().
Dieser Code wird unter einer MIT-Lizenz vertrieben.
Die Verwendung dieses Werkzeugs zum Angriff auf Ziele ohne vorherige gegenseitige Zustimmung ist illegal. Es liegt in der Verantwortung des Endbenutzers, alle geltenden lokalen, Landes- und Bundesgesetze zu befolgen. Die Entwickler übernehmen keine Haftung und sind nicht verantwortlich für Missbrauch oder Schäden, die durch dieses Programm verursacht werden.