# Leveraging An Order of Operations Bug to Achieve RCE in Sitecore 8.x - 10.x

Sitecore bundle.js endpoint validates file path before stripping '#' fragment, allowing unauthenticated arbitrary file read of web.config and backups, leading to RCE via ViewState deserialization.

- Payout: Research
- Severity: high
- Program: Sitecore CMS
- Credited: Assetnote
- Disclosed: 2025-02-12
- CVE: CVE-2024-46938
- Write-up quality: 8/10
- Original: https://www.assetnote.io/resources/research/leveraging-an-order-of-operations-bug-to-achieve-rce-in-sitecore-8-x---10-x
- Library page: https://bugbountylibrary.com/r/blog%3Aassetnote-io-resources-research-leveraging-an-order-of-operations-bug-to-achieve-rce-in-sitecore-8-x-10-x
- Tags: domain:web impact:data-leak impact:rce kind:research platform:research sev:high tech:dotnet technique:chained technique:source-review vuln:deserialization vuln:info-disclosure vuln:path-traversal

**Target:** /-/speak/v1/bundles/bundle.js endpoint in Sitecore CMS
**Root cause:** The bundle.js handler validates the file path (StartsWith allowed folder, EndsWith allowed extension) before the ScriptHost strips everything after '#', so 'web.config#.js' passes the .js extension check but is then read as web.config. MapPath also fails to collapse '..' when backslashes are used, enabling traversal.
**Steps:**
1. Leak absolute path: `POST /-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.EditHtml.ValidateXHtml?hdl=a` with body `__PAGESTATE=/../../a/`; 500 error reveals `C:\inetpub\wwwroot\<site>\a\.txt`
2. If no leak, guess common paths like `C:\inetpub\wwwroot\<domain>.sc\`
3. Send `GET /-/speak/v1/bundles/bundle.js?f=C:\inetpub\wwwroot\<site>\sitecore\shell\client\..\..\..\web.config%23.js`
4. Response returns web.config contents including machineKey and Telerik keys
5. Use machineKey to craft malicious ViewState for .NET deserialization RCE, or Telerik keys for Telerik RCE, or download Sitecore zip backups
**How found:** Code review of Sitecore.Resources.Pipelines.ResolveScript.Bundle and Sitecore.Web.ScriptHost revealed validation happens before '#' stripping and MapPath doesn't collapse '..' with backslashes; researchers recognized the order-of-operations mismatch and crafted 'web.config#.js' to bypass extension check.
**Exploitation:** Unauthenticated attacker leaks install path via manufactured exception, then abuses bundle.js path validation order to read web.config. Extracted machineKey enables ViewState deserialization RCE; Telerik keys enable Telerik RCE; backups can be downloaded for further DLL analysis.
**Escalation:** File read of web.config escalates to full RCE via .NET ViewState deserialization with leaked machineKey, or Telerik exploitation, or backup download for custom module analysis.
**Insight:** When a path is validated then later normalized/truncated (e.g. '#' or '?' stripping after the check), look for a suffix that satisfies the validator but is removed before file read; also test backslash traversal since MapPath may not collapse '..' with '\'.
