Saltar a contenido

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.

arch_tiers

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.

procmon

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.

change-perms

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.

proc-restart

Abrimos x64dbg, navegamos a Options -> Preferences, y desmarcamos todo excepto Exit Breakpoint:

text

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:

gdb_banner

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--.

maps

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.

magic_bytes_3

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.

souce-code_hidden

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.