SOAP/JAX-WS ThreadLocal Authentication Bypass
Tip
Learn & practice AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
TL;DR
- Some middleware chains store the authenticated
Subject/Principalinside a staticThreadLocaland only refresh it when a proprietary SOAP header arrives. - Because WebLogic/JBoss/GlassFish recycle worker threads, dropping that header causes the last privileged
Subjectprocessed by the thread to be silently reused. - Hammer the vulnerable endpoint with header-less but well-formed SOAP bodies until a reused thread grants you the stolen administrator context.
- 2025 HID ActivID/IASP (HID-PSA-2025-002) is a real-world instance: JAX-WS handler caches a
SubjectHolderThreadLocal, letting unauthenticated SOAP calls inherit the identity set by previous console/SSP requests.
Root Cause
Handlers similar to the following only overwrite the thread-local identity when the custom header is present, so the previous request’s context survives:
public boolean handleMessage(SOAPMessageContext ctx) {
if (!outbound) {
SOAPHeader hdr = ctx.getMessage().getSOAPPart().getEnvelope().getHeader();
SOAPHeaderElement e = findHeader(hdr, subjectName);
if (e != null) {
SubjectHolder.setSubject(unmarshal(e));
}
}
return true;
}
Recon
- Enumerate the reverse proxy / routing rules to locate hidden SOAP trees that may block
?wsdlyet accept POSTs (map them alongside the flow in 80,443 - Pentesting Web Methodology). - Unpack the EAR/WAR/EJB artifacts (
unzip *.ear) and inspectapplication.xml,web.xml,@WebServiceannotations, and handler chains (e.g.,LoginHandlerChain.xml) to uncover the handler class, SOAP header QName, and the backing EJB names. - If metadata is missing, brute-force likely
ServiceName?wsdlpaths or temporarily relax lab proxies, then import any recovered WSDL into tooling such as Burp Suite Wsdler to generate baseline envelopes. - Review the handler sources for
ThreadLocalkeepers (e.g.,SubjectHolder.setSubject()) that are never cleared when the authentication header is missing or malformed.
Exploitation
- Send a valid request with the proprietary header to learn the normal response codes and any error used for invalid tokens.
- Resend the same SOAP body while omitting the header. Keep the XML well-formed and respect the required namespaces so the handler exits cleanly.
- Loop the request; when it lands on a thread that previously executed a privileged action, the reused
Subjectunlocks protected operations such as user or credential managers.
POST /ac-iasp-backend-jaxws/UserManager HTTP/1.1
Host: target
Content-Type: text/xml;charset=UTF-8
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:jax="http://jaxws.user.frontend.iasp.service.actividentity.com">
<soapenv:Header/>
<soapenv:Body>
<jax:findUserIds>
<arg0></arg0>
<arg1>spl*</arg1>
</jax:findUserIds>
</soapenv:Body>
</soapenv:Envelope>
2025 HID ActivID/IASP case study (HID-PSA-2025-002)
- Synacktiv showed the JAX-WS
LoginHandlerin ActivID 8.6–8.7 setsSubjectHolder.subjectwhen amySubjectHeaderSOAP header is present or when console/SSP traffic authenticates, but never clears it when the header is absent. - Any subsequent SOAP call lacking the header on the same worker thread inherits that cached
Subject, allowing unauthenticated creation of administrator users or credential import via endpoints such asUserManagerorCredentialManager. - Reliable exploitation pattern observed:
- Trigger an authenticated context on many threads (e.g., spam
/sspor log into/aiconsoleas admin in another browser tab). - Flood header-less SOAP bodies to
/ac-iasp-backend-jaxws/UserManageror other EJB-backed JAX-WS endpoints with high parallelism; each hit that reuses an “infected” thread executes with elevatedSubject. - Repeat until privileged responses are returned; reuse Keep-Alive connections and large worker pools to maximize thread reuse probability.
- Trigger an authenticated context on many threads (e.g., spam
- Handler and process flow highlights:
LoginHandlerChain.xml→LoginHandler.handleMessage()unmarshalsmySubjectHeaderand stores theSubjectinSubjectHolder(a staticThreadLocal).ProcessManager.triggerProcess()later injectsSubjectHolder.getSubject()into business processes, so missing headers leave stale identities intact.
- In-field PoC from the advisory uses two-step SOAP abuse: first
getUsersto leak info, thencreateUser+importCredentialto plant a rogue admin when the privileged thread hits.
Validating the Bug
- Attach JDWP (
-agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=n) or similar debugging hooks to watch theThreadLocalcontents before and after each call, confirming that an unauthenticated request inherited a prior administratorSubject. - In production appliances you can also instrument with JFR or BTrace to dump
SubjectHolder.getSubject()per request, verifying header-less reuse.
References
- Synacktiv – ActivID authentication bypass (HID-PSA-2025-002)
- HID Global – Product Security Advisory HID-PSA-2025-002 SOAP-API Authentication Bypass
- Synacktiv – ActivID administrator account takeover: the story behind HID-PSA-2025-002
- PortSwigger – Wsdler (WSDL parser) extension
Tip
Learn & practice AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.


