Skip to content

Stored XSS via insufficient SVG element filtering

Moderate
SebastianStehle published GHSA-xfr4-qg2v-7v5m Nov 7, 2023

Package

Squidex CMS (Squidex )

Affected versions

<= 7.8.2

Patched versions

7.9.0

Description

Summary

A stored Cross-Site Scripting (XSS) vulnerability enables privilege escalation of authenticated users.

Details

CENSUS identified that the SVG element filtering mechanism intended to stop XSS attacks through uploaded SVG images, is insufficient resulting to stored XSS attacks. The issue has been assigned CVE-2023-46857.

Stored XSS attacks are those where the injected script is permanently stored on the target servers, such as in a database, in a message forum, visitor log, comment field, etc. The victim then retrieves the malicious script from the server when it requests the stored information. In the specific case, an adversary can store a malicious JavaScript payload, packed as an SVG image, through the "upload asset" functionality. This JavaScript payload will be executed every time the image endpoint is visited.

Squidex allows the CMS contributors to be granted the permission of uploading an SVG asset. When the asset is uploaded, a filtering mechanism is performed to validate that the SVG does not contain malicious code. The code executed when uploading an SVG is the following:

Squidex/squidex-7.8.2/backend/src/Squidex.Domain.Apps.Entities/Assets/SvgAssetMetadataSource.cs

15: public sealed class SvgAssetMetadataSource : IAssetMetadataSource
    {
       ...
                        using (var reader = new StreamReader(command.File.OpenRead()))
                        {
                            var text = await reader.ReadToEndAsync();

38:                         if (!text.IsValidSvg())
                            {
                                throw new ValidationException(T.Get("validation.notAnValidSvg"));
                            }
      ...
}

The IsValidSvg method is defined in Squidex/libs/text/Squidex.Text/HtmlSvgExtensions.cs:

Squidex/libs/text/Squidex.Text/HtmlSvgExtensions.cs

12: public static class HtmlSvgExtensions
    {
        private static readonly HashSet<string> InvalidSvgElements = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
        {
16:         "script"
        };

19:     public static bool IsValidSvg(this string html)
        {
            var document = LoadHtml(html);

            return IsValid(document.DocumentNode);
        }
        [...]

46:   private static bool IsValid(HtmlNode node)
        {
            switch (node.NodeType)
            {
                case HtmlNodeType.Document:
                    return IsChildrenValid(node);

                case HtmlNodeType.Element:
54:                 if (InvalidSvgElements.Contains(node.Name))
                    {
                        return false;
                    }

                    if (node.HasAttributes)
                    {
                        for (var i = 0; i < node.Attributes.Count; i++)
                        {
                            var attribute = node.Attributes[i];

65:                         if (attribute.Name.StartsWith("on", StringComparison.OrdinalIgnoreCase))
                            {
                                return false;
                            }
                        }
                    }

                    if (node.HasChildNodes)
                    {
                        return IsChildrenValid(node);
                    }

                    break;
            }

            return true;
        }
        [...]

The validation logic consists of traversing the HTML nodes in the DOM. In order for the validation to succeed, 2 conditions must be met:

  1. No HTML tags included in a "blacklist" called "InvalidSvgElements" are present (line 54). This list only contains the element "script".
  2. No attributes of HTML tags begin with "on" (i.e. onerror, onclick) (line 65).

If either of the 2 conditions is not satisfied, validation fails and the file/asset is not uploaded.

However it is possible to bypass the above filtering mechanism and execute arbitrary JavaScript code
by introducing other HTML elements such as an <iframe> element with a "src" attribute containing a "javascript:" value.

PoC

As a Proof-of-Concept, the following SVG file will be successfully uploaded, evading the validation efforts:

<svg width="500" height="500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <circle cx="50" cy="50" r="45" fill="green" id="foo"/>
  <foreignObject width="500" height="500">
     <iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:alert('xss')" width="400" height="250"/>
  </foreignObject>
</svg>

Impact

Authenticated adversaries with the "assets.create" permission, can leverage this vulnerability to upload a malicious SVG as an asset, targeting any registered user that will attempt to open/view the asset through the Squidex CMS.

The impact of this issue is magnified due to the fact that the SVG image is rendered in-browser, under the Squidex instance's domain (in default installations).

As a result, adversaries are able to execute arbitrary JavaScript code inside the browser’s context of the targeted Squidex CMS application user. This can cause a variety of risks for the end user that can range in severity from annoyance to complete account compromise. The most severe attacks involve disclosure of the access token stored in the browser's local storage, allowing the actors to hijack user access and completely take over their accounts. The achieved level of access is directly related to the CMS role and permissions assigned on the compromised user. This means that the overall risk to the application can be significantly increased in cases where CMS administrative users are compromised.

Moreover, this issue undermines the business logic behind the "Image" filetype validation in Content Schemas that permit file uploads. For example, administrators may prohibit clients from uploading elements such as HTML content for a specific schema, but allow them to upload Images, including SVG. However, SVG images may enable XSS vectors as discussed above, creating a false sense of security surrounding the "Image" upload option.

Severity

Moderate

CVE ID

CVE-2023-46857

Weaknesses

Credits