PowerShell is dead...? Not today my friend!

Hoy vamos a hablar de POWERSHELL, y digo vamos porque todas estas pruebas las he hecho con mi buen compañero pwner @Wint3r.

Últimamente se está escuchando mucho la palabra C# (o Csharp) y se habla de cómo el uso ofensivo de PowerShell está muriendo poco a poco. ¿La razón? Microsoft está poniendo mucho énfasis en detectar el uso malicioso de su lenguaje. A continuación vamos a ver cómo.

SEGURIDAD EN POWERSHELL

Posiblemente en algún momento nos hayamos encontrado con mensajes como los siguientes a la hora de pwnear:




Debemos tener mas o menos claro lo que significa cada uno de ellos:

Execution Policies

Las políticas de ejecución determinan cómo va a funcionar PowerShell en lo referente a cargar ficheros de configuración o correr scripts. Este tipo de políticas se pueden establecer para un usuario, una sesión, una máquina... o inclusive crear una política de grupo para organizar una serie de máquinas y usuarios.
Dentro de las políticas de ejecución nos interesan principalmente dos: Restricted y Bypass (como imaginaremos, vamos a buscar tener la política Bypass y evitar la Restricted)

Más info: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-6
  • Get-ExecutionPolicy # Ver la política de nuestra sesión actual
  • Set-ExecutionPolicy -ExecutionPolicy <PolicyName> # Establecer política (requiere Admin)
>> Normalmente no vamos a tener problema para cambiar la política de ejecución, ya que no es una "medida de seguridad" como tal. Si bien Set-ExecutionPolicy necesita admin, podemos solucionar este problema creando una nueva sesión con nuestra política en Bypass:


LanguageMode

Los modos de lenguage determinan qué elementos de powershell se pueden utilizar en la sesión actual. Digamos que es algo parecido a las execution policies pero, en este caso, SI que es una medida de seguridad más robusta. Normalmente nos encontraremos con los modos de lenguaje FULL LANGUAGE o CONSTRAINED LANGUAGE (como imaginaremos, vamos a buscar tener el modo FULL).

Más info: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_language_modes?view=powershell-6
  • $ExecutionContext.SessionState.LanguageMode # Ver
  • $ExecutionContext.SessionState.LanguageMode = <LanguageMode> # Establecer
Como se puede ver en la imagen a continuación, no necesitamos privilegios de Admin para cambiar nuestro modo de lenguaje de FULL a CONSTRAINED... pero una vez estemos en este último, salir de él va a ser más complicado. 


>> En muchos sitemas todavía sigue presente la versión 2.0 de PowerShell, este dato es importante porque el modo de lenguage CONSTRAINED se introdujo en la versión 3.0. Un bypass de este modo de lenguage en este tipo de sistemas es algo tan simple como crear una nueva sesión con la versión 2 de PowerShell:


>> Para aquellos sistemas sin la versión 2 (Microsoft está trabajando en que las nuevas versiones de Windows ya no la tengan incluida) disponemos de la siguiente herramienta:
Para utilizarla solo tendremos que compilar el proyecto y utilizar el binario (como se ve en la imagen, no hace falta que tenga la extensión .exe, lo que nos permite evitar también reglas de APPlocker). En el github se explica además cómo obtener una shell reversa con este método.


AMSI

Con el objetivo (entre otras cosas) de detectar malware ejecutado en memoria, Microsoft lanzó AntiMalware Scan Interface (AMSI). De acuerdo con Microsoft, AMSI puede ser integrado en cualquier aplicación y provee análisis de ficheros, memoria, URL's, IP's... pero lo que realmente hace efectivo a AMSI es que trata de capturar los scripts en la capa de Windows Script Host.

Más info


Antes de entrar en detalles sobre cómo bypassear AMSI (a lo largo de estos años ha habido numerosas técnicas que Microsoft también ha ido arreglando...) vamos a ver otras funcionalidades de seguridad claves en PowerShell.

Module Logging

Esta funcionalidad permite registrar y llevar control sobre módulos específicos de PowerShell. Simplificando un poco, si un Azulón tiene activado Module Logging y ha añadido el módulo "SmbShare", en el momento en el que nosotros en una sesión de PowerShell utilicemos (por ejemplo) Get-SmbShare, quedará registrado.


Script Block Logging
 
Similar a la anterior pero registrando comandos, bloques de script, scripts ps1, ..., sean invocados interactivamente o a través de una automatización. Por ejemplo, si se realiza un Systeminfo a través de un fichero .ps1, en el log quedará reflejado.


Powershell Transcription
 
Registrará tanto el input como el output resultante de las sesiones PowerShell en ficheros de texto. Por ejemplo, indicamos que en la carpeta C:\users\attl4s\desktop\winter se guarden los registros, abrimos powershell y escribimos un par de comandos. Si nos dirigimos a la carpeta veremos el fichero correspondiente con los comandos, fecha, hora..., etcétera.



BYPASSES BYPASSES

Como se ha mencionado antes, a lo largo del tiempo se han utilizado diferentes técnicas para bypassear AMSI y los diferentes Loggings. En este apartado vamos a mencionar dos bypasses recientes:
  • En la Derbycon 2018, Omer Yair presentó Invisi-Shell con el eslogan "Hide your Powershell script in plain sight. Bypass all Powershell security features"
  • Por otro lado, hace unos días, @zc00l escribió un post sobre cómo bypassear AMSI que luego complementó @Rastamouse.
La idea de ambos es la misma, se saltarán las diferentes protecciones de PowerShell parcheando la memoria dinámicamente. Pero como @Wint3r y yo no somos ningunos expertos en ensamblador, 
tampoco se entrará en mucho detalle.

Invisi-Shellhttps://github.com/OmerYa/Invisi-Shell

La clave de Invisi-Shell simplificando es:
  • Hookea Powershell (System.Management.Automation.dll) 
  • Hookea System.Core.dll (para el registro de eventos)
  • Hookea todas las llamadas a AMSI.
Al compilar el proyecto de Invisi-Shell, Windows Defender nos mandó un saludo borrándonos la dll resultante. Tras una serie de cambios básicos en el código fuente conseguimos hacerla indetectable (por lo menos para Windows Defender y Avast, que son los AVs que teníamos en nuestras máquinas de pruebas).

Disponemos por tanto de una dll y dos ficheros .bat en caso de que seamos o bien administrador o bien un usuario corriente.

Para la prueba de concepto hemos grabado un video:

  1. Todas las restricciones mencionadas en este post se encuentran activas (Constrained Language Mode, AMSI, Script Block Logging, Powershell Transcription, Module Logging).
  2. Con una sesión de PowerShell normal no podemos cargar un agente de Empire porque es detectado por AMSI. Todos los comandos de la sesión son registrados en el visor de eventos de windows.
  3. Al ejecutar el .bat de Invisi-Shell conseguimos una sesión de PowerShell:
    1. --> Sin Constrained Language Mode.
    2. --> Sin ningún tipo de registro de actividad.
    3. --> AMSI inutilizado.
  4. Obtenemos agente de Empire (para conseguir el agente de Empire ha sido necesario modificar ligeramente el launcher original, puesto que es detectado por su formato).
zC00l & Rastamouse

Simplificando, este bypass se basa en que:
  • La función AmsiScanBuffer dispone de una variable buffer que servirá para indicar a AMSI el número de bytes que debe analizar.
  • zC00l parchea dicho buffer convirtiendo su valor en 0 dinámicamente, por lo cual AMSI escaneará 0 bytes de nuestro payload (no hará nada).
Mas info:

En el siguiente video vemos un ejemplo de uso de la técnica para conseguir nuestro agente de Empire similar a la anterior. Destacar:
  1. En este caso solo nos saltamos AMSI, por lo que nuestros movimientos quedarán registrados en su totalidad si los Loggings están activados.
  2. Hosteamos nuestro bypass de AMSI para utilizarlo remotamente (esto se puede conseguir tambien con Invisi-Shell con poco esfuerzo).
  3. Una vez cargado el script, parcheamos la memoria con el comando [Bypass.AMSI]::Disable()
  4. Lanzamos nuestro payload y conseguimos el agente de Empire.
CONCLUSIONES

Como vemos, a pesar de tener numerosas funciones de seguridad que complican su uso ofensivo, siguen apareciendo técnicas que nos permiten hacer el mal con PowerShell.
PowerShell está muerto? probablemente nunca lo esté. De hecho, Microsoft se ha pronunciado sobre estos bypasses:

"We don’t see this as a security vulnerability – but we’ll definitely look into what we can do to prevent (or detect) this type of attacks."

Por otro lado, con C# nos evitamos tantos líos de obfuscación y bypasses (por lo menos de momento)... así que a gusto del consumidor.

Esperamos que este post haya sido de utilidad para entender un poco mejor cómo se encuentra PowerShell actualmente y algunos de sus bypasses.

Wint3r - attl4s

1 comentarios :