Skip to main content

Writeup do CTF Fetch the Flag 2022: Logster

Escrito por
feature ctf logster

10 de novembro de 2022

0 minutos de leitura

Obrigado 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 escreveram sobre os desafios!

Se você participou do Fetch the Flag da Snyk em 2022 e está procurando a resposta para o desafio Logster, chegou ao lugar certo. Vamos ver a solução juntos!

Vamos começar pela fase de reconhecimento

Nessa fase, o invasor identifica um alvo vulnerável e investiga como explorá-lo. No nosso caso, temos um link para um site. Só precisamos de um ponto de entrada para começar.

Ferramenta de consulta Logster 500 para um shell Jnioromous, com um link para logster.cctf-snyk.io

Primeiro, verificamos o link e acessamos http://logster.c.ctf-snyk.io/. Esse site permite fazer uma varredura em outro site.

Interface do scanner de sites com um campo de endereço, os botões Mais e Verificar e um painel de cabeçalhos brutos sem dados

Vamos testar com https://www.cnn.com/. O site exibe os cabeçalhos:

Scanner de sites mostrando https://www.cnn.com/ no campo de URL e um registro de cabeçalhos brutos com status HTTP 200

Com isso, podemos deduzir pela descrição do desafio (lookup) e pela linguagem de programação (Java) que estamos lidando com o Log4Shell.

Vamos criar um túnel!

Agora, vamos criar um servidor web Express para definir cabeçalhos personalizados, criar um túnel ngrok para executar o servidor localmente e, em seguida, expô-lo à internet. Depois, faremos uma varredura e veremos o que acontece!

Se você não sabe como configurar um servidor Express, a documentação oficial vai ajudar nessa etapa.

Editor de código com tema escuro exibindo um servidor Express.js com uma rota raiz que retorna “Hello World!” e escuta na porta 3000.

Vamos criar nosso servidor Express para atender na porta 3000 e definir um cabeçalho personalizado com ('PWN', 'pwn').

Vamos executá-lo com o comando node express.js:

Terminal exibindo um app de exemplo em Node.js e Express do Fetch the Flag, em execução na porta 3000

Vamos também criar o túnel ngrok com o comando ngrok http 3000. Consulte a documentação oficial do ngrok para configurá-lo na sua máquina.

Terminal exibindo uma sessão online do ngrok que encaminha uma URL HTTPS pública para localhost:3000, com estatísticas de conexão e URL de inspeção.

Copie o link de encaminhamento, cole-o no site e faça a varredura. No console do ngrok (http://localhost:4040/), podemos ver que o cabeçalho reflete o que definimos no arquivo express.js

Console do ngrok Inspect mostrando uma lista de solicitações GET com respostas 200 OK e cabeçalhos HTTP detalhados

Vamos tentar definir um cabeçalho com um payload do tipo Log4Shell. De volta ao arquivo express.js, vamos alterar o cabeçalho para ('${java:version}', 'pwn'):

Editor de código escuro mostrando um app Express.js com uma rota raiz que retorna “Hello World!” e escuta na porta 3000

Reinicie o servidor e faça outra varredura no site. Recebemos um 500 Internal Server Error e, ao consultar os logs, vemos que o nome do cabeçalho precisa ser um token HTTP válido.

Monitor de solicitações do servidor mostrando uma solicitação GET selecionada com erro 500 — erro interno do servidor — e uma mensagem de token HTTP inválido

O Express não aceita cabeçalhos inválidos — $ e {} não são caracteres válidos. Então, precisamos contornar essa restrição. Podemos fazer isso criando um servidor de socket que retorna uma resposta personalizada sempre que recebe uma conexão.

O servidor de socket fica assim. Ele escuta no socket e, a cada conexão, envia a resposta, que nesse caso inclui a versão do Java. Vamos tentar injetar esse cabeçalho personalizado e ver se ele é avaliado.

Código JavaScript em index.js que cria um servidor de rede, envia uma resposta HTTP 200 e fica em escuta na porta 3000

Vamos iniciar o servidor com o comando node index.js e alterar o túnel ngrok para um túnel TCP com o comando ngrok tcp 3000. Você precisa criar uma conta no ngrok para usar o recurso de túnel TCP.

Terminal mostrando uma sessão online do ngrok encaminhando tráfego TCP de 0.tcp.eu.ngrok.io:14584 para localhost:3000.

Copie o link de Forwarding sem o TCP e cole-o no site. Adicione https:// no início e faça a varredura do link. Podemos ver que o cabeçalho personalizado foi avaliado. Foi feito um lookup e recebemos a versão do Java. Sabemos que o lookup funciona.

Interface de análise de site com um campo de URL, os botões Mais e Analisar e resultados brutos de cabeçalho, incluindo o status 200.

Agora precisamos configurar uma exploração do Log4Shell.

O que é Log4Shell?

CVE-2021-44228, também conhecida como Log4Shell, é uma vulnerabilidade de execução remota de código (RCE) sem autenticação que afeta quase todas as versões 2 do Apache Log4j. Em 9 de dezembro de 2021, a notícia sobre a vulnerabilidade zero-day se espalhou pelas comunidades de segurança da informação, junto com uma prova de conceito (POC) disponível publicamente.

Para saber mais sobre a vulnerabilidade Log4Shell, confira nossa aula gratuita no Snyk Learn.

A POC

Vamos usar esta POC disponível publicamente nas próximas etapas. Este repositório contém tudo o que precisamos para realizar o ataque.

Clone o projeto com Git e acesse a classe Evil.java. Precisamos modificá-la para criar o payload específico deste desafio. Queremos listar todos os arquivos do diretório raiz. Vamos criar um objeto File, obter uma lista de arquivos e imprimir todos os nomes.

Editor de código com tema escuro exibindo Evil.java, uma ObjectFactory em Java que lista arquivos no diretório raiz e retorna “Você foi hackeado!”

Vamos criar nossa imagem Docker com o seguinte comando:

docker build -t log4shell-vulnerable-server-exploit .

Vamos iniciar o servidor TCP do ngrok com o comando:

ngrok tcp 9999
Terminal do ngrok mostrando uma sessão online encaminhando tcp://7.tcp.eu.ngrok.io:18771 para localhost:9999

E o servidor HTTP do ngrok com o comando: ngrok http 8888

Terminal do ngrok mostrando uma sessão ativa que encaminha uma URL HTTPS pública para http://localhost:8888

Precisamos executar o contêiner Docker remotamente com o seguinte comando:

Comando de terminal executando um contêiner Docker com mapeamentos de portas, o host de um servidor HTTP e o nome de um teste de vulnerabilidade Log4Shell

Mas, primeiro, precisamos fazer o servidor LDAP apontar para o link de Forwarding correto. Copie e cole o link do servidor HTTP que está atendendo na porta 8888.

Também precisamos incluir no arquivo de socket index.js o endereço do servidor TCP que está atendendo na porta 9999. Aqui, enviamos um cabeçalho com um payload real do Log4Shell. Estamos disponibilizando a classe Evil que modificamos anteriormente.

Código JavaScript que mostra uma resposta do servidor com um endereço TCP do ngrok e o texto “Evil”, seguido de “hello”.

Vamos reiniciar o servidor de socket com o comando: node index.js

Vamos executar este comando novamente:

Captura de tela do terminal mostrando um comando Docker executando um servidor vulnerável ao Log4Shell, com as portas 8888 e 9999 expostas.

Você deverá ver a mesma saída no terminal:

Terminal exibindo um comando Docker que inicia um exploit de servidor vulnerável, com servidores LDAP e HTTP escutando nas portas 9999 e 8888.

Voltando ao site, você deverá ver a lista de arquivos do diretório raiz. E lá está a flag!

Captura de tela com o título “Cabeçalhos brutos”, mostrando uma saída de depuração que lista diretórios e arquivos do servidor, incluindo package.json e node_modules.

Precisamos modificar o payload mais uma vez para revelar a flag. Vamos voltar à classe Evil. Este trecho de código permite ler a flag e exibir o conteúdo do arquivo.

Editor de código com tema escuro exibindo Evil.java, uma ObjectFactory em Java que lê /flag e retorna “você foi invadido!”

Precisamos executar o contêiner Docker novamente para que as alterações sejam aplicadas. Se fizermos mais uma varredura, veremos a saída do arquivo da flag!

Captura de tela de cabeçalhos brutos com logs de depuração e uma sequência de token SNYK destacada.

Resumo do Logster

A simplicidade dessa exploração e a presença generalizada da biblioteca deixaram profissionais de segurança correndo para responder desde que a falha foi divulgada. A recomendação inicial para mitigar o Log4Shell era atualizar para a versão 2.16. Infelizmente, depois descobriram uma exploração de negação de serviço nessa versão. A recomendação atual é atualizar para a versão 2.17.

Para ver em detalhes as recomendações de correção, confira nosso guia rápido de correção do Log4Shell. Ele é atualizado continuamente à medida que novas informações ficam disponíveis.

Espero que você tenha gostado do Logster e dos outros desafios do CTF :) Quer saber como encontramos todas as outras flags? Confira nossa página de soluções do Fetch the Flag e veja como fizemos.