Solução do CTF Fetch the Flag 2022: Geladeira nem tão inteligente
Antonio Gomes
10 de novembro de 2022
0 minutos de leituraObrigado por jogar Fetch com a gente! Parabéns aos milhares de jogadores que participaram do Fetch the Flag CTF. E um agradecimento especial aos Snykers que criaram, testaram e documentaram os desafios!
Este desafio do Fetch the Flag CTF começa com uma recepção calorosa e todas as informações necessárias sobre nossa novíssima Smart Fridge Ultra SFU-3000! Empolgante, não é?
Isaac Asimov previu certa vez: “Refeições completas ou semipreparadas podem ser armazenadas na geladeira e ficar prontas para consumo. Os utensílios da cozinha poderão preparar ‘refeições automáticas’, aquecer água e fazer café”. E aqui estamos, usando esta geladeira para pedir produtos e até tocar música pelo sistema de áudio. Incrível!

Bem, foi empolgante até eu descobrir que o recurso Music não estava disponível. E o recurso Settings, que permitiria atualizar o firmware da geladeira, estava com defeito. Ou seja, não havia como atualizá-lo de pistache/0.0.3.20220107 para a versão mais recente. Pelo menos sabemos qual é a versão do firmware, o que vai nos ajudar a identificar a flag e resolver este desafio!

Passo a passo
Depois de acessar a página web da nossa Smart Fridge Ultra SFU-3000 — e nos decepcionarmos com seus recursos de verdade —, fomos até Settings e descobrimos que o firmware é pistache/0.0.3.20220107. Para quem não conhece o pistache, ele é um framework moderno de HTTP e REST para C++, o que é ótimo, pois nos dá pistas sobre o software por trás da página web do desafio.
Com essas informações, podemos consultar a Snyk Intel Vulnerability Database para buscar problemas de segurança relacionados a pistache/0.0.3.20220107. Ao pesquisar por pistache, descobrimos que o Pistache é afetado por uma vulnerabilidade de traversal de diretório, que também afeta a versão presente no firmware da nossa geladeira — 0.0.3.20220107. Ótimo: podemos tentar explorá-la com o comando sugerido abaixo na PoC da Snyk.

Ao executar curl --path-as-is, o curl não removerá as sequências /../ do caminho completo. Isso também nos permitirá obter os resultados abaixo, que comprovam que conseguimos recuperar a lista de usuários com acesso ao sistema e aproveitar a vulnerabilidade de traversal de diretório, além de confirmar que temos uma pasta chamada doc.
Acessar o caminho da pasta doc nos dará acesso a um documento da API Swagger, que permite identificar os endpoints disponíveis na nossa aplicação web (por exemplo, v1/system/flag/{flag}). A essa altura, já sabemos que estamos lidando com uma aplicação web que usa pistache como binário C++.

E agora? Vamos aproveitar o proc do Linux. Mais especificamente, o /proc/self/exe, que aponta literalmente para o processo em execução no momento, que, neste caso, é o binário da aplicação web Pistache. Para isso, executamos o seguinte comando:
Com isso, podemos baixar o binário do Pistache. Precisaremos fazer engenharia reversa nesse binário para descobrir qual é a flag. Primeiro, vamos baixar uma ferramenta de engenharia reversa de software. Neste caso, vou usar o Ghidra (também disponível para usuários de macOS pelo brew).
Com o Ghidra, vou criar um novo projeto e importar o binário .exe que baixamos anteriormente.

Chegamos à parte mais empolgante do desafio: descobrir como é essa flag! No Ghidra, vamos filtrar os resultados por “flag”. Assim, descobrimos que há um método chamado checkFlag, cujo conteúdo pode ser visto na imagem abaixo, na janela Decompile: checkFlag - (exe).

Ao analisar a janela decompilada, vemos que a flag deve ter 70 caracteres:
if lVar4 == 0x46. A condição definida no código original verifica que lVar4 contém o tamanho da flag fornecida como entrada, enquanto 0x46 corresponde a 70 em decimal.

Se a condição acima for satisfeita — length == 70 —, veremos que outro método, chamado checkIndexes, será executado.

Como podemos ver nas imagens acima e abaixo, checkIndexes espera uma string de flag do programa, um vetor com uma série de índices e um caractere — '7' na imagem acima.

O que isso significa? Que cada chamada de checkIndexes valida um caractere em n posições de índice para verificar se a string da flag é válida. A lógica é chamar todos os métodos checkIndexes; se todos forem aprovados, significa que identificamos a flag. Para descobrir a flag, podemos investigar o arquivo desmontado e tentar converter cada variável local_* de hexadecimal para decimal, descobrindo a posição

{13, 22, 29, 39,40, 45, 59} corresponde à lista de índices em que o caractere `5` aparece na flag. Agora vamos montar a flag:
Outra forma de identificar todos os índices de cada vetor alocado é usar um script (confira o código). Para isso, exportamos o programa como um arquivo C/C++, removemos todo o restante e consideramos apenas o método checkFlag . Depois, usamos um script adicional para analisá-lo, converter as variáveis local_* de hexadecimal para decimal e encontrar os índices de cada caractere até reconstruir a flag.

Mais esperta que uma geladeira
Neste desafio, aprendemos a usar a Snyk para identificar uma vulnerabilidade de traversal de diretório em uma aplicação web C++, acessar e baixar o binário do processo em execução, fazer engenharia reversa com o Ghidra e descobrir a flag analisando o binário decompilado. Divertido!
É isso! Espero que você tenha gostado dos desafios. Obrigado por participar do Snyk CTF 2022! Quer saber como encontramos todas as outras flags? Acesse nossa página de soluções do Fetch the Flag e confira.
