Vulnerability Analysis

CVE-2025-2749: Kentico Xperience CMS Path Traversal to Remote Code Execution — Full Attack Chain & Mitigation

Executive Summary

CVE-2025-2749 is an authenticated path traversal and arbitrary file upload vulnerability in Kentico Xperience CMS's Staging Sync Server that enables full remote code execution (RCE) on the hosting server. When chained with critical authentication bypass flaws CVE-2025-2746 and CVE-2025-2747 (both CVSS 9.8), attackers can achieve unauthenticated RCE against any Kentico Xperience 13.x instance with the Staging service exposed. CISA added CVE-2025-2749 to its Known Exploited Vulnerabilities (KEV) catalog on April 20, 2026, with a mandatory federal patch deadline of May 4, 2026, confirming active in-the-wild exploitation.


1. What Is This Vulnerability?

Kentico Xperience is a widely-deployed enterprise Content Management System (CMS) used by government agencies, healthcare organizations, and large commercial enterprises. The platform includes a Staging Sync Service — a SOAP-based web service at /Staging/SyncServer.asmx — designed to synchronize content and configuration between environments (development, staging, production).

CVE-2025-2749 exists within the file upload handling logic of this Staging Sync Server. When an authenticated user submits a file synchronization request, the service accepts a relative file path parameter without adequate canonicalization or directory traversal sanitization. An attacker can manipulate this path parameter using ../ sequences to write arbitrary files outside the intended upload directory, including into web-accessible folders where server-side scripts (ASPX, ASHX) can be executed by IIS.

The Attack Vector: A Three-Step Exploit Chain

This vulnerability is most dangerous when combined with two companion authentication bypass flaws, enabling a fully unauthenticated attacker to achieve RCE:

Step 1 — Authentication Bypass (CVE-2025-2746 or CVE-2025-2747)

The Staging Sync Server authenticates via WS-Security (WSE 3.0 PasswordDigest). Researchers at WatchTowr discovered two separate logical flaws in this authentication handler:

  • CVE-2025-2746: When an attacker submits a SOAP authentication request with a non-existent username, the server improperly substitutes an empty string for the user's stored password hash. A crafted PasswordDigest computed against an empty password string then passes authentication — no valid credentials required.

  • CVE-2025-2747: A separate flaw in the WSE 3.0 library's handling of the None password type allows the authentication step to be entirely skipped by omitting the password element from the security header.

Both exploits require only a single HTTP POST request to the publicly accessible SOAP endpoint. No prior authentication, no user interaction.

Step 2 — Path Traversal File Upload (CVE-2025-2749)

With a valid staging session established via the auth bypass, the attacker submits a synchronization payload with a manipulated file path. For example, a legitimate sync path of ~/CMSPages/uploads/image.png can be replaced with ../../WebApp/CMSPages/webshell.aspx — or any other path traversable from the upload root. The server writes the attacker-supplied file contents to that location without restriction.

Step 3 — Webshell Execution

Once a malicious ASPX webshell or handler is written to a web-accessible directory, the attacker issues a standard HTTP GET or POST request to the planted file URL and receives server-side command execution with the privileges of the IIS application pool identity — commonly IIS APPPOOL\DefaultAppPool or, in poorly configured deployments, NT AUTHORITY\SYSTEM.

Stored XSS Variant (CVE-2025-2748)

A related vulnerability, CVE-2025-2748, enables unauthenticated stored XSS via the multi-file upload component, which fails to validate SVG file contents. By uploading an SVG containing embedded <script> tags, an attacker can execute JavaScript in the browser context of any authenticated administrator who views the uploaded file — potentially being used to steal session tokens and pivot to the staging endpoint without needing the auth bypass chain.

Attack Vector Summary

[Unauthenticated Attacker]
        │
        ▼
POST /Staging/SyncServer.asmx
  WS-Security: nonexistent-user / empty-password digest
        │
        ▼  (CVE-2025-2746 or CVE-2025-2747)
[Auth Bypassed — Session Token Issued]
        │
        ▼
SYNC request with path=../../CMSPages/webshell.aspx
  Content: <%@ Page ... %><% Process.Start("cmd.exe", ...) %>
        │
        ▼  (CVE-2025-2749)
[ASPX webshell written to disk]
        │
        ▼
GET /CMSPages/webshell.aspx?cmd=whoami
        │
        ▼
[Remote Code Execution as IIS identity]

Real-World Impact

Active exploitation has been confirmed in the wild. Threat actors have used this chain to plant webshells on Kentico-hosted enterprise websites, exfiltrate customer databases, and in at least several documented incidents, deploy ransomware precursor tooling via the compromised application pool. Government and healthcare sector deployments of Kentico Xperience are specifically cited as high-risk targets given their data sensitivity.


2. Who Is Affected?

Component Affected Versions
Kentico Xperience CMS All versions ≤ 13.0.178
Staging Sync Service Enabled (any deployment using staging workflows)
Hosting platform IIS on Windows Server (all supported versions)
Authentication model Username/password staging auth (not X.509 certificate auth)

Risk is highest when:

  • The Staging Sync Service is enabled and internet-accessible (common in misconfigured environments)
  • The application pool runs with elevated privileges
  • The /Staging/SyncServer.asmx endpoint is not blocked at the perimeter or WAF

Risk is lower (but not eliminated) when:

  • X.509 certificate-based mutual authentication is enforced on the staging endpoint
  • The staging service is restricted to internal IP ranges via firewall
  • Only CVE-2025-2749 is considered in isolation (requires valid staging credentials)

3. How to Detect It (Testing)

Manual Testing Steps

Step 1: Discover exposure of the Staging endpoint

curl -s -o /dev/null -w "%{http_code}" \
  https://your-kentico-site.com/Staging/SyncServer.asmx

A 200 OK response with a WSDL-style HTML body confirms the service is exposed. Any code other than 404 should be investigated.

Step 2: Check version via the admin panel

Navigate to https://your-site.com/CMSModules/System/System_Info.aspx (requires admin auth) and note the "Kentico version" field. Any version prior to 13.0.179 is vulnerable.

Step 3: Attempt unauthenticated SOAP handshake (CVE-2025-2746 indicator)

A proof-of-concept involves sending a crafted SOAP envelope to the staging endpoint with a fake username and a PasswordDigest computed against an empty string. If you receive a 200 OK with a staging session token in the response body (rather than an authentication fault), the auth bypass is exploitable.

⚠️ Only perform this test on systems you own or have explicit written authorization to test.

Step 4: Check web-accessible directories for unexpected ASPX files

Get-ChildItem -Recurse -Path "C:\inetpub\wwwroot\YourKenticoSite" `
  -Filter "*.aspx" | Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-30) }

Any recently created ASPX file in an unusual location (outside theme or page template directories) warrants immediate investigation.

Automated Scanning

Nuclei Template (community-contributed):

nuclei -u https://your-kentico-site.com \
  -t cves/2025/CVE-2025-2746.yaml \
  -t cves/2025/CVE-2025-2749.yaml \
  -severity critical,high

Templates for this CVE chain are available in the Nuclei community template repository.

Tenable Nessus / Nessus Professional: Search for plugin CVE-2025-2746 in the plugin library. Nessus includes detection for the staging endpoint exposure and version fingerprinting.

Shodan / Censys exposure check:

shodan search "Kentico" http.title:"Kentico" http.component:"Kentico Xperience"

Use this to assess your external attack surface and verify whether any organization-owned Kentico instances are indexed as publicly reachable.

Burp Suite Active Scan: With the staging WSDL imported, Burp's active scanner can be configured to fuzz the file path parameter in sync requests for directory traversal sequences (../, ..\, URL-encoded variants).

Code Review Checklist

  • Verify that all file path parameters processed by the Staging Sync Server are canonicalized using Path.GetFullPath() and validated against an allowed root prefix before use
  • Confirm that SOAP authentication handlers reject requests with non-existent usernames rather than substituting empty password strings
  • Check that the WSE 3.0 password type None is explicitly rejected in the authentication flow
  • Verify that uploaded files via the Staging service are restricted to a sandboxed directory not accessible via web requests
  • Confirm uploaded file extensions are validated against an allowlist and that ASPX, ASHX, ASMX, and other executable extensions are explicitly blocked

4. How to Fix It (Mitigation)

Step-by-Step Remediation

  1. Upgrade Kentico Xperience immediately to version 13.0.179 or later. This is the only definitive fix. The hotfix addresses path sanitization in the staging file upload handler and rewrites the WSE 3.0 authentication logic to eliminate both auth bypass patterns.

  2. Download the hotfix from the Kentico DevNet portal: Log in at devnet.kentico.com → Downloads → Kentico Xperience 13 → Hotfixes → Version 13.0.179.

  3. Apply the hotfix to all environments (dev, staging, production) — attackers routinely pivot from staging environments to production.

  4. After patching, rotate all staging service credentials and revoke any existing staging sessions:

    • Navigate to Kentico Admin → Staging → Clear Staging Tasks
    • Reset all staging user passwords in Admin → Users
  5. Audit the file system for any unexpected files written to web-accessible directories:

    # Find ASPX files modified in the last 90 days outside expected directories
    Get-ChildItem -Recurse "C:\inetpub\wwwroot\Kentico" -Include "*.aspx","*.ashx","*.asmx" |
      Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-90) } |
      Select-Object FullName, LastWriteTime, Length
    
  6. Review IIS logs for POST requests to /Staging/SyncServer.asmx from unusual IP addresses or with anomalous timing patterns.

Before/After: Path Traversal Sanitization

Vulnerable pattern (pseudocode — simplified):

// BEFORE (vulnerable): no path canonicalization
string uploadPath = Path.Combine(stagingRoot, userSuppliedPath);
File.WriteAllBytes(uploadPath, fileContents);

Fixed pattern:

// AFTER (fixed): canonicalize and validate against allowed root
string stagingRoot = Server.MapPath("~/CMSStagingFiles/");
string candidatePath = Path.GetFullPath(
    Path.Combine(stagingRoot, userSuppliedPath.Replace("..", ""))
);

if (!candidatePath.StartsWith(stagingRoot, StringComparison.OrdinalIgnoreCase))
{
    throw new SecurityException("Path traversal attempt detected.");
}

// Additionally validate file extension
string ext = Path.GetExtension(candidatePath).ToLowerInvariant();
string[] blockedExtensions = { ".aspx", ".ashx", ".asmx", ".cshtml", ".config", ".cs" };
if (blockedExtensions.Contains(ext))
{
    throw new SecurityException("Executable file extension not permitted.");
}

File.WriteAllBytes(candidatePath, fileContents);

Configuration Hardening (Immediate, Pre-Patch)

If immediate patching is not possible, apply these compensating controls:

1. Block the staging endpoint at the network perimeter:

# Nginx — block external access to staging service
location ~* /Staging/SyncServer\.asmx {
    allow 10.0.0.0/8;    # Internal network only
    allow 192.168.0.0/16;
    deny all;
}

2. Block via IIS Request Filtering (Windows):

<!-- In web.config under <system.webServer> -->
<security>
  <requestFiltering>
    <hiddenSegments>
      <add segment="Staging" />
    </hiddenSegments>
  </requestFiltering>
</security>

Note: This will disable staging functionality entirely — only appropriate as a temporary emergency measure.

3. Enable X.509 certificate-based authentication for the staging service (Kentico Admin → Settings → Staging → Use X.509 authentication). This eliminates the username/password auth bypass vectors while preserving staging functionality.

4. Restrict IIS Application Pool identity: Ensure the Kentico application pool runs as a low-privilege service account, not LocalSystem or NetworkService. This limits the blast radius of any RCE.


5. How to Test the Fix (Validation)

Regression Test Scenarios

  • Scenario A: Attempt the authentication bypass SOAP request (CVE-2025-2746) after patching — the server must return an authentication fault (wsse:InvalidSecurity), not a session token
  • Scenario B: Submit a staging sync request with a path traversal payload (../../webshell.aspx) — the server must return an error and must NOT write a file outside the staging root
  • Scenario C: Verify all legitimate staging workflows (content sync, file sync) continue to function correctly between authorized environments
  • Scenario D: Confirm that uploading SVG files via the media library now strips or sanitizes embedded script elements (CVE-2025-2748)

Security Test Cases

Test Case 1: Auth Bypass is Remediated

  • Precondition: Kentico upgraded to 13.0.179+
  • Steps: Send SOAP POST to /Staging/SyncServer.asmx with a nonexistent username and a PasswordDigest of SHA1(nonce + created + "") (empty password)
  • Expected Result: Server returns HTTP 200 with a SOAP Fault — wsse:InvalidSecurity, no session token issued

Test Case 2: Path Traversal is Blocked

  • Precondition: Valid staging credentials (or patched system where auth bypass no longer works)
  • Steps: Submit a file sync payload with relativePath set to ../../CMSPages/test_traversal.aspx
  • Expected Result: Server returns an error response; no file is created at CMSPages/test_traversal.aspx; file system audit confirms the file does not exist

Test Case 3: ASPX Extension Blocked

  • Precondition: Patched system with extension allowlist enforced
  • Steps: Attempt to sync a file with a .aspx extension through the staging service
  • Expected Result: Request is rejected with a validation error; no file is written

Automated Regression Test

import requests
import pytest

KENTICO_BASE = "https://your-kentico-site.com"
STAGING_ENDPOINT = f"{KENTICO_BASE}/Staging/SyncServer.asmx"

def test_auth_bypass_cve_2025_2746_remediated():
    """CVE-2025-2746: empty-password auth bypass must be blocked after patch."""
    # Minimal malformed SOAP envelope mimicking the bypass technique
    payload = """<?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
                   xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <soap:Header>
        <wsse:Security>
          <wsse:UsernameToken>
            <wsse:Username>nonexistent_test_user_abc123</wsse:Username>
            <wsse:Password Type="PasswordDigest">AAAAAAAAAAAAAAAAAAAAAAAA==</wsse:Password>
          </wsse:UsernameToken>
        </wsse:Security>
      </soap:Header>
      <soap:Body/>
    </soap:Envelope>"""
    
    response = requests.post(STAGING_ENDPOINT, data=payload,
                             headers={"Content-Type": "text/xml; charset=utf-8"})
    
    # After patching, must NOT return a valid session
    assert "InvalidSecurity" in response.text or "Authentication" in response.text, \
        "Auth bypass still possible — CVE-2025-2746 not remediated!"
    assert "StagingToken" not in response.text, \
        "Session token returned for invalid credentials — patch failed!"

def test_staging_endpoint_not_publicly_exposed():
    """Staging endpoint should not be reachable from external networks."""
    response = requests.get(STAGING_ENDPOINT, timeout=5)
    assert response.status_code == 404, \
        f"Staging endpoint is publicly reachable (HTTP {response.status_code}) — restrict access!"

6. Prevention & Hardening

Best Practices

  • Disable Staging if unused: Many Kentico deployments enable the Staging Service by default but never use it. If content synchronization between environments is not actively used, disable the service entirely: Kentico Admin → Settings → Staging → Enable staging (uncheck). This eliminates the entire attack surface.

  • Enforce network segmentation for the staging service: The staging endpoint is a server-to-server communication tool that should never be internet-facing. Place it behind a firewall or API gateway that allows only explicitly approved internal IP addresses.

  • Adopt X.509 mutual TLS for staging authentication: Replace username/password authentication with certificate-based auth (supported in Kentico 13). This eliminates the SOAP credential attack surface entirely and is Kentico's own recommended configuration for production environments.

  • Run the IIS application pool with least privilege: Create a dedicated low-privilege Windows service account for the Kentico app pool. Limit that account's filesystem rights to only the directories it genuinely needs. RCE via a webshell will be sandboxed to that account's permissions.

  • Implement a Web Application Firewall (WAF) rule to detect and block path traversal patterns (../, ..\, URL-encoded variants %2e%2e%2f) in POST request bodies to CMS endpoints. This is a defense-in-depth measure, not a substitute for patching.

  • Establish a recurring vulnerability scan schedule: CMS platforms like Kentico release hotfixes frequently. Subscribe to Kentico Security Advisories and run authenticated vulnerability scans against Kentico instances monthly.

  • Monitor for new ASPX files in web directories: Deploy file integrity monitoring (FIM) on the Kentico web root. Tools like AIDE, Tripwire, or Windows File System Auditing can alert on any new or modified ASPX/ASHX file creation within minutes of occurrence.

Monitoring & Detection

Configure the following detections in your SIEM/EDR:

IIS Log Monitoring — unusual POST to staging endpoint:

# Splunk / ELK query
index=iis_logs cs-uri-stem="/Staging/SyncServer.asmx" cs-method=POST
| stats count by c-ip, cs-username, _time
| where count > 5

New ASPX file creation alert (Windows Event Logging): Enable object access auditing on the Kentico web root via Group Policy, then alert on Event ID 4663 (File Created) for .aspx, .ashx, and .config extensions.

EDR Behavioral Rule: Alert on any process spawned by w3wp.exe (IIS worker process) that executes cmd.exe, powershell.exe, net.exe, or performs network connections to external IPs — this is the hallmark of webshell-based post-exploitation.

Threat intelligence: Monitor for Kentico-specific IOCs (webshell filenames, staging POST patterns) via your threat intel feed. Rapid7's Metasploit module for this chain was published following CISA's KEV addition.


References

Latest from the blog

See all →