SOAP/JAX-WS ThreadLocal Authentication Bypass

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks

TL;DR

  • Algumas cadeias de middleware armazenam o Subject/Principal autenticado dentro de um ThreadLocal estático e só o atualizam quando um cabeçalho SOAP proprietário chega.
  • Como o WebLogic/JBoss/GlassFish reciclam worker threads, omitir esse cabeçalho faz com que o último Subject privilegiado processado pela thread seja reutilizado silenciosamente.
  • Sobrecarregue o endpoint vulnerável com bodies SOAP bem-formados mas sem o cabeçalho até que uma thread reutilizada lhe conceda o contexto de administrador roubado.
  • 2025 HID ActivID/IASP (HID-PSA-2025-002) é um caso real: o handler JAX-WS faz cache de um SubjectHolder ThreadLocal, permitindo que chamadas SOAP não autenticadas herdem a identidade definida por solicitações anteriores do console/SSP.

Causa raiz

Handlers similares ao seguinte apenas sobrescrevem a identidade do ThreadLocal quando o cabeçalho customizado está presente, então o contexto da requisição anterior persiste:

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;
}

Reconhecimento

  1. Enumere as regras de reverse proxy / roteamento para localizar árvores SOAP ocultas que podem bloquear ?wsdl mas aceitar POSTs (mapeie-as junto ao fluxo em 80,443 - Pentesting Web Methodology).
  2. Descompacte os artefatos EAR/WAR/EJB (unzip *.ear) e inspecione application.xml, web.xml, anotações @WebService e handler chains (por exemplo, LoginHandlerChain.xml) para descobrir a classe handler, o QName do cabeçalho SOAP e os nomes dos EJBs de suporte.
  3. Se os metadados estiverem ausentes, faça brute-force em prováveis caminhos ServiceName?wsdl ou relaxe temporariamente proxies de laboratório, então importe qualquer WSDL recuperado em tooling como Burp Suite Wsdler para gerar envelopes base.
  4. Revise as fontes dos handlers em busca de variáveis ThreadLocal (por exemplo, SubjectHolder.setSubject()) que nunca são limpadas quando o cabeçalho de autenticação está ausente ou malformado.

Exploração

  1. Envie uma requisição válida com o cabeçalho proprietário para descobrir os códigos de resposta normais e qualquer erro usado para tokens inválidos.
  2. Reenvie o mesmo corpo SOAP omitindo o cabeçalho. Mantenha o XML bem-formado e respeite os namespaces exigidos para que o handler termine corretamente.
  3. Faça um loop da requisição; quando ela cair em uma thread que executou anteriormente uma ação privilegiada, o reutilizado Subject desbloqueia operações protegidas como gerenciadores de usuários ou credenciais.
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 Estudo de caso HID ActivID/IASP (HID-PSA-2025-002)

  • Synacktiv mostrou que o JAX-WS LoginHandler no ActivID 8.6–8.7 define SubjectHolder.subject quando um cabeçalho SOAP mySubjectHeader está presente ou quando o tráfego do console/SSP autentica, mas nunca o limpa quando o header está ausente.
  • Qualquer chamada SOAP subsequente sem o header na mesma worker thread herda esse Subject em cache, permitindo a criação não autenticada de usuários administrador ou importação de credenciais via endpoints como UserManager ou CredentialManager.
  • Padrão de exploração confiável observado:
  1. Provocar um contexto autenticado em muitas threads (por exemplo, spam /ssp ou logar no /aiconsole como admin em outra aba do navegador).
  2. Enviar em massa corpos SOAP sem header para /ac-iasp-backend-jaxws/UserManager ou outros endpoints JAX-WS com EJB de forma altamente paralela; cada requisição que reutiliza uma thread “infectada” executa com Subject elevado.
  3. Repetir até que respostas privilegiadas sejam retornadas; reutilizar conexões Keep-Alive e pools de workers grandes para maximizar a probabilidade de reuso de threads.
  • Destaques do handler e do fluxo de processo:
  • LoginHandlerChain.xmlLoginHandler.handleMessage() desserializa mySubjectHeader e armazena o Subject em SubjectHolder (um ThreadLocal estático).
  • ProcessManager.triggerProcess() injeta posteriormente SubjectHolder.getSubject() em processos de negócio, então headers ausentes deixam identidades obsoletas intactas.
  • O PoC em campo do advisory usa um abuso SOAP em duas etapas: primeiro getUsers para leak info, depois createUser + importCredential para plantar um administrador malicioso quando a thread privilegiada for atingida.

Validando o Bug

  • Anexar JDWP (-agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=n) ou ganchos de debug similares para observar o conteúdo do ThreadLocal antes e depois de cada chamada, confirmando que uma requisição não autenticada herdou um Subject de administrador anterior.
  • Em appliances de produção você também pode instrumentar com JFR ou BTrace para despejar SubjectHolder.getSubject() por requisição, verificando o reuso sem header.

References

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks