Cabeçalho penumbroso

Decodificação de assinatura web json: Guia de um engenheiro de segurança para não ser dominado

O controle de acesso moderno vive e morre em cima de tokens baseados em JSON. Quando você inspeciona um token de acesso OAuth, um token de ID OpenID Connect ou uma sessão de API assinada, geralmente está vendo um Assinatura da Web JSON (JWS) estrutura. Os mecanismos de pesquisa enviarão muitas pessoas para ferramentas de "decodificação de assinatura da Web json" que parecem transformar magicamente cadeias de caracteres opacas em JSON legível.

Para os engenheiros de segurança ofensivos e defensivos, essa é apenas a primeira etapa. A decodificação de um JWS informa o que o token reivindicaçõesEle não informa se essas alegações são confiáveis, se a assinatura é aplicada corretamente ou se a implementação já está em um banco de dados CVE.

Este artigo explica o que realmente acontece quando você executa a decodificação da assinatura web json, como as vulnerabilidades do mundo real surgiram de erros sutis em torno da verificação do JWS e como criar um fluxo de trabalho repetível que se encaixa em um pipeline de pentest automatizado e aumentado por IA.

Dominando a decodificação de assinaturas da Web JSON: Análise avançada, explorações de CVE e defesa de IA Penligent
Decodificação de assinatura web json: Guia de um engenheiro de segurança para não ser dominado

O que realmente é uma assinatura da Web JSON

De acordo com a especificação JWS, uma assinatura da Web JSON representa um conteúdo arbitrário protegido por uma assinatura digital ou um MAC, usando estruturas baseadas em JSON. Ela fornece integridade e autenticidade para uma sequência de bytes, independentemente do que esses bytes representam. (Rastreador de dados da IETF)

Na prática, na maioria das vezes, essa sequência de bytes é um objeto JSON de reivindicações - que é o que chamamos de JSON Web Token (JWT). O JWS em si é definido na [RFC 7515], enquanto o JWT está em um padrão irmão que se concentra em como essas declarações são estruturadas e interpretadas. (Médio)

O formulário compacto familiar tem a seguinte aparência:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0Iiwic2NvcGUiOlsicmVhZCIsIndyaXRlIl0sImV4cCI6MTczNDkxMjAwMH0.
ODU5Y...signature-bytes-here...

Conceitualmente, são três partes codificadas em Base64URL unidas por pontos:

ParteNomeDescrição
1º pedaçoCabeçalhoJSON descrevendo o algoritmo, dicas de chave (garoto, jwk, x5u), tipo de token
2º pedaçoCarga útilReivindicações: assunto, escopos, emissor, expiração, etc.
3º pedaçoAssinaturaSaída de assinatura base64url(header) + "." + base64url(payload)

Uma operação de decodificação de assinatura web json, seja ela realizada por uma ferramenta on-line ou em seus próprios scripts, apenas reverte a codificação Base64URL das duas primeiras partes e imprime o JSON. Ela faz não provar que a assinatura é válida, a menos que a ferramenta realize explicitamente a verificação com uma chave conhecida e um conjunto de algoritmos restritos. (desenvolvedor.pingidentity.com)

Como as ferramentas de decodificação de assinaturas web json realmente funcionam

A maioria dos decodificadores JWT/JWS, como as ferramentas comuns de desenvolvedor usadas em navegadores ou playgrounds baseados na Web, implementa o mesmo pipeline mínimo:

  1. Dividir os pontos em três segmentos.
  2. Base64URL-decodifica os dois primeiros segmentos.
  3. Analise-os como JSON para cabeçalho e carga útil.
  4. Se uma chave de verificação for fornecida, recalcule a assinatura usando o algoritmo anunciado no cabeçalho e compare com o terceiro segmento. (desenvolvedor.pingidentity.com)

Do ponto de vista de um engenheiro de segurança, as etapas 1 a 3 são suficientemente seguras para análise off-line; a etapa 4 é onde a maioria das vulnerabilidades se esconde.

Trecho mínimo de decodificação em Python

Aqui está um trecho deliberadamente simples de decodificação somente em Python, útil quando você está pesquisando os tokens capturados durante um pentest:

importar base64
importar json

def b64url_decode(data: str) -> bytes:
    # Manuseio do preenchimento do JWT
    padding = '=' * (-len(data) % 4)
    return base64.urlsafe_b64decode(data + padding)

def decode_jws(token: str):
    header_b64, payload_b64, signature_b64 = token.split('.')
    header = json.loads(b64url_decode(header_b64))
    payload = json.loads(b64url_decode(payload_b64))
    return header, payload, signature_b64

jws = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...."
h, p, sig = decode_jws(jws)
print("Header:", h)
print("Carga útil:", p)

Observe que essa função nunca chama uma rotina de verificação; ele está apenas decodificando. Em geral, é exatamente isso que você deseja ao fazer a triagem de um novo alvo: inspeção rápida com zero suposições criptográficas.

Trecho de Node.js com verificação

Quando você passa da decodificação para a verificação, todos os detalhes são importantes:

import jwt from "jsonwebtoken";
import fs from "fs";

const publicKey = fs.readFileSync("public.pem", "utf-8");

função verifyJws(token) {
  // Crítico: bloquear explicitamente os algoritmos suportados
  return jwt.verify(token, publicKey, {
    algorithms: ["RS256"],
  });
}

Se você omitir o algoritmos whitelist e deixar a biblioteca inferir o algoritmo a partir do cabeçalho não confiável, você está reproduzindo exatamente as condições que levaram a várias CVEs do JWT.

A decodificação é inofensiva, confiando que os dados decodificados não são

Um padrão aparece repetidamente em relatórios de incidentes e CVEs: os desenvolvedores tratam decodificado Dados JWT / JWS como se já fossem verificado. Vários artigos modernos sobre os problemas de segurança do JWT enfatizam que a decodificação do Base64URL é trivial e que o sigilo de um token não vem do fato de "ser difícil de ler". (PortSwigger)

Três classes recorrentes de bugs se destacam:

  1. O campo "alg" é tratado como uma fonte de verdade. Se o seu código de verificação extrair o algoritmo a ser usado do cabeçalho, que é controlado pelo usuário, você estará convidando a ataques de confusão de algoritmos.
  2. O nenhum é aceito acidentalmente. Historicamente, o padrão JWT exigia suporte para "nenhum" como um algoritmo que significa "sem proteção de integridade". A análise clássica do Auth0 mostrou como várias bibliotecas honraram ingenuamente essa escolha, permitindo que tokens não assinados passassem por verificações. (Auth0)
  3. Dicas importantes (garoto, incorporado jwk, x5u) não são validados. Tanto a RFC do JWS quanto os guias de teste destacam que permitir que o token escolha sua própria chave de verificação sem uma lista branca rigorosa permite que os invasores contrabandeiem chaves públicas arbitrárias ou forcem pesquisas de chaves em locais controlados por invasores. (PortSwigger)

Em outras palavras, a decodificação de assinatura web json oferece observabilidade. Ela não lhe dá confiança. Essa distinção é o que separa uma configuração de depuração segura de um cabeçalho de execução de código remoto.

Quando a decodificação encontra os CVEs: modos de falha concretos do JWS

Para entender como as coisas podem dar errado quando a decodificação e a verificação são combinadas, vale a pena examinar alguns CVEs que giram em torno da lógica de verificação do JWS.

CVE-2015-9235 - Confusão de chaves HS/RS em jsonwebtoken

No Node.js jsonwebtoken Antes da versão 4.2.2, um erro de projeto tornava possível contornar a verificação de assinatura ao mudar de um algoritmo assimétrico (famílias RS256 / ES256) para um simétrico (HS256). O caminho do código vulnerável reutilizava o mesmo valor - a chave pública RSA - como o segredo HMAC quando o invasor alterava o alg cabeçalho para HS256. (nvd.nist.gov)

Do ponto de vista do invasor, o fluxo de trabalho é simples:

  1. Decodifique o token original e inspecione o cabeçalho.
  2. Extraia a chave pública do servidor (por exemplo, de um ponto de extremidade ou certificado JWK).
  3. Forjar um novo token com um cabeçalho HS256, usando a chave pública como um segredo HMAC.
  4. Apresentar o token forjado; o servidor o trata erroneamente como válido.

Aqui, a decodificação forneceu ao invasor a matéria-prima (cabeçalho, algoritmo, locais-chave); a lógica de verificação fez o resto.

CVE-2018-1000531 - aceitação do nenhum algoritmo

Essa vulnerabilidade rastreou casos em que as bibliotecas aceitavam tokens assinados com o nenhum tratando-os efetivamente como válidos, apesar de não terem nenhuma assinatura. O padrão de exploração é quase comicamente simples: alterar "alg": "RS256" para "alg": "none"remova a parte da assinatura e veja se a API de destino aceita o token. (0xn3va.gitbook.io)

CVE-2023-48238 - Confusão de algoritmo em json-web-token

O json-web-token para JavaScript foi considerada vulnerável a outro ataque de confusão de algoritmos. O principal problema: o algoritmo usado para verificação foi retirado diretamente do cabeçalho do token, que, naquele momento, não era confiável. Isso permitiu que os invasores escolhessem um algoritmo mais conveniente do que aquele que o operador do servidor achava que estava aplicando. (nvd.nist.gov)

CVE-2024-54150 - confusão em uma implementação de JWT em C

Mais recentemente, o cjwt A biblioteca C sofreu uma falha crítica de confusão de algoritmos, agora rastreada como CVE-2024-54150. Uma revisão de código revelou que a implementação não distinguia corretamente os algoritmos baseados em HMAC dos algoritmos RSA / EC ao verificar os tokens, abrindo novamente a porta para a confusão de chaves. (nvd.nist.gov)

Esses casos não são curiosidades históricas; eles mostram que, mesmo em 2023-2024, erros sutis no caminho de verificação do JWS continuam sendo uma fonte ativa de vulnerabilidades graves.

Para mantê-los em ordem durante uma avaliação, muitas equipes criam uma folha de dicas como a seguinte:

CVECausa raizTema de ataqueLição principal
2015-9235Confusão de chaves HS vs RSConfusão de algoritmosAplicar a lista branca de algoritmos; chaves separadas por algoritmo
2018-1000531nenhum aceito como assinaturaAssinatura nulaNunca permita nenhum em produção
2023-48238Algoritmo de JWT não confiávelConfusão de algoritmosIgnorar cabeçalho algusar somente a configuração do lado do servidor
2024-54150Sem distinção entre HS e RS/ECConfusão de algoritmos (C)Tratar o MAC e a assinatura como caminhos fundamentalmente diferentes

Durante um exercício de decodificação de assinatura web json, mapear explicitamente os tokens observados em relação a essa tabela é uma maneira rápida de identificar quais playbooks você deve tentar.

Um fluxo de trabalho prático de decodificação inicial para pentesters

Quando estiver avaliando uma API ou um sistema SSO que dependa do JWS, um fluxo de trabalho disciplinado de decodificação em primeiro lugar evita pontos cegos e suposições ruidosas.

  1. Capturar e catalogar tokens. Use o proxy ou o conjunto de testes para capturar todos os tokens: Cabeçalhos de autorização, cookies, parâmetros de URL. Agrupe-os por emissor e público-alvo.
  2. Decodificar o cabeçalho e a carga útil off-line. Use scripts como o trecho de Python acima ou jwt_tool apenas para decodificação; nunca confie em um serviço on-line para tokens confidenciais em compromissos reais. (GitHub)
  3. Crie uma matriz de cabeçalho. Para cada família de tokens, registre alg, garoto, presença de jku / jwk / x5ue quaisquer campos de cabeçalho personalizados. É aqui que a orientação do PortSwigger sobre JWKs incorporados e chaves fornecidas por invasores se torna diretamente acionável. (PortSwigger)
  4. Inferir padrões de gerenciamento de chaves. Com base em campos de cabeçalho e pontos de extremidade conhecidos (/.well-known/jwks.json), faça um esboço de como as chaves são distribuídas e giradas.
  5. Teste para classes conhecidas de bugs.
    • Experimente a assinatura nula / nenhum se a biblioteca ou a pilha as suportar historicamente.
    • Realizar tentativas de confusão de chaves HS/RS onde os algs não estão bloqueados.
    • Sonda garoto para o comportamento de travessia de diretório ou inclusão de arquivo.
    • Tentativa de injeção de JWK incorporada onde a especificação permite, mas a implementação pode não restringi-la.
  6. Então, e somente então, passe para as tentativas de exploração total. Nesse estágio, você deve saber exatamente o que está tentando provar, em vez de simplesmente lançar cargas úteis em uma caixa preta.

Nesse processo, a decodificação da assinatura web json é a camada de observabilidade para o restante de sua metodologia de ataque.

Integração da decodificação de assinatura web json em um pipeline de pentest orientado por IA (Penligent.ai)

A análise manual funciona para um único envolvimento; em escala, as equipes precisam de algo mais próximo de um pipeline. Uma plataforma assistida por IA como a Penligent.ai pode incorporar a decodificação de assinaturas web json diretamente em suas fases de reconhecimento e exploração.

Em uma configuração típica, a plataforma ingere o tráfego HTTP de uma sandbox de navegador ou de um proxy, extrai automaticamente os tokens candidatos e executa a decodificação JWS em massa nos cabeçalhos e nas cargas úteis. Em seguida, o agente de IA agrupa os tokens por emissor, algoritmo e dicas de chave, procurando anomalias, como diversidade inesperada de algoritmos, estranheza, etc. garoto codificações ou combinações incomuns de reivindicações.

Depois que essa linha de base é criada, o mecanismo de ataque da Penligent pode executar automaticamente playbooks de JWT/JWS com curadoria: tentativas de assinatura nula, cenários de confusão de algoritmos, JWK incorporado ou jku abuso e sondas conhecidas inspiradas em CVE. Em vez de deixar essas verificações na memória de um ser humano, o sistema as trata como casos de teste repetíveis que são executados em todos os alvos, alimentando os resultados em uma lista de riscos com base em evidências e em um relatório legível por máquina.

Para os engenheiros de segurança que estão criando um recurso interno de "equipe vermelha de IA", conectar a decodificação de assinatura da Web json a esse pipeline automatizado costuma ser uma das peças de maior aproveitamento do encanamento de baixo nível.

Lista de verificação de proteção e leitura adicional

Se o seu trabalho diário envolve a emissão ou verificação de tokens JWS/JWT, você pode tratar isso como uma barra mínima:

  • Aplicar uma lista rigorosa de algoritmos permitidos no lado do servidor; nunca ler alg de um token não confiável como política.
  • Separe as chaves entre assinaturas assimétricas e segredos HMAC; nunca reutilize uma chave pública RSA como uma chave HMAC.
  • Desativar permanentemente nenhum em bibliotecas de produção e rejeitar qualquer token que o anuncie.
  • Tratar todos os campos de cabeçalho (garoto, jku, jwk, x5u) como entrada não confiável e validá-los em relação a um conjunto de chaves fixadas ou lista de permissões.
  • Mantenha suas bibliotecas JWT corrigidas; analise periodicamente CVEs como CVE-2015-9235, CVE-2018-1000531, CVE-2023-48238 e CVE-2024-54150 para ver se sua pilha foi afetada. (Laboratório Swissky)
  • Adicione testes de regressão que exercitem explicitamente cenários de não-confusão/confusão de algoritmo.

Para aprofundamentos mais profundos, vale a pena marcar essas referências em inglês e criar links a partir de seus runbooks internos:

  • O núcleo [JSON Web Signature (JWS) RFC 7515] da IETF. (Rastreador de dados da IETF)
  • Seção da OWASP sobre [Testing JSON Web Tokens] no Guia de teste de segurança da Web. (Fundação OWASP)
  • Laboratórios da PortSwigger's Web Security Academy sobre [ataques JWT] e [confusão de algoritmos]. (PortSwigger)
  • O clássico artigo de Tim McLean sobre o Auth0 sobre [vulnerabilidades críticas nas bibliotecas JSON Web Token]. (Auth0)
  • O rascunho em evolução do [JWT Best Current Practices] no grupo de trabalho IETF OAuth. (IETF)

Usada corretamente, a decodificação de assinatura web json não é apenas uma conveniência de depuração; é a porta de entrada para uma maneira sistemática de entender, atacar e fortalecer a estrutura de autenticação dos seus aplicativos.

Compartilhe a postagem:
Publicações relacionadas