Como Contornar a Autenticação SAML SSO

Imagine poder entrar em qualquer conta online sem precisar de senha. Parece filme de espião, certo? Mas, acredite, uma falha grave no ruby-saml, uma biblioteca usada para autenticação em diversos sites, permitia exatamente isso. Hackers poderiam usar uma assinatura digital roubada para se passar por qualquer usuário. Essa brecha, explorada por pesquisadores, forçou uma atualização urgente para proteger seus dados. Quer saber como essa história de bypass de autenticação SAML se desenrolou e como você pode se proteger? Continue lendo!

Descoberta e Impacto da Vulnerabilidade

Duas vulnerabilidades críticas de bypass de autenticação SAML, catalogadas como CVE-2025-25291 e CVE-2025-25292, foram encontradas na biblioteca ruby-saml, afetando versões até a 1.17.0. Um atacante, de posse de uma assinatura válida obtida da organização-alvo, poderia criar suas próprias declarações SAML e, assim, acessar contas de qualquer usuário. Em outras palavras, um ataque de tomada de conta era possível.

Usuários do ruby-saml foram orientados a atualizar para a versão 1.18.0. Além disso, bibliotecas que utilizam o ruby-saml, como o omniauth-saml, também precisariam ser atualizadas para referenciar a versão corrigida do ruby-saml.

A vulnerabilidade foi detalhada em uma publicação do GitHub, que avaliou o uso da biblioteca para autenticação SAML. Apesar de o GitHub não utilizar o ruby-saml no momento, a biblioteca é usada em outros projetos e produtos populares, incluindo uma instância vulnerável descoberta no GitLab, cuja equipe de segurança foi notificada.

O GitHub utilizou o ruby-saml até 2014, mas migrou para uma implementação própria devido à falta de funcionalidades na época. Após relatos de vulnerabilidades em sua própria implementação, como a CVE-2024-9487, o GitHub decidiu reavaliar o uso do ruby-saml.

A Busca por Vulnerabilidades

Em outubro de 2024, uma vulnerabilidade de bypass de autenticação SAML (CVE-2024-45409) foi descoberta no ruby-saml pelo pesquisador ahacker1. Esse incidente levou o GitHub a iniciar um programa de bug bounty para avaliar a segurança da biblioteca, concedendo acesso a ambientes de teste para pesquisadores.

Durante a revisão do código, ahacker1 e outro pesquisador notaram que o ruby-saml utilizava dois parsers XML diferentes durante a verificação da assinatura: REXML e Nokogiri. REXML é implementado em Ruby, enquanto Nokogiri é um wrapper para bibliotecas como libxml2. Nokogiri foi adicionado para suportar a canonicalização XML e outras funcionalidades não suportadas pelo REXML.

Os pesquisadores identificaram que o elemento de assinatura a ser verificado era lido tanto por REXML quanto por Nokogiri. Isso levantou a possibilidade de que, se os parsers fossem enganados para retornar diferentes elementos de assinatura para a mesma consulta XPath, seria possível burlar a verificação da assinatura.

Essa descoberta apontava para um potencial bypass de autenticação SAML devido a uma diferencial de parser, onde parsers diferentes interpretam a mesma entrada de maneiras distintas. A exploração dessa vulnerabilidade exigiu a conclusão de quatro etapas: identificar o uso de parsers diferentes, determinar se e como a diferença poderia ser explorada, encontrar uma diferença real entre os parsers e criar um exploit completo.

Como as Respostas SAML São Validadas

As respostas da Security Assertion Markup Language (SAML) são usadas para transmitir informações sobre um usuário autenticado do provedor de identidade (IdP) para o provedor de serviço (SP) em formato XML. A informação mais importante geralmente é o nome de usuário ou endereço de e-mail.

Quando o binding HTTP POST é usado, a resposta SAML viaja do IdP para o SP através do navegador do usuário, tornando essencial a verificação da assinatura para evitar adulterações.

Uma resposta SAML simplificada contém um elemento de assertion, onde a informação principal está no elemento Subject, que inclui o NameID com o nome de usuário. A assertion é canonicalizada e comparada com o DigestValue, enquanto o SignedInfo é canonicalizado e verificado contra o SignatureValue.

Na prática, a assertion da resposta SAML é assinada, mas em outros casos, a resposta SAML inteira pode ser assinada, garantindo a integridade da informação transmitida entre o IdP e o SP.

A Busca por Diferenciais de Parser

O ruby-saml utiliza dois parsers XML distintos, REXML e Nokogiri, para validar a resposta SAML. O foco da validação reside no método validate_signature no arquivo xml_security.rb. Dentro desse método, uma consulta XPath abrangente é realizada com REXML para encontrar o primeiro elemento de assinatura no documento SAML.

A distinção entre as consultas para REXML e Nokogiri pode ser feita pela forma como são chamadas: métodos REXML são prefixados com REXML::, enquanto os métodos Nokogiri são chamados diretamente no document.

Posteriormente, o SignatureValue é lido a partir deste elemento. O elemento Signature contém tanto a assinatura propriamente dita no nó SignatureValue quanto a parte que é realmente assinada no nó SignedInfo, incluindo o DigestValue, que contém o hash da assertion e informações sobre a chave utilizada.

Mais adiante no mesmo método, uma nova consulta para as Signatures é realizada, desta vez utilizando Nokogiri. O elemento SignedInfo é extraído dessa assinatura e canonicalizado, resultando em uma string que contém o elemento SignedInfo canonicalizado. Essa string será crucial para a exploração da vulnerabilidade.

Exploração da Diferencial de Parser

A questão central é: seria possível criar um documento XML onde REXML e Nokogiri identificassem assinaturas diferentes? A resposta é sim.

O pesquisador ahacker1 conseguiu criar um exploit funcional utilizando uma diferencial de parser, inspirado nas vulnerabilidades de XML roundtrips publicadas por Juho Forsén da Mattermost em 2021.

Outro pesquisador desenvolveu um exploit utilizando uma diferencial de parser diferente, com a ajuda do fuzzer Ruby da Trail of Bits, chamado ruzzy. Ambos os exploits resultaram em bypass de autenticação SAML, permitindo que um atacante, de posse de uma assinatura válida, construísse assertions para qualquer usuário.

Um exploit poderia adicionar uma assinatura adicional como parte do elemento StatusDetail, visível apenas para Nokogiri. Nesse cenário, o elemento SignedInfo da assinatura visível para Nokogiri é canonicalizado e verificado contra o SignatureValue extraído da assinatura vista pelo REXML. A assertion é recuperada via Nokogiri, canonicalizada e hasheada, e o hash é comparado ao hash contido no DigestValue, recuperado via REXML.

Medidas de Mitigação e Confusões em SAML

Para mitigar a vulnerabilidade, é possível verificar erros de parsing do Nokogiri nas respostas SAML, inspecionando o membro errors do documento parsed. Embora não seja uma solução perfeita, essa medida impede pelo menos um exploit.

Não há indicadores de comprometimento confiáveis conhecidos. A melhor recomendação é monitorar logins suspeitos via SAML no provedor de serviço, originados de endereços IP inesperados para o usuário.

Implementar sistemas com SAML é desafiador, especialmente ao usar assinaturas XML de forma segura. É aconselhável não seguir estritamente as especificações, pois isso não garante implementações seguras. A validação de assertions assinadas envolve um processo complexo, onde o SignedInfo contém um DigestValue, que é o hash da assertion canonicalizada com o elemento de assinatura removido.

Essa verificação em duas etapas pode levar a implementações desconexas entre a verificação do hash e da assinatura. Nos diferenciais de parser do ruby-saml, o hash e a assinatura são válidos individualmente, mas não estão conectados. A biblioteca extrai o SignedInfo e o utiliza para verificar a assinatura de sua string canonicalizada, mas não o utiliza para obter o digest value.

Em vez de utilizar dois parsers XML, a solução seria usar o conteúdo do SignedInfo extraído para obter o digest value, garantindo a segurança da implementação. Alternativamente, poder-se-ia utilizar um padrão menos complicado para transmitir um nome de usuário assinado criptograficamente entre dois sistemas.

Considerações Finais

A utilização de dois parsers em um contexto de segurança é complexa e propensa a erros, mas a explorabilidade não é automática. Verificar erros do Nokogiri pode não impedir o diferencial de parser, mas pode evitar a exploração.

A correção inicial para o bypass de autenticação SAML não removeu um dos parsers XML para evitar problemas de compatibilidade da API. A questão principal era a desconexão entre a verificação do hash e da assinatura. A remoção de um dos parsers XML foi planejada para uma versão futura, juntamente com melhorias adicionais.

Se sua empresa depende do software de código aberto para funcionalidades críticas, considere patrocinar os projetos para financiar o desenvolvimento e correções de bugs. Usuários da biblioteca ruby-saml devem atualizar para a versão 1.18.0, que corrige as vulnerabilidades CVE-2025-25291 e CVE-2025-25292. Bibliotecas que utilizam o ruby-saml, como o omniauth-saml, também precisam ser atualizadas. Uma prova de conceito do exploit será publicada no repositório GitHub Security Lab.

Este conteúdo foi auxiliado por Inteligência Artificiado, mas escrito e revisado por um humano.

Via The GitHub Blog

Leave a Comment

Exit mobile version