From 90f30c3f3c1194a2efdd7f5e4e5ea688c67d5e81 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 5 Dec 2016 17:13:07 +1100 Subject: [PATCH 1/2] Ensures tag values are Html encoded both on the client side and on the server side to prevent any xss --- .../lib/umbraco/Extensions.js | 16 ++++++++++++++++ .../propertyeditors/tags/tags.controller.js | 2 +- .../PropertyEditors/TagsPropertyEditor.cs | 5 ++++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/lib/umbraco/Extensions.js b/src/Umbraco.Web.UI.Client/lib/umbraco/Extensions.js index b70a6b12bcc9..3c148f0535d1 100644 --- a/src/Umbraco.Web.UI.Client/lib/umbraco/Extensions.js +++ b/src/Umbraco.Web.UI.Client/lib/umbraco/Extensions.js @@ -69,6 +69,22 @@ }; } + if (!String.prototype.htmlEncode) { + /** htmlEncode extension method for string */ + String.prototype.htmlEncode = function () { + //create a in-memory div, set it's inner text(which jQuery automatically encodes) + //then grab the encoded contents back out. The div never exists on the page. + return $('
').text(this).html(); + }; + } + + if (!String.prototype.htmlDecode) { + /** htmlDecode extension method for string */ + String.prototype.htmlDecode = function () { + return $('
').html(this).text(); + }; + } + if (!String.prototype.startsWith) { /** startsWith extension method for string */ String.prototype.startsWith = function (str) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/tags/tags.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/tags/tags.controller.js index d18ff73bd583..f965b812d815 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/tags/tags.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/tags/tags.controller.js @@ -41,7 +41,7 @@ angular.module("umbraco") //Helper method to add a tag on enter or on typeahead select function addTag(tagToAdd) { - tagToAdd = $sanitize(tagToAdd); + tagToAdd = String(tagToAdd).htmlEncode(); if (tagToAdd != null && tagToAdd.length > 0) { if ($scope.model.value.indexOf(tagToAdd) < 0) { $scope.model.value.push(tagToAdd); diff --git a/src/Umbraco.Web/PropertyEditors/TagsPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/TagsPropertyEditor.cs index b44c65b1577c..120b2d678d8b 100644 --- a/src/Umbraco.Web/PropertyEditors/TagsPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/TagsPropertyEditor.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; +using System.Net; using System.Runtime.InteropServices; using Newtonsoft.Json.Linq; using Umbraco.Core; @@ -60,7 +61,9 @@ public TagPropertyValueEditor(PropertyValueEditor wrapped) public override object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue) { var json = editorValue.Value as JArray; - return json == null ? null : json.Select(x => x.Value()); + return json == null + ? null + : json.Select(x => x.Value()).Where(x => x.IsNullOrWhiteSpace() == false).Select(WebUtility.HtmlEncode); } /// From 4823235bf58f00a49e18c9974b6d60c8cae427e6 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 5 Dec 2016 17:21:24 +1100 Subject: [PATCH 2/2] Ensures the cleaned value isn't double html encoded --- src/Umbraco.Web/PropertyEditors/TagsPropertyEditor.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/PropertyEditors/TagsPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/TagsPropertyEditor.cs index 120b2d678d8b..be228bf3efe3 100644 --- a/src/Umbraco.Web/PropertyEditors/TagsPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/TagsPropertyEditor.cs @@ -63,7 +63,12 @@ public override object ConvertEditorToDb(ContentPropertyData editorValue, object var json = editorValue.Value as JArray; return json == null ? null - : json.Select(x => x.Value()).Where(x => x.IsNullOrWhiteSpace() == false).Select(WebUtility.HtmlEncode); + : json.Select(x => x.Value()).Where(x => x.IsNullOrWhiteSpace() == false) + //First we will decode it as html because we know that if this is not a malicious post that the value is + // already Html encoded by the tags JavaScript controller. Then we'll re-Html Encode it to ensure that in case this + // is a malicious post (i.e. someone is submitting data manually by modifying the request). + .Select(WebUtility.HtmlDecode) + .Select(WebUtility.HtmlEncode); } ///