daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

exploiting-viewstate-knowing-the-secret.md (9744B)


      1 ---
      2 title: "Exploiting VIEWSTATE Knowing the Secret"
      3 section: "Web Pentesting"
      4 sectionSlug: "pentesting-web"
      5 sourcePath: "src/pentesting-web/deserialization/exploiting-__viewstate-knowing-the-secret.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/deserialization/exploiting-__viewstate-knowing-the-secret.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Exploiting __VIEWSTATE Knowing the Secret
     14 
     15 If you **don't know the keys yet**, start with [the sister page about recovering / guessing them](/hacktricks/pentesting-web/deserialization/exploiting-viewstate-parameter). This page is for the case where you already have the **`validationKey`** (and sometimes the **`decryptionKey`**) and want to **forge a valid malicious `__VIEWSTATE`**.<sup>[[1]](#references)</sup>
     16 
     17 ## When is the secret enough?
     18 
     19 In practice, “knowing the secret” usually means you obtained the values from a leaked `web.config`, `machine.config`, registry/host access, another node in the same web farm, or from a **publicly disclosed / hardcoded `machineKey`**.
     20 
     21 The minimum material you need depends on the framework mode:
     22 
     23 - **.NET < 4.5**:
     24   - If encryption is **not** enforced, the **`validationKey`** and validation algorithm are enough.
     25   - Even if `ViewStateEncryptionMode="Always"` is configured, older versions still accept an **unencrypted** ViewState if `__VIEWSTATEENCRYPTED` is removed from the request.
     26 - **.NET >= 4.5** / `compatibilityMode="Framework45"`:
     27   - You usually need **both** the `validationKey` and the `decryptionKey`, plus their algorithms.
     28   - The payload also depends on the target **page path** and **application path**.
     29 
     30 ## Quick triage checklist
     31 
     32 Before generating the payload, collect:
     33 
     34 - `__VIEWSTATE`
     35 - `__VIEWSTATEGENERATOR` if present
     36 - Target page path (for example `/dir/app/page.aspx`)
     37 - IIS application path / virtual root (for example `/app/`)
     38 - Validation algorithm + `validationKey`
     39 - Decryption algorithm + `decryptionKey` if the target uses modern ViewState protection
     40 - `ViewStateUserKey` if the application salts ViewState per user / session
     41 
     42 If you only know the keys but not the exact gadget to use, check the nearby [.NET gadget page](/hacktricks/pentesting-web/deserialization/basic-net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json-net).
     43 
     44 ## Forging the payload with ysoserial.net
     45 
     46 ### Legacy targets (.NET 4.0 and below)
     47 
     48 When the target uses the **legacy** signing logic, `ysoserial.net` can use either:
     49 
     50 - `--generator=<__VIEWSTATEGENERATOR>` if the page exposes that value, or
     51 - `--path` + `--apppath` if you know the IIS application root.
     52 
     53 Example using the exposed generator value:
     54 
     55 ```bash
     56 ysoserial.exe -p ViewState -g TypeConfuseDelegate \
     57   -c "cmd /c whoami" \
     58   --generator=CA0B0334 \
     59   --islegacy \
     60   --validationalg="SHA1" \
     61   --validationkey="<VALIDATION_KEY>"
     62 ```
     63 
     64 If the page is configured with `ViewStateEncryptionMode="Always"` but runs on **.NET < 4.5**, remove `__VIEWSTATEENCRYPTED` from the request and send an **unencrypted but correctly signed** payload.
     65 
     66 If you need the request to still **look encrypted** on a legacy target, recent `ysoserial.net` builds also expose `--isencrypted`, which wraps the legacy payload instead of relying only on the `__VIEWSTATEENCRYPTED` removal trick.
     67 
     68 ### Modern targets (.NET 4.5 and above)
     69 
     70 Modern ViewState derivation uses the target **page path** and **application path** when deriving the protection material, so you normally need both:<sup>[[1]](#references)</sup>
     71 
     72 ```bash
     73 ysoserial.exe -p ViewState -g TextFormattingRunProperties \
     74   -c "cmd /c whoami" \
     75   --path="/content/default.aspx" \
     76   --apppath="/" \
     77   --validationalg="HMACSHA256" \
     78   --validationkey="<VALIDATION_KEY>" \
     79   --decryptionalg="AES" \
     80   --decryptionkey="<DECRYPTION_KEY>"
     81 ```
     82 
     83 If the payload fails and you suspect the **path** or **app path** is wrong, retry with `--isdebug`. The plugin prints the derived values and helps validate whether your guess matches the target's `__VIEWSTATEGENERATOR` / path logic.
     84 
     85 Recent `ysoserial.net` builds also expose `--minify`, which is handy when you need to keep the forged payload short enough for WAF, proxy, or URL-length constraints.
     86 
     87 ## Common gotchas
     88 
     89 ### `__VIEWSTATEGENERATOR` is helpful, but mostly for legacy targets
     90 
     91 `ysoserial.net`'s ViewState plugin explicitly treats `--generator` as a **legacy** shortcut. For **.NET 4.5+** you should expect to need the real `--path` and `--apppath` values.
     92 
     93 ### `ViewStateUserKey` will break otherwise valid payloads
     94 
     95 If the application binds ViewState to a user, session, or anti-CSRF token, you must include the same value when generating the payload:
     96 
     97 ```bash
     98 ysoserial.exe -p ViewState -g TextFormattingRunProperties \
     99   -c "cmd /c whoami" \
    100   --path="/content/default.aspx" \
    101   --apppath="/" \
    102   --validationalg="HMACSHA256" \
    103   --validationkey="<VALIDATION_KEY>" \
    104   --decryptionalg="AES" \
    105   --decryptionkey="<DECRYPTION_KEY>" \
    106   --viewstateuserkey="<KNOWN_OR_GUESSED_VSUK>"
    107 ```
    108 
    109 #### Recovering `ViewStateUserKey` in practice
    110 
    111 Once the keys are known, `ViewStateUserKey` is the most common reason for a forged payload to fail. In real applications, it is often derived from:
    112 
    113 - `Session.SessionID`
    114 - `__AntiXsrfToken` / anti-CSRF cookies
    115 - A value stored in `web.config`, `appSettings`, `Global.asax`, or a shared `BasePage`
    116 
    117 If you already have filesystem access or an ASPX execution primitive, grep for it directly:
    118 
    119 ```bash
    120 rg -n "ViewStateUserKey|AntiXsrf|__AntiXsrfToken|Session\.SessionID" .
    121 ```
    122 
    123 If you only have HTTP access, inspect the response cookies before guessing blindly. Current `badsecrets` / `crapsecrets` logic already tries common candidates such as `ASP.NET_SessionId`, `__AntiXsrfToken`, and small built-in wordlists, so they are also useful for validating whether the missing piece is really the per-user salt.
    124 
    125 ### GET requests can also work
    126 
    127 Although POST is the common delivery path, some applications also parse `__VIEWSTATE` from a **GET** request. This is useful when trying to stay close to the application's normal traffic or when replaying a payload through a URL-based gadget delivery point.
    128 
    129 ### Start with the highest-value endpoints
    130 
    131 Once you know the keys, test the pages that are both **reachable pre-auth** and **guaranteed to post back** before spending time on random forms. Recent real-world examples include:
    132 
    133 - SharePoint `/_layouts/15/ToolPane.aspx` (see the [SharePoint page](/hacktricks/network-services-pentesting/pentesting-web/microsoft-sharepoint))
    134 - Sitecore `/sitecore/blocked.aspx`, which was abused in 2025 when older deployments reused a published sample `machineKey`<sup>[[3]](#references)</sup>
    135 
    136 In practice, license, error, login, and admin helper pages are often better initial sinks than the main application workflow because they expose a stable hidden `__VIEWSTATE` field without requiring a full authenticated UI path.
    137 
    138 ### `__EVENTVALIDATION` can be abused with the same secrets
    139 
    140 The same signing material can also become useful against `__EVENTVALIDATION`, but exploitation is more constrained than normal ViewState abuse: you need a **POST** request, a page that actually processes input, and a **valid control/input name**.
    141 
    142 On **.NET 4.5+**, the secret is reused with a **different cryptographic purpose string**: `__VIEWSTATE` uses `WebForms.HiddenFieldPageStatePersister.ClientState`, while `__EVENTVALIDATION` uses `WebForms.ClientScriptManager.EventValidation`. So if a forged ViewState works but a forged event payload does not, double-check the **page/app path**, the **specific purpose**, and whether the target control is actually allowed to raise that event.<sup>[[1]](#references)</sup>
    143 
    144 ## Why this still matters in 2025-2026
    145 
    146 This workflow is still very relevant because attackers increasingly do **not** need an additional bug once the keys are known:
    147 
    148 - Microsoft reported in **February 2025** that threat actors were abusing **publicly disclosed ASP.NET machine keys** to generate valid malicious ViewState blobs.<sup>[[2]](#references)</sup>
    149 - Mandiant documented in **September 2025** that Sitecore deployments reusing an old **sample `machineKey`** could be hit pre-auth through `/sitecore/blocked.aspx`, turning a documentation mistake into direct ViewState RCE.<sup>[[3]](#references)</sup>
    150 - SANS observed in **August 2025** that post-exploitation SharePoint activity frequently included **dumping machine keys first**, because one recovered key pair can be replayed laterally against sibling IIS applications.<sup>[[4]](#references)</sup>
    151 - In shared IIS / SharePoint farms, one recovered key pair can often be **replayed laterally** against sibling applications that trust the same configuration.
    152 
    153 So, once you recover a single valid key pair, immediately test:
    154 
    155 - Other virtual directories on the same host
    156 - Sibling nodes behind the load balancer
    157 - Admin-only pages that expose richer gadget surfaces
    158 - Alternate state parameters such as `__EVENTVALIDATION`
    159 
    160 ## References
    161 
    162 - [1] [Exploiting Deserialisation in ASP.NET via ViewState](https://soroush.me/blog/exploiting-deserialisation-in-asp-net-via-viewstate)
    163 - [2] [Code injection attacks using publicly disclosed ASP.NET machine keys](https://www.microsoft.com/en-us/security/blog/2025/02/06/code-injection-attacks-using-publicly-disclosed-asp-net-machine-keys/)
    164 - [3] [ViewState Deserialization Zero-Day Vulnerability in Sitecore Products](https://cloud.google.com/blog/topics/threat-intelligence/viewstate-deserialization-zero-day-vulnerability)
    165 - [4] [Stealing Machine Keys for fun and profit (or riding the SharePoint wave)](https://isc.sans.edu/diary/32174)