Como encontrar e corrigir vulnerabilidades de entidades XML
Michael Sherman
7 de setembro de 2022
0 minutos de leituraXML é um formato de texto legível por humanos, usado para transportar e armazenar dados estruturados. As tags e estruturas de dados são definidas pelos usuários em documentos autodocumentados, que podem ser analisados por qualquer ferramenta XML, oferecendo aos desenvolvedores um mecanismo altamente configurável para representar dados.
Para ampliar a sintaxe básica limitada do XML, um autor pode definir a estrutura e o conteúdo aceitável dos dados de um documento usando uma definição de tipo de documento (DTD). A DTD permite definir os dados válidos de um documento e descrevê-los em um único lugar para reutilizá-los em todo o documento. Uma entidade geral é declarada na DTD e, em seguida, referenciada no corpo do documento com um e comercial (&) antes do nome e um ponto e vírgula (;) depois dele.
Você pode definir uma entidade no documento:
No entanto, também é possível declarar uma entidade em uma fonte externa, referenciando um caminho de arquivo ou URL:
O arquivo person.dtd contém:
Combinada à sintaxe simples do XML e à uniformidade da maioria dos analisadores, essa capacidade facilita relativamente a execução de um ataque chamado injeção de entidade externa XML (XXE). Neste artigo, vamos analisar a XXE de perto e explorar maneiras de evitá-la.
Por que a XXE representa um risco à segurança
Os ataques de injeção XXE permitem que invasores aproveitem declarações de entidades externas para acessar arquivos ou a infraestrutura do servidor ou da rede visados. Isso pode incluir informações pessoais confidenciais, lógica de negócios e credenciais.
Em casos graves, os invasores podem realizar uma falsificação de solicitação do lado do servidor, que permite se passar por um servidor na rede do alvo e pode possibilitar a execução remota de código. Assim, eles podem elevar seus privilégios, percorrer a infraestrutura do alvo e atacar outros componentes desprotegidos — ou propagar ataques que parecem ter origem no alvo para outras redes conectadas.
Extração de dados
A vulnerabilidade de injeção XXE mais comum permite que invasores induzam um servidor a revelar dados ou arquivos confidenciais em uma resposta HTTP. Isoladamente, isso dá ao invasor acesso somente de leitura aos dados, mas pode revelar informações úteis para escalar para um ataque mais danoso.
Por exemplo, um invasor pode enviar uma carga maliciosa a um servidor-alvo para fazer com que ele exiba um arquivo local de senhas:
A implementação de um protocolo robusto de criptografia de dados é eficaz para evitar a extração de dados, pois torna os dados armazenados ilegíveis e inutilizáveis — mesmo que um invasor consiga se infiltrar no servidor-alvo. Ao usar algoritmos simétricos, como o padrão de criptografia avançada (AES), para armazenar e transferir informações confidenciais baseadas em XML, você define uma chave de segurança confidencial que será usada para criptografar e descriptografar seus dados.
Além disso, desativar o suporte padrão do analisador XML a entidades externas é uma estratégia eficaz para mitigar esse tipo de ataque.
Falsificação de solicitação do lado do servidor
Um servidor vulnerável à injeção XXE oferece ao invasor a oportunidade de se passar por ele e fazer solicitações a recursos internos que normalmente não são visíveis fora da rede.
Em um ataque de falsificação de solicitação do lado do servidor (SSRF), o invasor costuma inserir uma URL ou endereço que aponta para o sistema de arquivos local do servidor vulnerável ou para outros recursos de acesso restrito — especialmente quando o analisador XML não filtra adequadamente as entradas do usuário. Com isso, o invasor pode obter credenciais e privilégios administrativos na rede do alvo:
Se conseguir obter privilégios administrativos, o invasor poderá se passar pelo servidor para sondar a rede do alvo em busca de outras vulnerabilidades. Também poderá executar código remotamente e propagar novos ataques.
Há algumas medidas que melhoram significativamente a resiliência do seu aplicativo a esse tipo de ataque:
Bloqueie todas as solicitações recebidas não autorizadas de usuários a recursos internos e endereços confidenciais.
Considere implementar uma lista de bloqueio abrangente com possíveis endereços e URLs maliciosos que possam representar uma ameaça à sua infraestrutura web.
Adote ferramentas inteligentes de análise estática, como o Snyk Code, capazes de testar seu código em busca de vulnerabilidades e brechas de segurança.
Execução remota de código
Um invasor pode usar a injeção XXE para executar código remotamente (RCE) em um servidor-alvo.
Por exemplo, pode atacar um site ou aplicativo baseado em PHP com o plugin Expect habilitado, declarando uma entidade que contém o wrapper expect para executar comandos remotamente:
Neste exemplo, o comando ifconfig retorna a configuração de rede do servidor quando o analisador XML avalia a entidade xxe.
Podemos evitar a RCE desativando seletivamente wrappers de protocolo, como a extensão Expect do PHP, em nossos sites ou aplicativos web.
No entanto, mesmo quando não há como receber uma resposta direta do servidor, o invasor pode recorrer a métodos de XXE cega.
Ataques de XXE cega
Em alguns casos, os analisadores XML podem impedir declarações de entidades no corpo dos documentos XML. Um invasor pode contornar essa restrição usando entidades de parâmetro, que só são declaradas na DTD ou como valor de outra entidade. Uma entidade de parâmetro é declarada com um sinal de porcentagem e um espaço em branco antes do nome (%) e referenciada com um sinal de porcentagem (%) antes do nome e um ponto e vírgula (;) depois dele.
Nesse código, o servidor visado tentará enviar a solicitação HTTP para a URL do servidor do invasor. Como resultado, o invasor poderá fazer uma consulta DNS ao servidor-alvo usando esse ataque de XXE cega.
Exposição de informações baseada em erros
Nosso servidor está vulnerável a métodos de injeção XXE cega se um invasor puder recuperar dados valiosos analisando as mensagens de erro emitidas pelo servidor.
Por exemplo, esta carga maliciosa induz nosso servidor a revelar o arquivo /etc/pâsswd na mensagem de erro:
Esta carga maliciosa define três entidades de parâmetro: badfile, preenchida com o conteúdo do arquivo /etc/pâsswd; wrapper, que contém a declaração dinâmica de uma nova entidade de parâmetro chamada induce; e a entidade induce, que provoca uma consulta a um caminho que gera uma mensagem de erro.
Para declarar a entidade wrapper, o invasor declara dinamicamente a entidade induce, que contém um caminho válido, mas inexistente, com o valor do parâmetro badfile. Então, quando a entidade wrapper é referenciada, a declaração dinâmica da entidade induce é iniciada.
Por fim, quando o analisador encontra a entidade induce, ele retorna uma mensagem de erro informando que o arquivo cujo nome corresponde ao valor de badfile não existe no caminho nosuchfileexists. Como badfile contém o conteúdo de etc/pâsswd, as informações são exibidas para o invasor.
Um protocolo robusto de tratamento de erros pode reduzir a vulnerabilidade do nosso aplicativo à exposição de informações baseada em erros. Esse protocolo pode incluir a limitação do tamanho e do escopo das mensagens de erro enviadas pelo servidor ao cliente. Com um corpo de mensagem personalizado e um código de status HTTP, podemos evitar mensagens de erro prolixas e geradas automaticamente, que acabam oferecendo reconhecimento gratuito aos invasores.
Precisamos definir claramente as mensagens de erro para situações previstas, como as relacionadas à exceção FileNotFound do nosso servidor de exemplo. Também precisamos especificar mensagens de erro adequadas para casos extremos, o que geralmente exige testes do nosso código.
Exfiltração por canal externo
Um ataque por canal externo é usado para exfiltrar dados por um canal diferente daquele usado para enviar o ataque. Esse tipo de ataque geralmente envolve instruir o servidor-alvo a fazer uma solicitação para um endereço onde o invasor hospeda uma DTD externa maliciosa.
Primeiro, o invasor precisa enviar uma carga comprometida com o conteúdo de uma DTD maliciosa, como:
O arquivo corrupted.dtd no servidor do invasor contém:
Quando a entidade revealinfo é executada, uma solicitação HTTP é enviada ao servidor do invasor, com o valor de badfile incorporado à string da solicitação.
Quando a entidade deval é referenciada, a declaração dinâmica da entidade revealinfo é iniciada.
Outros vetores
Outros vetores comuns de ataques XXE incluem:
Envios de arquivos, como arquivos
.configCampos de entrada de texto, especialmente campos HTML como
textetextarea, que podem ter regras limitadas de validação de entradaTecnologias baseadas em XML, como feeds RSS e APIs
Arquivos baseados em XML, especialmente formatos comuns como imagens SVG
Por exemplo, um invasor pode enviar um arquivo SVG com um link para um documento malicioso e executar um ataque de bomba XML:
A carga maliciosa pode ser parecida com esta:
O analisador identifica várias declarações de entidades na DTD, mas não as avalia imediatamente. Em seguida, lê o documento e encontra o elemento bin, que é chamado pela expansão da entidade a4. Para isso, porém, é preciso expandir as dez instâncias contidas da entidade a3, o que exige expandir as entidades a2 contidas nelas — até chegar a a0.
O tamanho final expandido do elemento bin inclui a expansão recursiva de todos os elementos da entidade a4. Em uma carga maliciosa com dez ou mais níveis de entidades aninhadas, o arquivo resultante pode chegar a centenas de gigabytes, geralmente causando um erro de falta de memória no servidor que tenta analisar o arquivo SVG — e uma negação de serviço para nossos usuários.
Definir limites automáticos de memória ou de uso de outros recursos durante o processamento de solicitações é suficiente para evitar muitos tipos de ataques de negação de serviço (DoS), pois eles geralmente dependem de sobrecarregar a capacidade do servidor.
Práticas de segurança aplicáveis a todos os casos
Desative o suporte a entidades externas
Impedir o uso de entidades externas e DTDs definidas pelo usuário costuma ser suficiente para mitigar muitos tipos de ataques de injeção XXE, e a maioria das ferramentas oferece comandos de uma linha para fazer isso.
Use um firewall de aplicativos web (WAF)
Firewalls de aplicativos web (WAFs) são ótimas ferramentas para combater ataques XXE, pois inspecionam o tráfego HTTP em busca de conteúdo potencialmente malicioso e aplicam regras de filtragem para proteger nossos aplicativos web.
Implemente segurança Zero Trust
A relação de confiança entre seus aplicativos web e outros serviços externos ou de terceiros, como agentes de mensagens e plataformas de autenticação de usuários, pode ser explorada para lançar um ataque SSRF à infraestrutura do servidor. Além disso, os serviços da sua rede só devem ter acesso aos recursos necessários para funcionar corretamente.
Devemos garantir o isolamento adequado de logs e dados confidenciais e implementar processos rigorosos para auditar regularmente os privilégios de acesso de todos os usuários — humanos e programáticos. Isso também facilita a manutenção da segurança a longo prazo.
Sempre execute análises e testes automatizados para detectar vulnerabilidades XXE
As análises de vulnerabilidades XXE automatizadas podem ajudar a identificar e corrigir vulnerabilidades na sua infraestrutura antes que um invasor as explore. Um sistema de detecção abrangente e inteligente também deve recomendar outras medidas para proteger o sistema.
Mantenha seus patches de segurança atualizados
É importante manter nossos sistemas atualizados com patches de provedores de segurança confiáveis. Esses patches podem incluir atualizações de drivers de segurança e correções para proteção contra DoS. Para acompanhar as vulnerabilidades de código aberto mais recentes, recomendamos o Snyk Open Source, que é baseado no abrangente, preciso e atualizado Snyk Vulnerability Database.
Reduza os riscos com os recursos de proteção da Snyk
Bibliotecas de terceiros às vezes apresentam vulnerabilidades que podem ser exploradas, expondo sua aplicação a ataques. Para reforçar ainda mais as defesas da sua aplicação, recomendamos usar o Snyk OSS para analisar cada biblioteca de terceiros integrada a ela.
Você também pode aproveitar os recursos do Snyk Code para identificar e detectar possíveis vulnerabilidades de segurança antes que sejam exploradas.
Considerações finais sobre segurança em XML
XML é uma ferramenta versátil e poderosa para transportar dados — ainda mais porque permite usar dinamicamente recursos externos vinculados. No entanto, essas características fazem dele uma ferramenta popular entre agentes mal-intencionados. Para prevenir e mitigar adequadamente os riscos associados, é fundamental entender as possíveis vulnerabilidades que ele pode introduzir.
Entradas de usuário sem sanitização adequada, mensagens de erro detalhadas demais e privilégios de acesso mal configurados abrem espaço para que invasores usem ataques de injeção de entidade externa (XXE) para comprometer nossos sistemas. Uma maneira eficaz de corrigir essas vulnerabilidades é validar e filtrar as entradas e os uploads dos usuários e, na maioria dos casos, simplesmente remover funcionalidades como o processamento de DTDs externos ou os wrappers de protocolo do PHP.
As mensagens de erro são mais adequadas quando comunicam o mínimo de informações ao usuário. Por exemplo, se alguém não conseguir fazer login, não é necessário informar se o problema foi a senha ou o nome de usuário.
Também podemos implementar WAFs e proteções contra ataques de negação de serviço (DoS), ou usar um provedor de serviços que ofereça esses recursos. E, se um invasor conseguir violar a segurança, ele deverá encontrar apenas dados criptografados e uma rede de serviços com confiança zero.
Comece a jogar Capture the Flag
Aprenda a resolver desafios de Capture the Flag assistindo à gravação sob demanda do nosso workshop virtual introdutório.



