Writeup do CTF Fetch the Flag 2022: Logster
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 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.

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

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

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.

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:

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.

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

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'):

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.

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.

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.

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.

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.

Vamos criar nossa imagem Docker com o seguinte comando:
Vamos iniciar o servidor TCP do ngrok com o comando:

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

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

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.

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

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

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

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.

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!

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.
