CVE-2024-34071 (C#, published 2024-05-21T14:15Z)
Description: value: Umbraco is an ASP.NET CMS used by more than 730.000 websites. Umbraco has an endpoint that is vulnerable to open redirects. The endpoint is protected so it requires the user to be signed into backoffice before the vulnerable is exposed. This vulnerability has been patched in version(s) 8.18.14, 10.8.6, 12.3.10 and 13.3.1.
Severity: nan (CVSS v3 base score: )
Weakness: NVD-CWE-noinfo \u2014 Insufficient Information
There is insufficient information about the issue to classify it; details are unkown or unspecified.
Repository: https://github.com/umbraco/Umbraco-CMS
Files changed:
src/Umbraco.Core/Routing/WebPath.cs
src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs
src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs
tests/Umbraco.Tests.UnitTests/Umbraco.Core/Routing/WebPathTests.cs
Commit message: Merge pull request from GHSA-j74q-mv2c-rxmp



Vulnerable code:
        if(Uri.IsWellFormedUriString(encodedImagePath, UriKind.Relative))
        if (Uri.IsWellFormedUriString(redir, UriKind.Relative)
            && redir.StartsWith("//") == false

Fixed code:


    /// <summary>
    /// Determines whether the provided web path is well-formed according to the specified UriKind.
    /// </summary>
    /// <param name="webPath">The web path to check. This can be null.</param>
    /// <param name="uriKind">The kind of Uri (Absolute, Relative, or RelativeOrAbsolute).</param>
    /// <returns>
    /// true if <paramref name="webPath"/> is well-formed; otherwise, false.
    /// </returns>
    public static bool IsWellFormedWebPath(string? webPath, UriKind uriKind)
    {
        if (string.IsNullOrWhiteSpace(webPath))
        {
            return false;
        }

        if (webPath.StartsWith("//"))
        {
            return uriKind is not UriKind.Relative;
        }

        return Uri.IsWellFormedUriString(webPath, uriKind);
    }
using Umbraco.Cms.Core.Routing;
        if(WebPath.IsWellFormedWebPath(encodedImagePath, UriKind.Relative))
using Umbraco.Cms.Core.Routing;
        if (WebPath.IsWellFormedWebPath(redir, UriKind.Relative)


    [Test]
    [TestCase("ftp://hello.com/", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("file:///hello.com/", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("ws://hello.com/", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("wss://hello.com/", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("https://hello.com:8080/", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("http://hello.com:8080/", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("https://hello.com/path", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("http://hello.com/path", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("https://hello.com/path?query=param", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("http://hello.com/path?query=param", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("https://hello.com/path#fragment", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("http://hello.com/path#fragment", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("https://hello.com/path?query=param#fragment", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("http://hello.com/path?query=param#fragment", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("https://hello.com:8080/path?query=param#fragment", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("http://hello.com:8080/path?query=param#fragment", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("//hello.com:8080/path?query=param#fragment", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("//hello.com:8080/path", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("//hello.com:8080", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("//hello.com", UriKind.Absolute, ExpectedResult = true)]
    [TestCase("/test/test.jpg", UriKind.Absolute, ExpectedResult = false)]
    [TestCase("/test", UriKind.Absolute, ExpectedResult = false)]
    [TestCase("test", UriKind.Absolute, ExpectedResult = false)]
    [TestCase("", UriKind.Absolute, ExpectedResult = false)]
    [TestCase(null, UriKind.Absolute, ExpectedResult = false)]
    [TestCase("this is not welformed", UriKind.Absolute, ExpectedResult = false)]
    [TestCase("ftp://hello.com/", UriKind.Relative, ExpectedResult = false)]
    [TestCase("file:///hello.com/", UriKind.Relative, ExpectedResult = false)]
    [TestCase("ws://hello.com/", UriKind.Relative, ExpectedResult = false)]
    [TestCase("wss://hello.com/", UriKind.Relative, ExpectedResult = false)]
    [TestCase("https://hello.com:8080/", UriKind.Relative, ExpectedResult = false)]
    [TestCase("http://hello.com:8080/", UriKind.Relative, ExpectedResult = false)]
    [TestCase("https://hello.com/path", UriKind.Relative, ExpectedResult = false)]
    [TestCase("http://hello.com/path", UriKind.Relative, ExpectedResult = false)]
    [TestCase("https://hello.com/path?query=param", UriKind.Relative, ExpectedResult = false)]
    [TestCase("http://hello.com/path?query=param", UriKind.Relative, ExpectedResult = false)]
    [TestCase("https://hello.com/path#fragment", UriKind.Relative, ExpectedResult = false)]
    [TestCase("http://hello.com/path#fragment", UriKind.Relative, ExpectedResult = false)]
    [TestCase("https://hello.com/path?query=param#fragment", UriKind.Relative, ExpectedResult = false)]
    [TestCase("http://hello.com/path?query=param#fragment", UriKind.Relative, ExpectedResult = false)]
    [TestCase("https://hello.com:8080/path?query=param#fragment", UriKind.Relative, ExpectedResult = false)]
    [TestCase("http://hello.com:8080/path?query=param#fragment", UriKind.Relative, ExpectedResult = false)]
    [TestCase("//hello.com:8080/path?query=param#fragment", UriKind.Relative, ExpectedResult = false)]
    [TestCase("//hello.com:8080/path", UriKind.Relative, ExpectedResult = false)]
    [TestCase("//hello.com:8080", UriKind.Relative, ExpectedResult = false)]
    [TestCase("//hello.com", UriKind.Relative, ExpectedResult = false)]
    [TestCase("/test/test.jpg", UriKind.Relative, ExpectedResult = true)]
    [TestCase("/test", UriKind.Relative, ExpectedResult = true)]
    [TestCase("test", UriKind.Relative, ExpectedResult = true)]
    [TestCase("", UriKind.Relative, ExpectedResult = false)]
    [TestCase(null, UriKind.Relative, ExpectedResult = false)]
    [TestCase("this is not welformed", UriKind.Relative, ExpectedResult = false)]
    [TestCase("ftp://hello.com/", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("file:///hello.com/", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("ws://hello.com/", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("wss://hello.com/", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("https://hello.com:8080/", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("http://hello.com:8080/", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("https://hello.com/path", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("http://hello.com/path", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("https://hello.com/path?query=param", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("http://hello.com/path?query=param", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("https://hello.com/path#fragment", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("http://hello.com/path#fragment", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("https://hello.com/path?query=param#fragment", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("http://hello.com/path?query=param#fragment", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("https://hello.com:8080/path?query=param#fragment", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("http://hello.com:8080/path?query=param#fragment", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("//hello.com:8080/path?query=param#fragment", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("//hello.com:8080/path", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("//hello.com:8080", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("//hello.com", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("/test/test.jpg", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("/test", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("test", UriKind.RelativeOrAbsolute, ExpectedResult = true)]
    [TestCase("", UriKind.RelativeOrAbsolute, ExpectedResult = false)]
    [TestCase(null, UriKind.RelativeOrAbsolute, ExpectedResult = false)]
    [TestCase("this is not welformed", UriKind.RelativeOrAbsolute, ExpectedResult = false)]
    public bool IsWellFormedWebPath(string? webPath, UriKind uriKind) => WebPath.IsWellFormedWebPath(webPath, uriKind);