diff --git a/src/Umbraco.Web.UI/config/splashes/booting.aspx b/src/Umbraco.Web.UI/config/splashes/booting.aspx index 39e97e4ffe..267e36b369 100644 --- a/src/Umbraco.Web.UI/config/splashes/booting.aspx +++ b/src/Umbraco.Web.UI/config/splashes/booting.aspx @@ -1,15 +1,23 @@ <%@ Page Language="C#" AutoEventWireup="true" Inherits="System.Web.UI.Page" %> +<% + // NH: Adds this inline check to avoid a simple codebehind file in the legacy project! + if (!umbraco.cms.helpers.url.ValidateProxyUrl(Request["url"], Request.Url.AbsoluteUri)) + { + throw new ArgumentException("Can't redirect to the requested url - it's not local or an approved proxy url", + "url"); + } +%> - + The website is restarting - "> + ">

The website is restarting

Please wait for 10s while we prepare to serve the page you have requested...

- +

You can modify the design of this page by editing /config/splashes/booting.aspx

diff --git a/src/umbraco.cms/helpers/url.cs b/src/umbraco.cms/helpers/url.cs index 8426486ce0..3fdc380785 100644 --- a/src/umbraco.cms/helpers/url.cs +++ b/src/umbraco.cms/helpers/url.cs @@ -1,30 +1,31 @@ using System; using System.Xml; using System.Text.RegularExpressions; +using umbraco.IO; namespace umbraco.cms.helpers { - /// - /// Summary description for url. - /// - public class url - { - public url() - { - // - // TODO: Add constructor logic here - // - } + /// + /// Summary description for url. + /// + public class url + { + public url() + { + // + // TODO: Add constructor logic here + // + } - public static string FormatUrl(string url) - { - string _newUrl = url; - XmlNode replaceChars = UmbracoSettings.UrlReplaceCharacters; - foreach (XmlNode n in replaceChars.SelectNodes("char")) - { - if (n.Attributes.GetNamedItem("org") != null && n.Attributes.GetNamedItem("org").Value != "") - _newUrl = _newUrl.Replace(n.Attributes.GetNamedItem("org").Value,xmlHelper.GetNodeValue(n)); - } + public static string FormatUrl(string url) + { + string _newUrl = url; + XmlNode replaceChars = UmbracoSettings.UrlReplaceCharacters; + foreach (XmlNode n in replaceChars.SelectNodes("char")) + { + if (n.Attributes.GetNamedItem("org") != null && n.Attributes.GetNamedItem("org").Value != "") + _newUrl = _newUrl.Replace(n.Attributes.GetNamedItem("org").Value, xmlHelper.GetNodeValue(n)); + } // check for double dashes if (UmbracoSettings.RemoveDoubleDashesFromUrlReplacing) @@ -32,8 +33,49 @@ namespace umbraco.cms.helpers _newUrl = Regex.Replace(_newUrl, @"[-]{2,}", "-"); } - return _newUrl; - } + return _newUrl; + } - } + /// + /// Utility method for checking for valid proxy urls or redirect urls to prevent Open Redirect security issues + /// + /// The url to validate + /// The url of the current local domain (to ensure we can validate if the requested url is local without dependency on the request) + /// True if it's an allowed url + public static bool ValidateProxyUrl(string url, string callerUrl) + { + Uri requestUri; + Uri localUri; + if (Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out requestUri)) + { + if (!String.IsNullOrEmpty(callerUrl)) + { + if (Uri.TryCreate(callerUrl, UriKind.RelativeOrAbsolute, out localUri)) + { + // check for local urls + if (!requestUri.IsAbsoluteUri || requestUri.Host == localUri.Host) + { + return true; + } + } + else + { + throw new ArgumentException("CallerUrl is in a wrong format that couldn't be parsed as a valid URI. If you don't want to evaluate for local urls, but just proxy urls then leave callerUrl empty", "callerUrl"); + } + } + // check for valid proxy urls + var feedProxyXml = xmlHelper.OpenAsXmlDocument(IOHelper.MapPath(SystemFiles.FeedProxyConfig)); + if (feedProxyXml != null && + feedProxyXml.SelectSingleNode(string.Concat("//allow[@host = '", requestUri.Host, "']")) != null) + { + return true; + } + } else + { + throw new ArgumentException("url is in a wrong format that couldn't be parsed as a valid URI", "url"); + + } + return false; + } + } }