Apache Druid Kerberos Cookie-Signing Secret Recovery via ThreadLocalRandom Seed Inversion (CVE-2025-59390)
by Daeda1usUK · 2026-07-06
- Severity
- Critical
- CVE
- CVE-2025-59390
- Category
- crypto
- Affected product
- Apache Druid — Kerberos authenticator (druid.auth.authenticator.kerberos)
- Affected versions
- Through 34.0.0 (fixed in 35.0.0)
- Disclosed
- 2026-07-06
- Patch status
- patched
Tags
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-06 |
| Last Updated | 2026-07 |
| Author / Researcher | Daeda1usUK |
| CVE / Advisory | CVE-2025-59390 |
| Category | crypto |
| Severity | Critical |
| CVSS Score | 9.8 (CVSSv3.1: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) |
| Status | PoC |
| Tags | apache-druid, kerberos, threadlocalrandom, prng, seed-recovery, cookie-forgery, authentication-bypass, cwe-338 |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | Apache Druid — Kerberos authenticator (druid.auth.authenticator.kerberos) |
| Versions Affected | Through 34.0.0 (fixed in 35.0.0) |
| Language / Platform | C++ (PoC seed-recovery tool); target is Java (JDK 8+ ThreadLocalRandom) |
| Authentication Required | No (attacker only needs observable cookie-signature outputs) |
| Network Access Required | Yes, to obtain signed Kerberos authentication cookies from a target Druid deployment |
Summary
When Apache Druid’s Kerberos authenticator is deployed without an explicit druid.auth.authenticator.kerberos.cookieSignatureSecret, Druid falls back to generating that secret using Java’s ThreadLocalRandom, which is not cryptographically secure. Because ThreadLocalRandom’s internal 64-bit seed advances by a fixed additive constant (GAMMA = 0x9e3779b97f4a7c15) each call and is squashed through a reversible 64-bit “mix” (splitmix64-style) finalizer before being truncated to a 32-bit output, an attacker who observes a handful of successive 32-bit outputs from the same generator instance can mathematically invert the finalizer and recover the generator’s internal seed. Once the seed (and therefore the entire output stream, forwards and backwards) is known, the attacker can reconstruct or predict the fallback cookie-signing secret and forge valid Kerberos authentication cookies, enabling authentication bypass. The included PoC is a from-scratch demonstration of the seed-recovery mathematics, not a network exploit against a live Druid instance.
Vulnerability Details
Root Cause
ThreadLocalRandom.nextInt()/nextLong() derives outputs by taking the generator’s internal seed, advancing it by the constant GAMMA (mod 2^64), and passing the result through mix32/mix64 — a bijective (invertible) mixing function built from XOR-shift and odd (thus multiplicatively invertible modulo 2^64) constant multiplications:
z = (z ^ (z >> 33)) * 0xff51afd7ed558ccd (mod 2^64)
z = (z ^ (z >> 33)) * 0xc4ceb9fe1a85ec53 (mod 2^64)
return (int32)(z >> 32)
Because every step is reversible (the multiplicative constants are odd and thus units in the ring Z/2^64Z, and the XOR-shift steps can be undone by re-applying the shift/XOR), observing a small number of consecutive outputs is enough to invert the entire construction and recover the internal seed — this is CWE-338 (Use of a Cryptographically Weak PRNG). Since Druid uses this non-CSPRNG to generate the Kerberos cookie-signing secret whenever the operator omits cookieSignatureSecret from configuration, the secret itself becomes recoverable via the same seed-inversion attack, and each Druid process/node generates its own independent (and independently crackable) fallback secret.
Attack Vector
- Identify a target Apache Druid deployment (≤ 34.0.0) whose Kerberos authenticator does not have
druid.auth.authenticator.kerberos.cookieSignatureSecretexplicitly configured, so it relies on theThreadLocalRandom-derived fallback secret. - Collect a small number (as few as 2, reliably 3) of successive 32-bit outputs produced by the vulnerable
ThreadLocalRandominstance during secret generation/signing, e.g. via cookie material, timing/behavior, or other Druid-exposed randomness derived from the same generator stream. - Run the seed-inversion routine (see
ThreadLocalRandom_Inverse_POC.cpp): place the first known output in the high 32 bits of a 64-bit candidate, brute-force the low 32 bits (2^32 iterations), invert both multiplicative mix steps and both XOR-shift steps to reconstruct a candidate pre-mix value, then verify the candidate by re-deriving the 2nd (and 3rd, to eliminate collisions) known output and comparing. - Once the seed is recovered, walk the generator’s output stream forward/backward by adding/subtracting
GAMMAto reconstruct the actual cookie-signing secret Druid derived from it. - Use the recovered secret to forge a validly-signed Kerberos authentication cookie and bypass authentication on the target Druid cluster.
Impact
Full authentication bypass against Apache Druid’s Kerberos authenticator: an attacker who can observe enough PRNG output to recover the seed can forge signed authentication cookies and impersonate any authenticated principal, without needing to compromise Kerberos itself. Distributed/multi-node Druid clusters are additionally affected by cross-node signature-verification failures because each node independently derives its own (crackable) fallback secret.
Environment / Lab Setup
Target: Apache Druid (through 34.0.0) with Kerberos authenticator enabled and
druid.auth.authenticator.kerberos.cookieSignatureSecret left unset
Attacker: Any machine capable of compiling/running the C++ seed-recovery PoC
(built/tested on x86_64-pc-linux-gnu, GCC 14.2.1)
Proof of Concept
PoC Script
See
ThreadLocalRandom_Inverse_POC.cppin this folder (mirrored from the upstream repo’sThreadLocalRandom Inverse POCfile).
| |
The PoC hardcodes a demonstration 64-bit threadSeed, generates three successive mix32 outputs (T1, T2, T3) exactly as ThreadLocalRandom would, then brute-forces the missing 32 bits of the first output, inverts both odd-constant multiplications and both XOR-shift steps to recover a seed candidate, and confirms it by checking that advancing by GAMMA and 2*GAMMA reproduces T2 and T3. On success it prints the recovered seed in hex, demonstrating that knowledge of a few ThreadLocalRandom outputs is sufficient to fully recover the generator’s internal state — the same technique applicable to recovering Druid’s fallback Kerberos cookie-signing secret.
Detection & Indicators of Compromise
Signs of compromise:
druid.auth.authenticator.kerberos.cookieSignatureSecretabsent from Druid configuration- Unexplained successful authentications or forged-looking session cookies against Druid’s Kerberos authenticator
- Inconsistent authentication behavior across Druid brokers/nodes in the same cluster (a symptom of the same root cause — independently generated fallback secrets)
Remediation
| Action | Detail |
|---|---|
| Primary fix | Upgrade to Apache Druid 35.0.0 or later, which makes druid.auth.authenticator.kerberos.cookieSignatureSecret mandatory and refuses to start without it |
| Interim mitigation | Explicitly configure a strong, random cookieSignatureSecret for the Kerberos authenticator on every Druid node/process before 35.0.0 can be deployed |
References
Notes
Mirrored from https://github.com/Daeda1usUK/CVE-2025-59390- on 2026-07-06. The upstream repository’s original README (renamed here to upstream-README.md) contains the vendor advisory text; the source file ThreadLocalRandom Inverse POC was copied as ThreadLocalRandom_Inverse_POC.cpp for clarity (identical content, extension added since the original filename had none).
| |