
Security Assertion Markup Language (SAML) é um padrão aberto para troca de dados de autenticação e autorização entre partes em um sistema de identidade federada. Ele permite o single sign-on (SSO) entre domínios. Os principais componentes são:
Em um fluxo SAML típico, o SP redireciona o usuário para o IdP para autenticação. O IdP retorna uma resposta SAML assinada contendo asserções sobre o usuário (ex.: e-mail, nome). O SP valida a assinatura e provisiona ou autentica o usuário.
CVE-2021-21239 é uma vulnerabilidade de bypass na validação de assinaturas na biblioteca pysaml2 (versões <6.5.0), usada pelo Redash <=10.1.0 para SAML SSO. Em um nível alto, ela permite que um atacante forje uma resposta SAML com uma chave pública incorporada arbitrária, possibilitando a suplantação de usuários e escalonamento de privilégios por meio do provisionamento just-in-time (JIT).
A vulnerabilidade decorre de como o pysaml2 invoca o xmlsec1 para verificar assinaturas SAML. O Xmlsec1, por padrão, prefere chaves públicas incorporadas no <ds:KeyInfo> da resposta SAML em vez do certificado configurado do IdP. Um atacante pode criar uma resposta SAML com um par de chaves RSA gerado por ele, incorporar a chave pública em <ds:RSAKeyValue> e assinar a asserção com a chave privada. Como o pysaml2 não restringe o xmlsec1 a utilizar apenas o certificado confiável do IdP, a assinatura forjada é considerada válida, permitindo que o atacante entre como qualquer usuário (ex.: admin) e obtenha os maiores privilégios.
No nível de código, a vulnerabilidade existe no sigver.py do pysaml2 (função check_signature). A lista de comandos do xmlsec1 não inclui a opção --enabled-key-data raw-x509-cert, permitindo que o xmlsec1 use chaves incorporadas não confiáveis:
com_list = [
self.xmlsec, '--verify', '--enabled-reference-uris', 'empty,same-doc',
'--pubkey-cert-pem', cert_file_name,
'--id-attr:%s' % id_attr, node_name,
'--node-id', nodeid, '--output', output_file_name, xml_file_name
]
Isso permite ataques em que o atacante modifica o e-mail em <saml:NameID> para suplantar qualquer usuário, aproveitando o provisionamento JIT.
Para testar o exploit, uma instância local do Redash (v10.1.0 ou anterior) é iniciada usando Docker Compose. A configuração envolve definir o SAML SSO com o IdP do Google:
Essa configuração permite testar a resposta SAML forjada enviada por meio de um script Python ou Burp Suite, verificando o escalonamento de privilégios.
A vulnerabilidade surge porque a invocação do xmlsec1 pelo pysaml2 permite que chaves incorporadas sejam usadas para verificação, contornando o certificado confiável do IdP. Um atacante gera um par de chaves RSA, cria uma resposta SAML com a chave pública em <ds:RSAKeyValue>, modifica atributos (ex.: e-mail para o do admin) e assina a asserção. O Xmlsec1 verifica usando a chave incorporada, considerando-a válida.
A correção foi implementada no pysaml2 v6.5.0 (commit inicial em 17 de janeiro de 2021) em src/saml2/sigver.py. A lista de comandos do xmlsec1 foi atualizada para incluir --enabled-key-data raw-x509-cert, restringindo a verificação ao certificado configurado do IdP:
com_list = [
self.xmlsec, '--verify', '--enabled-reference-uris', 'empty,same-doc',
'--pubkey-cert-pem', cert_file_name,
'--enabled-key-data', 'raw-x509-cert',
'--id-attr:%s' % id_attr, node_name,
'--node-id', nodeid, '--output', output_file_name, xml_file_name
]
Isso impõe a validação da cadeia de confiança, impedindo o uso de chaves incorporadas. O Redash corrigiu isso atualizando o pysaml2 em versões posteriores (ex.: v11+). As versões vulneráveis não usavam --insecure; o bug era a opção de restrição ausente.
O código do exploit está implementado no cve-2021-21239.py. Este script Python automatiza o processo de forjar uma resposta SAML para explorar a CVE-2021-21239 no Redash <=10.1.0, permitindo suplantação de usuários e escalonamento de privilégios via provisionamento JIT. O exploit visa o IdP SAML do Google Workspace, mas o ataque foi testado com outros IdPs (keycloak). O script executa as seguintes etapas:
email="[email protected]").idpid do endpoint de login SAML do Redash se não for fornecido, garantindo compatibilidade com a configuração do alvo.SAMLResponseTempalte.xml) com espaços reservados para e-mail, nomes, carimbos de data/hora e ID da asserção. Carimbos de data/hora UTC dinâmicos são gerados com uma janela de validade de 5 minutos para passar na validação do Redash.xmlsec para assinar o elemento <saml:Assertion> com RSA-SHA256, incorporando a chave pública em <ds:RSAKeyValue> para explorar a vulnerabilidade./saml/callback?org_slug=default).Explorar a CVE-2021-21239 exigiu forjar uma resposta SAML que o Redash aceitasse via provisionamento JIT. Principais dificuldades e contornos:
<ds:RSAKeyValue>, assinando com a chave privada.xmlsec1 funcionaram, mas a biblioteca Python xmlsec causava incompatibilidades de digest devido a problemas de espaços em branco/canonicalização. Contornado ao serializar o XML em uma única linha (etree.tostring(..., pretty_print=False)) antes de assinar.NotOnOrAfter muito no futuro causava rejeição; contornado usando carimbos de data/hora UTC dinâmicos com validade de 5 minutos.SAMLResponse duas vezes, causando falhas de parsing; contornado enviando dados de formulário brutos.Esses desafios destacam a necessidade de manipulação precisa de XML e configuração de ambiente para explorar a vulnerabilidade com eficácia. O código do exploit fornecido demonstra isso com sucesso, forjando uma resposta SAML para suplantar usuários e obter acesso.