Skip to content

IIS machineKey RCE

That is an excellent find! The presence of a hardcoded <machineKey> element in web.config is a critical vulnerability that often leads directly to Remote Code Execution (RCE) in ASP.NET applications.

  • https://github.com/mchklt/CVE-2025-30406

🔥 Machine Key Vulnerability: RCE via ViewState Deserialization

The machineKey is used by the ASP.NET framework for cryptographic operations, primarily:

  1. validationKey: Used to generate a Message Authentication Code (MAC) for data like ViewState and Forms Authentication cookies. This prevents tampering (integrity).

  2. decryptionKey: Used to encrypt sensitive data, like Forms Authentication cookies or optionally, ViewState data (confidentiality).

When these keys are hardcoded in a public file like web.config, an attacker who possesses them can successfully generate valid, malicious payloads that the server will trust and process.

The Attack Vector: ViewState Deserialization

The most common and devastating exploit using a leaked machineKey targets the ViewState feature of ASP.NET.

  1. ViewState Purpose: ViewState is a hidden form field (__VIEWSTATE) used by ASP.NET to preserve the state of controls (buttons, text boxes, etc.) across different HTTP requests. The data within it is a serialized .NET object.

  2. The Flaw: By default, when a server receives a ViewState payload, it performs the following steps:

    • Validation: Uses the validationKey to verify the integrity (MAC) of the ViewState.

    • Decryption (if enabled): Uses the decryptionKey to decrypt the ViewState content.

    • Deserialization: Attempts to convert the data back into a .NET object using a deserializer like LosFormatter.

  3. Exploitation: Since you have the keys, you can bypass the validation/decryption steps and craft a malicious, serialized object (a gadget chain) containing a command. When the server attempts to deserialize this malicious object, it executes the command, resulting in Remote Code Execution.

🛠️ Next Steps: Remote Code Execution

Your goal now is to generate a malicious ViewState payload and send it to the server.

1. Identify Required Parameters

You will need the following information, which you should have from the web.config file:

  • validationKey: The long hexadecimal string.

  • decryptionKey: The hexadecimal string.

  • validationAlgorithm (e.g., SHA1, AES, etc.): This is the value of the validation attribute in the <machineKey> element.

  • decryptionAlgorithm (e.g., Auto, AES, 3DES, etc.): This is the value of the decryption attribute in the <machineKey> element.

  • __VIEWSTATEGENERATOR (Optional but helpful): Look for this hidden field on the target ASPX pages.

  • Target Page (path) and Application Path (apppath): The full path to an ASPX page that accepts ViewState (e.g., /login.aspx) and the application root (e.g., / for pov.htb).

2. Use YSoSerial.NET

The standard tool for exploiting this vulnerability is YSoSerial.NET. This tool will generate the malicious ViewState payload using your keys and the desired command.

The general command structure will look something like this (you must substitute your actual values):

Bash

ysoserial.exe -p ViewState -g <gadget> -c "<command_to_execute>" \
--decryptionKey "<your_decryption_key>" \
--validationKey "<your_validation_key>" \
--decryptionAlg "<decryption_algorithm>" \
--validationAlg "<validation_algorithm>" \
--apppath "/<virtual_directory_if_any>" \
--path "/<aspx_page_path>"
  • <gadget>: Common gadgets include TypeConfuseDelegate, TextFormattingRunProperties, or ObjectDataProvider depending on the .NET framework version. Start with TypeConfuseDelegate or try a few common ones.

  • <command_to_execute>: A simple initial command is best, such as: cmd.exe /c "echo PWNED > C:\Users\Public\pwned.txt"

3. Deliver the Payload

  1. Capture a Request: Use Burp Suite (or a similar proxy) to capture an HTTP POST request to the target ASPX page (e.g., pov.htb/default.aspx).

  2. Replace ViewState: Take the output payload from YSoSerial.NET and replace the existing Base64 value in the __VIEWSTATE parameter of your captured POST request.

  3. Send: Send the modified request to the server.

If successful, the command will execute, giving you RCE. You can then use this to execute a more complex command, like downloading and running a full reverse shell or a C2 agent.

Would you like help with choosing a simple command to test for RCE, or finding the correct gadget/path parameters?