A Saga do Cypher Injection

De um erro descritivo até a extensão do Burp

Tempest Security
Jan 7 · 6 min read

Por Vinícius Morais

Esta é uma daquelas histórias interessantes de se contar do início, de forma linear. Há algum tempo, eu e um colega de trabalho estávamos realizando um pentest em uma aplicação web e nos deparamos com uma estranha mensagem de erro ao inserir uma aspa simples em um dos parâmetros de uma requisição: Neo4jError. Inicialmente nos pareceu que era só mais um erro genérico. Porém, algo que ainda não havíamos notado estava escondido naquela névoa entre nós e a aplicação.

Figura1 — Mensagem de erro do banco Neo4j

Ao pesquisarmos um pouco sobre a mensagem de erro, descobrimos o seguinte: existe um banco de dados chamado Neo4j que utiliza grafos para representar seus dados e tem uma linguagem de consulta própria chamada Cypher. Foi então que uma dúvida surgiu em nossas mentes: seria a mensagem de erro o indicativo de um code injection?

Para saná-la, resolvemos fazer um teste simples. Trocamos o valor numérico no parâmetro id da requisição de 42 (Figura 2) para a operação matemática 41+2–1 (Figura 3) e a resposta foi a mesma. Isso indicou que estávamos, de fato, diante de um code injection.

Figura 2 — Requisição original
Figura 3 — Requisição com operação matemática

Confirmado que estávamos com uma parte da Cypher query sob o nosso controle, o objetivo agora era entender como poderíamos explorar isso para demonstrar um impacto real. Como, a partir dessa falha, conseguiríamos realizar consultas arbitrárias para o banco de dados?

Em bancos de dados SQL, uma forma muito comum de subverter uma consulta é através do operador UNION, que permite juntar a query original com uma outra arbitrária. Tentamos então criar um payload utilizando esse operador, mas isso acabou não funcionando. E qual foi o motivo? Descobrimos que no Cypher existe uma restrição no UNION que exige que ambas as consultas tenham o mesmo nome de retorno.

Com isso em mente, voltamos ao erro descritivo da Figura 1 e começamos a juntar as peças do quebra-cabeça: a parte final da consulta (RETURN a) estava sendo exposta e sabíamos que se usássemos um id válido, tínhamos como resposta os dados de uma pessoa. Concluímos que a consulta original se parecia com a seguinte:

Sabendo que o valor do id estava sob nosso controle, tentamos modificar a consulta para que ela retornasse todos os labels do banco de dados, respeitando a restrição que determinava que o payload tinha que usar a variável a como nome de retorno. Assim, a seguinte consulta foi construída:

Vale notar que a primeira consulta retorna um Number enquanto a segunda retorna uma String. Essa diferença de tipos não é um problema no Cypher, porém a consulta acima nunca chegou a funcionar por um motivo simples: esse parâmetro vulnerável tinha um limite de caracteres permitidos, impossibilitando a execução do nosso payload. A aplicação possuía outros pontos vulneráveis que não tinham um limite de caracteres, porém não conseguimos gerar um erro que fornecesse o nome da variável de retorno em nenhum desses pontos.

Nós tínhamos um problema chato: estávamos ao mesmo tempo tão perto e tão longe da solução! Para seguirmos em frente, precisávamos descobrir outro payload que possibilitasse a exploração do code injection e que não utilizasse o operador UNION.

Muitas tentativas foram feitas. Após algum tempo, e com a ajuda de grandes mestres do hacking (meus colegas de trabalho), a solução surgiu. No Cypher existe um operador muito bacana (para um atacante) chamado LOAD CSV, que tenta ler um arquivo CSV e retorna o seu conteúdo como uma String. Acontece que ele também realiza requisições HTTP para buscar o arquivo (o que já permite realizar ataques Server-Side Request Forgery) e foi aí que finalmente enxergamos uma luz no fim do túnel em que estávamos.

A ideia foi a seguinte: criaríamos um payload que faria a consulta para trazer os labels do banco de dados. Porém, ao invés de tentar retorná-los na resposta da requisição, seria efetuada uma nova requisição para um servidor externo utilizando o LOAD CSV e concatenando os labels na URL requisitada.

Já que não tínhamos um servidor sob nosso controle (na verdade, isso foi só pra deixar esse blogpost mais legal), utilizamos a ferramenta Collaborator do Burp Suite.

O Burp Suite é uma ferramenta bastante utilizada em trabalhos de pentest que atua como um proxy entre o cliente (geralmente um browser) e o servidor web. Essa solução possui um mecanismo chamado Burp Collaborator Client que fornece URLs temporárias e permite visualizar as requisições feitas para cada uma delas. De posse dessas ferramentas, criamos um payload com o operador LOAD CSV utilizando uma URL fornecida pelo Burp Collaborator:

Finalmente deu certo! Nós conseguimos receber os resultados da consulta no Collaborator:

Figura 4: Requisições recebidas após a execução do payload contendo o LOAD CSV

A aplicação vulnerável realizou uma requisição para cada label do banco Neo4j. Um dos labels recuperados (Person) pode ser observado na figura 4.

Enfim, o período de testes dessa aplicação terminou e achávamos que esse assunto estava acabado. Porém surgiu uma oportunidade de palestrar sobre o tema, o que me fez criar uma aplicação propositadamente vulnerável a Cypher Injection, cujo código está disponível no meu github e continuar com a pesquisa.

Durante essa pesquisa eu percebi a ausência de ferramentas para a exploração de Cypher Injection e isso me fez criar uma extensão para o Burp Suite com o objetivo de facilitar a detecção dessa vulnerabilidade. Foi assim que nasceu a extensão Cypher Injection Scanner que está disponível na BApp Store, a loja de extensões do Burp Suite.

O Cypher Injection Scanner tem duas funcionalidades:

Checagem passiva (Passive Scan): alerta se foi encontrado um erro descritivo do banco de dados Neo4j em alguma das respostas HTTP já recebidas.

Figura 5: Issue de erro descritivo

Checagem Ativa (Active Scan): Envia payloads contendo o operador LOAD CSV com o objetivo de realizar requisições DNS para uma sessão do Collaborator. O scanner aplica uma variedade de payloads, pois alguns detalhes de sintaxe precisam ser tratados de acordo com o local da query em que a injeção acontece. Caso um dos payloads funcione, é lançada uma issue no Burp Scanner informando, entre outros dados, o tipo da vulnerabilidade, a sua severidade e o payload utilizado.

Figura 6: Issue de Cypher Injection

A extensão pode ser instalada pelo próprio Burp Suite. Basta acessar a aba Extender, em seguida BApp Store e buscar por Cypher Injection Scanner.

Espero que a extensão seja útil para quem quiser se aventurar nas injeções de Cypher.

SideChannel-BR

Notícias e análises sobre segurança da informação produzidas pela equipe e por amigos da Tempest Security Intelligence

Tempest Security

Written by

Empresa líder no mercado brasileiro de segurança da informação e combate a fraudes digitais, atuando desde o ano 2000.

SideChannel-BR

Notícias e análises sobre segurança da informação produzidas pela equipe e por amigos da Tempest Security Intelligence

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade