Attacking Thick Client Applications
Las aplicaciones thick client son aquellas que se instalan localmente en nuestros computadores. A diferencia de las aplicaciones thin client, que se ejecutan en un servidor remoto y se pueden acceder a través del navegador web, estas aplicaciones no requieren acceso a internet para funcionar y tienen mejor rendimiento en términos de capacidad de procesamiento, memoria y almacenamiento. Las aplicaciones thick client suelen ser utilizadas en entornos empresariales y creadas para propósitos específicos. Entre estas aplicaciones se incluyen sistemas de gestión de proyectos, sistemas de gestión de relaciones con clientes, herramientas de gestión de inventarios y otro software de productividad. Estas aplicaciones suelen desarrollarse utilizando Java, C++, .NET o Microsoft Silverlight.
Una medida de seguridad crítica que, por ejemplo, Java tiene es una tecnología llamada sandbox. La sandbox es un entorno virtual que permite que el código no confiable, como el código descargado de internet, se ejecute de manera segura en el sistema del usuario sin representar un riesgo de seguridad. Además, aísla el código no confiable, impidiendo que acceda o modifique los recursos del sistema y otras aplicaciones sin la debida autorización. Además de eso, también existen las Java API restrictions y Code Signing que ayudan a crear un entorno más seguro.
En un entorno .NET, un thick client, también conocido como rich client o fat client, se refiere a una aplicación que realiza una cantidad significativa de procesamiento en el lado del cliente en lugar de depender únicamente del servidor para todas las tareas de procesamiento. Como resultado, los thick clients pueden ofrecer un mejor rendimiento, más características y experiencias de usuario mejoradas en comparación con sus contrapartes thin client, que dependen en gran medida del servidor para el procesamiento y almacenamiento de datos.
Algunos ejemplos de aplicaciones thick client son navegadores web, reproductores de medios, software de chat y videojuegos. Algunas aplicaciones thick client suelen estar disponibles para su compra o descarga gratuita a través de su sitio web oficial o tiendas de aplicaciones de terceros, mientras que otras aplicaciones personalizadas que han sido creadas para una empresa específica, pueden ser entregadas directamente por el departamento de IT que ha desarrollado el software. Implementar y mantener aplicaciones thick client puede ser más difícil que las aplicaciones thin client, ya que los parches y actualizaciones deben hacerse localmente en el computador del usuario. Algunas características de las aplicaciones thick client son:
- Software independiente.
- Funcionamiento sin acceso a internet.
- Almacenamiento de datos localmente.
- Menos seguro.
- Consumo de más recursos.
- Más caro.
Las aplicaciones thick client se pueden categorizar en arquitectura de dos niveles y de tres niveles. En la arquitectura de dos niveles, la aplicación se instala localmente en el computador y se comunica directamente con la base de datos. En la arquitectura de tres niveles, las aplicaciones también se instalan localmente en el computador, pero para interactuar con las bases de datos, primero se comunican con un servidor de aplicaciones, generalmente utilizando el protocolo HTTP/HTTPS. En este caso, el servidor de aplicaciones y la base de datos pueden estar ubicados en la misma red o a través de internet. Esto hace que la arquitectura de tres niveles sea más segura, ya que los atacantes no podrán comunicarse directamente con la base de datos. La siguiente imagen muestra las diferencias entre las aplicaciones de arquitectura de dos niveles y tres niveles.
Dado que una gran parte de las aplicaciones thick client se descargan de internet, no hay una forma suficiente de asegurar que los usuarios descarguen la aplicación oficial, lo que genera preocupaciones de seguridad. Las vulnerabilidades específicas de la web como XSS, CSRF y Clickjacking no se aplican a las aplicaciones thick client. Sin embargo, las aplicaciones thick client se consideran menos seguras que las aplicaciones web, con muchos ataques aplicables, incluyendo:
- Manejo incorrecto de errores.
- Datos sensibles hardcoded.
- DLL Hijacking.
- Buffer Overflow.
- SQL Injection.
- Almacenamiento inseguro.
- Gestión de sesiones.
Penetration Testing Steps
Las aplicaciones thick client se consideran más complejas que otras, y la superficie de ataque puede ser grande. El penetration testing de aplicaciones thick client se puede realizar tanto usando herramientas automatizadas como manualmente. Los siguientes pasos se suelen seguir al probar aplicaciones thick client.
Information Gathering
En este paso, los penetration testers deben identificar la arquitectura de la aplicación, los lenguajes de programación y frameworks que se han utilizado, y entender cómo funcionan la aplicación y la infraestructura. También deben identificar las tecnologías que se utilizan en los lados del cliente y del servidor y encontrar puntos de entrada e inputs de usuario. Los testers también deben buscar identificar vulnerabilidades comunes como las que mencionamos anteriormente al final de la sección About. Las siguientes herramientas nos ayudarán a recopilar información.
CFF Explorer | Detect It Easy | Process Monitor | Strings |
---|---|---|---|
Client Side attacks
Aunque los thick clients realizan un procesamiento y almacenamiento de datos significativos en el lado del cliente, todavía se comunican con servidores para varias tareas, como la sincronización de datos o el acceso a recursos compartidos. Esta interacción con servidores y otros sistemas externos puede exponer a los thick clients a vulnerabilidades similares a las que se encuentran en las aplicaciones web, incluyendo command injection, weak access control y SQL injection.
Información sensible como nombres de usuario y contraseñas, tokens o strings para la comunicación con otros servicios, pueden estar almacenados en los archivos locales de la aplicación. Credenciales hardcoded y otra información sensible también se pueden encontrar en el código fuente de la aplicación, por lo que el análisis estático es un paso necesario mientras se prueba la aplicación. Usando las herramientas adecuadas, podemos hacer ingeniería inversa y examinar aplicaciones .NET y Java, incluidos formatos de archivos como EXE, DLL, JAR, CLASS, WAR, entre otros. También se debe realizar análisis dinámico en este paso, ya que las aplicaciones thick client almacenan información sensible en la memoria también.
Ghidra | IDA | OllyDbg | Radare2 |
---|---|---|---|
dnSpy | x64dbg | JADX | Frida |
Network Side Attacks
Si la aplicación se está comunicando con un servidor local o remoto, el análisis del tráfico de red nos ayudará a capturar información sensible que podría estar siendo transferida a través de conexiones HTTP/HTTPS o TCP/UDP, y nos dará una mejor comprensión de cómo funciona esa aplicación. Los penetration testers que realicen análisis de tráfico en aplicaciones thick client deben estar familiarizados con herramientas como:
Wireshark | tcpdump | TCPView | Burp Suite
Server Side Attacks
Los ataques del lado del servidor en aplicaciones thick client son similares a los ataques de aplicaciones web, y los penetration testers deben prestar atención a los más comunes, incluyendo la mayoría de los OWASP Top Ten.
Retrieving hardcoded Credentials from Thick-Client Applications
El siguiente escenario nos lleva a enumerar y explotar una aplicación thick client para movernos lateralmente dentro de una red corporativa durante un penetration testing. El escenario comienza después de haber obtenido acceso a un servicio SMB expuesto.
Explorar el share NETLOGON
del servicio SMB revela RestartOracle-Service.exe
entre otros archivos. Al descargar el ejecutable localmente y ejecutarlo a través de la línea de comandos, parece que no se ejecuta o ejecuta algo oculto.
C:\Apps>.\Restart-OracleService.exe
C:\Apps>
Descargando la herramienta ProcMon64
de SysInternals y monitoreando el proceso revela que el ejecutable realmente crea un archivo temporal en C:\Users\Matt\AppData\Local\Temp
.
Para capturar los archivos, se requiere cambiar los permisos de la carpeta Temp
para desactivar la eliminación de archivos. Para hacer esto, hacemos clic derecho en la carpeta C:\Users\Matt\AppData\Local\Temp
y en Properties
-> Security
-> Advanced
-> cybervaca
-> Disable inheritance
-> Convert inherited permissions into explicit permissions on this object
-> Edit
-> Show advanced permissions
, deseleccionamos las casillas Delete subfolders and files
y Delete
.
Finalmente apretamos OK
-> Apply
-> OK
-> OK
en las ventanas abiertas. Una vez que se hayan aplicado los permisos de la carpeta, simplemente ejecutamos nuevamente Restart-OracleService.exe
y revisamos la carpeta temp
. El archivo 6F39.bat
se crea en la ruta C:\Users\cybervaca\AppData\Local\Temp\2
. Los nombres de los archivos generados son aleatorios cada vez que se ejecuta el servicio.
C:\Apps>dir C:\Users\cybervaca\AppData\Local\Temp\2
...SNIP...
04/03/2023 02:09 PM 1,730,212 6F39.bat
04/03/2023 02:09 PM 0 6F39.tmp
Al listar el contenido del archivo batch 6F39
, se revela lo siguiente.
@shift /0
@echo off
if %username% == matt goto correcto
if %username% == frankytech goto correcto
if %username% == ev4si0n goto correcto
goto error
:correcto
echo TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA > c:\programdata\oracle.txt
echo AAAAAAAAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4g >> c:\programdata\oracle.txt
<SNIP>
echo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA >> c:\programdata\oracle.txt
echo $salida = $null; $fichero = (Get-Content C:\ProgramData\oracle.txt) ; foreach ($linea in $fichero) {$salida += $linea }; $salida = $salida.Replace(" ",""); [System.IO.File]::WriteAllBytes("c:\programdata\restart-service.exe", [System.Convert]::FromBase64String($salida)) > c:\programdata\monta.ps1
powershell.exe -exec bypass -file c:\programdata\monta.ps1
del c:\programdata\monta.ps1
del c:\programdata\oracle.txt
c:\programdata\restart-service.exe
del c:\programdata\restart-service.exe
Al inspeccionar el contenido del archivo, se observa que dos archivos están siendo generados por el script batch y eliminados antes de que alguien pueda acceder a los restos. Podemos intentar recuperar el contenido de los dos archivos modificando el script y eliminando las líneas de eliminación.
@shift /0
@echo off
echo TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA > c:\programdata\oracle.txt
echo AAAAAAAAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4g >> c:\programdata\oracle.txt
<SNIP>
echo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA >> c:\programdata\oracle.txt
echo $salida = $null; $fichero = (Get-Content C:\ProgramData\oracle.txt) ; foreach ($linea in $fichero) {$salida += $linea }; $salida = $salida.Replace(" ",""); [System.IO.File]::WriteAllBytes("c:\programdata\restart-service.exe", [System.Convert]::FromBase64String($salida)) > c:\programdata\monta.ps1
Después de ejecutar el script batch haciendo doble clic sobre él, esperamos unos minutos para identificar el archivo oracle.txt
, que contiene otro archivo lleno de líneas en base64, y el script monta.ps1
, que tiene el siguiente contenido en el directorio c:\programdata\
. Listar el contenido del archivo monta.ps1
revela lo siguiente.
C:\> cat C:\programdata\monta.ps1
$salida = $null; $fichero = (Get-Content C:\ProgramData\oracle.txt) ; foreach ($linea in $fichero) {$salida += $linea }; $salida = $salida.Replace(" ",""); [System.IO.File]::WriteAllBytes("c:\programdata\restart-service.exe", [System.Convert]::FromBase64String($salida))
Este script simplemente lee el contenido del archivo oracle.txt
y lo decodifica en el ejecutable restart-service.exe
. Al ejecutar este script, obtenemos un ejecutable final que podemos analizar más a fondo.
C:\> ls C:\programdata\
Mode LastWriteTime Length Name
<SNIP>
-a---- 3/24/2023 1:01 PM 273 monta.ps1
-a---- 3/24/2023 1:01 PM 601066 oracle.txt
-a---- 3/24/2023 1:17 PM 432273 restart-service.exe
Al ejecutar restart-service.exe
, se muestra el banner Restart Oracle
, creado por HelpDesk
en 2010.
C:\> .\restart-service.exe
____ __ __ ____ __
/ __ \___ _____/ /_____ ______/ /_ / __ \_________ ______/ /__
/ /_/ / _ \/ ___/ __/ __ `/ ___/ __/ / / / / ___/ __ `/ ___/ / _ \
/ _, _/ __(__ ) /_/ /_/ / / / /_ / /_/ / / / /_/ / /__/ / __/
/_/ |_|\___/____/\__/\__,_/_/ \__/ \____/_/ \__,_/\___/_/\___/
by @HelpDesk 2010
PS C:\ProgramData>
Inspeccionando la ejecución del ejecutable con ProcMon64
, se observa que consulta múltiples elementos en el registro sin mostrar algo concluyente.
Abrimos x64dbg
, navegamos a Options
-> Preferences
, y desmarcamos todo excepto Exit Breakpoint
:
Al desmarcar las demás opciones, la depuración comenzará directamente desde el punto de salida de la aplicación, evitando pasar por archivos dll
cargados antes de que la aplicación se inicie. Luego seleccionamos file
-> open
y elegimos restart-service.exe
para importarlo y comenzar la depuración. Una vez importado, hacemos clic derecho en la vista CPU
y seleccionamos Follow in Memory Map
:
Al revisar los mapas de memoria en esta etapa de la ejecución, destaca un mapa con un tamaño de 0000000000003000
, tipo MAP
y protección -RW--
.
Los archivos mapeados en memoria permiten que las aplicaciones accedan a grandes archivos sin necesidad de leer o escribir el archivo completo en memoria. Esto puede ser un punto interesante para buscar credenciales hardcodeadas.
Si hacemos doble clic, veremos los bytes mágicos MZ
en la columna ASCII
, indicando que el archivo es un DOS MZ executable.
Volvemos al panel Memory Map
, y exportamos el elemento mapeado recién descubierto a un archivo dump haciendo clic derecho en la dirección y seleccionando Dump Memory to File
. Al ejecutar strings
en el archivo exportado, se revelan algunos datos interesantes.
C:\> C:\TOOLS\Strings\strings64.exe .\restart-service_00000000001E0000.bin
<SNIP>
"#M
z\V
).NETFramework,Version=v4.0,Profile=Client
FrameworkDisplayName
.NET Framework 4 Client Profile
<SNIP>
Al leer la salida, se confirma que el dump contiene un ejecutable .NET
. Podemos usar De4Dot
para revertir ejecutables .NET
al código fuente arrastrando restart-service_00000000001E0000.bin
sobre el ejecutable de4dot
.
de4dot v3.1.41592.3405
Detected Unknown Obfuscator (C:\Users\cybervaca\Desktop\restart-service_00000000001E0000.bin)
Cleaning C:\Users\cybervaca\Desktop\restart-service_00000000001E0000.bin
Renaming all obfuscated symbols
Saving C:\Users\cybervaca\Desktop\restart-service_00000000001E0000-cleaned.bin
Press any key to exit...
Finalmente, podemos leer el código fuente de la aplicación exportada arrastrándola y soltándola sobre el ejecutable DnSpy
.
Con el código fuente expuesto, entendemos que este binario es una versión personalizada de runas.exe
, diseñada específicamente para reiniciar el servicio de Oracle usando credenciales hardcodeadas.