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