
CVE-2026-11374-check — Updated!
Detection script for CVE-2026-11374
CVE-2026-11374 ManageEngine AD360 Precondition Detection Script
A detection script for the exploit precondition of CVE-2026-11374, a predictable SSO-ticket
flaw that leads to unauthenticated account takeover across the ManageEngine AD360 suite. The
four in-scope products share the ManageEngineADSFramework:
| Product | Affected build | Fixed build |
|---|---|---|
| ADSelfService Plus | ≤ 6528 | 6529 |
| RecoveryManager Plus | ≤ 6320 | 6321 |
| M365 Manager Plus | ≤ 4816 | 4817 |
| ADAudit Plus | ≤ 8702 | 8703 |
In affected builds the SSO ticket is just System.currentTimeMillis() (a predictable timestamp) sampled at the victim's
login, so it can be replayed through the CUSTOM_SSO_TICKET cookie to hijack that session. The
fix replaces the ticket with UUID.randomUUID() (a sufficiently random identifier). The replay path is only reachable when the
product is AD360-integrated: ADSFilter gates it on isProductIntegrated(). That gate is the
precondition this tool checks for.
NOTE: this detector confirms the precondition, not the vulnerability itself. A
POTENTIALLY_AFFECTEDresult is not a confirmed-vulnerable verdict — see below for more info.
Is it safe to run?
Yes. It's built for production and assessment use.
- Nothing is exploited. The probe sends an invalid SSO ticket (
1700000000000, a millisecond value far enough in the past that it can never be cache-resident), so no session is ever recovered. The server just tells us to clear the cookies we sent. - No target state changes. Every request is a plain
GET, and the only cookies affected are the throwaway ones the tool sends. - No brute forcing or session resolution. The tool does not attempt the active timestamp-ticket resolution that would prove exploitability; that's exploitation rather than detection, and it's out of scope here (see Limitations).
What this can and cannot tell you
CVE-2026-11374's patch changed only how the ticket is generated (milliseconds to UUID); it did not change the cookie-replay path this probe exercises. As a result, a patched install responds byte-for-byte identically to a vulnerable one for any unauthenticated request.
What the tool can do, unauthenticated and non-destructively:
- Confirm that a reachable in-scope product has the CustomSSO cookie-replay path active (that is, it is AD360-integrated), which is the CVE-2026-11374 exploit precondition.
- Identify which of the four products it is, from the per-product session cookie.
- Make a best-effort read of an asset build number as a hint. This is available on ADSelfService Plus, ADAudit Plus, and M365 Manager Plus; unavailable on RecoveryManager Plus.
What it can't do:
- Tell vulnerable from patched. There is no safe, passive, unauthenticated signal for it. A
POTENTIALLY_AFFECTEDresult means the precondition is met and you should go verify the patch level, not that the host is confirmed vulnerable. - Confirm exploitability. Proving a host is actually exploitable requires observing a minted
ticket's format (a 13-digit number is vulnerable, a UUID is patched, both of which need
authenticated or on-host visibility), reading
conf/product.conflocally, or actively resolving a live ticket (real exploitation, intentionally not implemented here). - Fully trust a below-fixed ADSelfService Plus build number. ADSSP's
?build=is sometimes the real build and sometimes a frozen placeholder that reads below the fixed build, so a below-fixed value is ambiguous and the tool marks it inconclusive. A value at or above the fixed build is still a trustworthy patched signal, since the placeholder is always too low to reach it.
Requirements
- Python 3.7+ and the
requestslibrary. Install withpip install requests.
Usage
# 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
Default ports differ per product (ADSelfService Plus 8888, ADAudit Plus 8081, M365 Manager Plus
8365, RecoveryManager Plus 8090), so pass a URL or host:port. A bare host defaults to 8888.
Options
| Flag | Description |
|---|---|
targets | One or more host, host:port, or https://host:port |
-f, --targets-file FILE | Read targets from a file (one per line; # comments) |
--brief | Single aligned line per target, good for scanning many hosts |
--json | Emit structured JSON results |
--timeout SECS | Per-request timeout (default: 15) |
--no-build | Skip the extra build-number request on a positive finding |
--no-color | Disable coloured output (also honours NO_COLOR and non-TTY) |
Examples
An AD360-integrated console (verbose, the default). The second line spells out that this is the precondition and not a vulnerable verdict; the third is the best-effort build hint:
$ ./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)
A standalone install of the same product, where the replay path isn't active:
$ ./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.
Scanning a list with one aligned line per host (--brief). Exit status is 1 if any host is
POTENTIALLY_AFFECTED, otherwise 0, which is handy in scripts. The trailing note shows the
identified product, plus the build number on a finding:
$ ./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
Machine-readable output (--json). Each result carries the verdict, the state and detail
behind it, the identified product, and — on a finding — a build object: build is the number
found, fixed_build the threshold for that product, patch_hint the directional call
(likely_patched at or above the fixed build, otherwise inconclusive), and note a short
explanation:
$ ./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"
}
]