Skip to content

Latest research: Read the advisory

All research
CVE AnalysisDeserializationReverse EngineeringCVE-2025-53690 9.0

Sitecore CVE-2025-53690: a sample machine key from the docs, turned into unauthenticated RCE

Phuoc Pham· Founder9 min read

A machine key copied verbatim out of Sitecore's own 2017 deployment guide lets an attacker forge a valid ASP.NET ViewState and reach pre-auth RCE. This is a full walkthrough: from the leaked key, to a ysoserial.net payload that lands, to a fileless in-memory route handler that survives the patch.

Sitecore is an enterprise CMS and digital-experience platform. It runs behind a lot of very large brands, which is exactly why a pre-authentication remote code execution bug in it is worth taking apart carefully. CVE-2025-53690 is a CVSS 9.0, and the root cause is almost embarrassing: a cryptographic key that was copied straight out of Sitecore's own documentation.

The Sitecore digital-experience platform.
Sitecore is deployed across retail, finance and healthcare — the blast radius is the point.

This post walks the whole chain, from why the key matters to a payload that lands reliably and then hides. It is a rewrite of the original deep-dive by our founder; the full version with every screenshot is linked at the end.

The backstory: a zero-day found in the wild

The vulnerability came to light through incident response, not a lab. Mandiant's threat-intelligence team documented an active ViewState deserialization attack against Sitecore deployments that were reusing a sample ASP.NET machine key exposed in Sitecore deployment guides from 2017 and earlier. An attacker who knows that key can forge a ViewState blob the server will trust, and turn it into code execution.

Mandiant's write-up of the in-the-wild ViewState attack that surfaced CVE-2025-53690.
The bug was caught in incident response: real intrusions, then the CVE.

Why ViewState is the attack surface

ASP.NET Web Forms round-trips the state of server controls through a hidden __VIEWSTATE field: a Base64-encoded, serialized object graph that the browser posts back on every request. To stop clients from tampering with it, the framework signs (and optionally encrypts) that blob with the machine key — a validationKey / decryptionKey pair in web.config.

The security of the whole scheme rests on one assumption: the machine key is secret. If you know it, you can serialize an arbitrary .NET object, sign it with the key, and the server will happily deserialize it. Unsafe deserialization of an attacker-chosen type is a direct path to RCE.

The exposure got worse in 2025: as ViewState key theft became a headline technique across other platforms, the pool of attackers who knew how to weaponize a leaked key grew fast.

ViewState key theft moved from niche to mainstream in 2025.
Once key theft is a known technique, a leaked sample key is a loaded gun.

The CVE itself

A Sitecore deployment guide shipped a concrete machineKey example, wrapped in the worst possible phrasing: "you can either paste this key into your web.config file or generate another unique key." Given a working default and an optional "or", a large number of real deployments pasted the sample key in verbatim. The value eventually turned up in public wordlists and GitHub repositories, so it is no longer a secret at all: it is a well-known constant that unlocks ViewState forgery against every site that reused it.

Reproducing it

With the key in hand, the target is an endpoint that accepts a POST with a ViewState field without authentication. /sitecore/blocked.aspx fits. The payload comes from ysoserial.net, which generates a signed ViewState given the machine key and a gadget chain.

The first attempt, using the popular TextFormattingRunProperties gadget, failed: that chain depends on WPF assemblies that are not present on a stock Sitecore server. The fix is to pick a gadget that only touches assemblies that are always there. TypeConfuseDelegate relies on core mscorlib.dll types, so it is portable across essentially every .NET target — and it worked.

Weaponizing it: from one command to a fileless shell

Getting a single command to run is the start, not the finish. Two refinements turn a proof-of-concept into something usable.

Echo the output back. The XamlAssemblyLoadFromFile gadget can load a small assembly that reaches System.Web.HttpContext.Current.Response and writes command output directly into the HTTP response. Now you get the result of your command in the same request, with no outbound connection required — important on a segmented, egress-filtered network.

Then stop sending payloads at all. Every exploit request carries a large ViewState blob, which is loud and easy to signature. The quieter approach is an in-memory shell: inject a custom RouteBase subclass at position 0 of RouteTable.Routes. From then on it intercepts every incoming request, checks for a magic header (a cmd header), executes when present and returns the result inline. One payload installs it; every command afterwards is an ordinary-looking request with no ViewState at all.

How ASP.NET routing resolves an incoming request — the seam the in-memory shell hooks into.
Insert a malicious route at index 0 and you sit in front of every request.

Routing runs early in the pipeline: UrlRoutingModule executes at the PostResolveRequestCache stage and matches the URL against RouteTable.Routes, delegating to the first matching IRouteHandler. A route inserted at index 0 is checked first on every request, which is exactly why it makes such an effective, fileless persistence primitive — there is no webshell file on disk to find.

Scaling and detection

For finding vulnerable hosts at scale, /sitecore/default.aspx is a better probe than /blocked.aspx: it is reachable pre-auth on more installs and raises fewer flags. A Nuclei template that posts a forged ViewState and looks for the tell-tale response confirms the bug in milliseconds.

A Nuclei template flagging CVE-2025-53690 against a local Sitecore instance.
Critical, one match — /sitecore/default.aspx answers a forged ViewState.

Beyond the two endpoints above, the original research enumerates 35+ unauthenticated ASPX endpoints that carry a ViewState field, any of which can be an entry point once the key is known.

Mitigation

  • Rotate the machine key. Immediately. If your web.config still contains the sample key from the deployment guide, generate a fresh, unique validationKey / decryptionKey pair. Any reused or documented key must be treated as compromised.
  • Apply Sitecore's official security fix and follow their bulletin for CVE-2025-53690.
  • Enable ViewState MAC and encryption, and scope machine keys per application rather than sharing one across a farm from a copied template.
  • Hunt for persistence: a forged-ViewState intrusion may have already installed an in-memory route handler that a patch will not remove. Check RouteTable.Routes for unexpected entries and restart worker processes after remediation.

The uncomfortable takeaway is that the patch alone is not enough here. A signed ViewState payload keeps working until the key is rotated, and an in-memory shell survives the update. Rotate the key, then hunt.

Phuoc Pham

Founder, Starfish Security

LinkedIn