Essa writeup é sobre a PwnLab:init, é uma BOX OSCP Like recomendada para pratica no exame OSCP. Segundo o autor da box, o nível de dificuldade é baixo.
Os desafios encontrados na resolução dessa box foram bem interessantes, o reconhecimento do alvo foi bem direto, com poucas aplicações. Na etapa de exploração, foram exploradas falhas na aplicação Web, sendo duas de LFI e uma de Arbitrary File Upload. Posteriormente, na etapa de escalação de privilégios, foi possível obter acesso root de duas formas distintas, sendo a primeira através de binários com a flag SUID e a forma alternativa foi através de execução de um exploit.
Target IpAddress:172.16.0.103
VulnHubMachineName:PwnLab: init
URL: https://www.vulnhub.com/entry/pwnlab-init,158/
Descrição:
Wellcome to "PwnLab: init", my first Boot2Root virtual machine. Meant to be easy, I hope you enjoy it and maybe learn something. The purpose of this CTF is to get root and read de flag.
Can contact me at: claor@pwnlab.net or on Twitter: @Chronicoder
Difficulty: Low
Flag: /root/flag.txt
Reconhecimento
Durante a etapa de enumeração, foi possível identificar que o alvo possui diversas portas TCP abertas de serviços como HTTP(80/TCP) e MYSQL(3306/TCP).
Testes de enumeração de arquivos e diretórios foram realizados contra a URL http://172.16.0.103/, diversos arquivos PHP e diretórios foram identificados.
Exploração.
Testes na aplicação web identificaram uma falha de LFI na URL http://172.16.0.104/?page=. A falha de LFI detectada permitiu a leitura de arquivos do servidor alvo a partir da funcionalidade do php conhecida como filter, onde os caracteres são encodados em base64 quando se trata de arquivos php, evitando que eles sejam processados pelo server-side.
Payload utilizado:
http://10.1.0.114/?page=php://filter/convert.base64-encode/resource=config
A falha permitiu extrair as credenciais do banco de dados localizadas no arquivo config.php, arquivo qual foi enumerado em etapa anterior com o GoBuster.
$server = "localhost";
$username = "root";
$password = "H4u%QJ_H99";
$database = "Users";
Utilizando as credenciais encontradas no arquivo config.php, foi possível realizar o acesso ao banco de dados MySQL qual está exposto na porta default 3306/TCP.
Com o acesso root no banco de dados remoto, foi possível enumerar além do banco de dados, as tabelas e colunas da aplicação web.
O acesso a base de dados permitiu obter acesso a credenciais de usuários na tabela users no banco de dados Users.
Foi identificado que as senhas estão encodadas em base64, posteriormente o processo de decode utilizando a ferramenta base64 com a flag de -d(ou –decode), foi possível obter as credenciais em texto claro.
kent:JWzXuBJJNy
mike:SIfdsTEn6I
kane:iSv5Ym2GRo
A credencial do usuário Kane(kane:iSv5Ym2GRo) foi utilizada para acessar a plataforma, permitindo a realização de arquivos para a aplicação na URL http://10.1.0.114/?page=upload.
Com o objetivo de identificar as restrições que a feature de upload impõe, a falha de LFI encontrada anteriormente foi novamente explorada para obter acesso ao código fonte do arquivo upload.php.
$ curl -sq http://10.1.0.114/?page=php://filter/convert.base64-encode/resource=upload | grep -e '[^\ ]\{40,\}' | base64 -d
<?php
session_start();
if (!isset($_SESSION['user'])) { die('You must be log in.'); }
?>
<html>
<body>
<form action='' method='post' enctype='multipart/form-data'>
<input type='file' name='file' id='file' />
<input type='submit' name='submit' value='Upload'/>
</form>
</body>
</html>
<?php
if(isset($_POST['submit'])) {
if ($_FILES['file']['error'] <= 0) {
$filename = $_FILES['file']['name'];
$filetype = $_FILES['file']['type'];
$uploaddir = 'upload/';
$file_ext = strrchr($filename, '.');
$imageinfo = getimagesize($_FILES['file']['tmp_name']);
$whitelist = array(".jpg",".jpeg",".gif",".png");
if (!(in_array($file_ext, $whitelist))) {
die('Not allowed extension, please upload images only.');
}
if(strpos($filetype,'image') === false) {
die('Error 001');
}
if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg' && $imageinfo['mime'] != 'image/jpg'&& $imageinfo['mime'] != 'image/png') {
die('Error 002');
}
if(substr_count($filetype, '/')>1){
die('Error 003');
}
$uploadfile = $uploaddir . md5(basename($_FILES['file']['name'])).$file_ext;
if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {
echo "<img src=\"".$uploadfile."\"><br />";
} else {
die('Error 4');
}
}
}
?>
O código upload.php demonstra possuir alguns mecanismos de validação, como:
- Validação por extensão de arquivo com base em whitelist com extensões permitidas.
$whitelist = array(".jpg",".jpeg",".gif",".png");
if (!(in_array($file_ext, $whitelist))) {
- Verificação utilizando função strpos da existência da string image na variável $filetype
$filetype = $_FILES['file']['type'];
if(strpos($filetype,'image') === false) {
- Verificação de mimeType passado na requisição.
if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg' && $imageinfo['mime'] != 'image/jpg'&& $imageinfo['mime'] != 'image/png') {
Posteriormente, o arquivo é submetido para o diretório upload e seu nome é alterado para uma função de hash md5 que é gerado a partir do nome e extensão do arquivo.
$uploadfile = $uploaddir . md5(basename($_FILES['file']['name'])).$file_ext;
Analisando como a feature de upload(upload.php) realiza as validações, é possível realizar o upload de um arquivo que contenha código PHP, porém não seria possível executar ele diretamente.
A execução do arquivo malicioso foi executada a partir de uma segunda falha de LFI encontrada posteriormente uma analise do código fonte do arquivo index.php.
A analise identificou que existe outro LFI na variável lang definida a partir de um cookie permitiu carregar o jpg e executar código arbitrário. Uma vez que a variável lang é definida em cookie, é possível executar o código malicioso.
A partir disso, o upload de uma webshell php foi realizada, uma vez definido o path do arquivo malicioso na variável LANG através do cookie, foi possível obter uma conexão reversa.
Privilege Escalation.
Com acesso shell a partir de uma conexão revesa executada pela segunda falha de LFI, foi possível testar se as credenciais localizadas no banco de dados podem ser utilizadas para lateralização. A credencial do usuário kane(kane:iSv5Ym2GRo) localizada no banco de dados é a mesma para o sistema operacional.
No diretório do usuário kane foi encontrado um binário cujo nome é msgmike. Esse arquivo pertence ao usuário Mike(owner) e possui a flag SUID ativada.
Uma analise estatica no binário identificou que ele executa o comando “cat /home/mike/msg.txt“.
Caso o PATH do usuário seja alterado, é possível executar um programa que se chame ‘cat’ no mesmo diretório. Nesse cenário é possível que binário execute esse novo comando como usuário mike, possibilitando a obtenção de uma lateralização de usuário.
Foi criado uma copia do binário /bin/bash para o diretório /home/kane/ com o nome de cat. Posteriormente foi necessário alterar o path para o diretório local. Uma vez que o programa msgmike fosse executado, uma shell com o usuário mike seria aberta.
No diretório home do usuário mike, existe um arquivo msg2root, esse binário possui SUID habilitado, logo, seria possível obter acesso root(id 0). Durante analise, foi identificado que o binário msg2root possui uma falha de command injection, permitindo abrir uma shell com privilégios de usuário root devido ao SUID.
Nota: A abertura do shell bash não resultava no usuário id 0, a abertura do sh permitiu acesso shell com usuário id 0.
Uma vez com usuário root, é possível obter acesso a flag e finalizar a challenge.
Privilege Escalation, part 2.
Uma segunda forma de escalar privilégios foi identificada. É possível a partir do exploit cowroot.c que explora a falha DirtyCow, obter acesso root no sistema.
Conclusão
Foi uma box interessante, a utilização das falhas de LFI com a utilização da funcionalidade php://filter para extrair arquivos php do servidor. A segunda falha de LFI foi necessária para o sucesso da execução do arquivo malicioso e obtenção do primeiro acesso ao sistema. A escalação de privilégios teve seus desafios, um fato curioso foi a exploração do binário com SUID de root só ter sido possível com a utilização da shell /bin/sh, ao que aparenta é alguma medida de proteção do sistema.
Links/Recursos:
- File Inclusion Vulnerability https://en.wikipedia.org/wiki/File_inclusion_vulnerability
- PHP Strpos https://www.php.net/manual/en/function.strpos.php
- Mime https://en.wikipedia.org/wiki/MIME
- SUID Files https://en.wikipedia.org/wiki/Setuid
- Unrestricted File Upload https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload
- DirtCow, cowroot exploit https://www.exploit-db.com/exploits/40616
- Php://Filter https://www.idontplaydarts.com/2011/02/using-php-filter-for-local-file-inclusion/
- Writeup Alternativa https://raw.githubusercontent.com/dhn/write_ups/master/boot2root/2017_pwnlab.txt