From ae0e4a13cb4b3a7e6fed21173b669d8c87acb5bf Mon Sep 17 00:00:00 2001
From: AlekseyMartynov
Date: Mon, 20 Apr 2020 20:12:07 +0300
Subject: [PATCH 1/3] HtmlEditorExtender.Decode: fix removal of insecure HTML
---
.../HtmlEditorExtenderTests.cs | 36 ++++++++++++-
.../HtmlEditorExtender/HtmlEditorExtender.cs | 51 ++++++++++++-------
2 files changed, 69 insertions(+), 18 deletions(-)
diff --git a/AjaxControlToolkit.Tests/HtmlEditorExtenderTests.cs b/AjaxControlToolkit.Tests/HtmlEditorExtenderTests.cs
index d99ca8ddd..98f20fe68 100644
--- a/AjaxControlToolkit.Tests/HtmlEditorExtenderTests.cs
+++ b/AjaxControlToolkit.Tests/HtmlEditorExtenderTests.cs
@@ -61,7 +61,7 @@ public void StripScriptTagWithoutAttributes() {
var text = @" Z"));
+
+ // was "Hello world!alert()" - see https://github.com/DevExpress/AjaxControlToolkit/issues/525
+ Assert.AreEqual(
+ "Hello world! ",
+ html.Decode("Hello world! ")
+ );
+
+ // was "";
+ Assert.AreEqual(issue513html, html.Decode(issue513html));
+
+ // was "
"
+ Assert.AreEqual(
+ "Click me
",
+ html.Decode("Click me
")
+ );
+
+ var comment = "";
+ Assert.AreEqual(comment, html.Decode(comment));
+ }
+ }
}
}
diff --git a/AjaxControlToolkit/HtmlEditorExtender/HtmlEditorExtender.cs b/AjaxControlToolkit/HtmlEditorExtender/HtmlEditorExtender.cs
index ec3e2ff63..a7850f9be 100644
--- a/AjaxControlToolkit/HtmlEditorExtender/HtmlEditorExtender.cs
+++ b/AjaxControlToolkit/HtmlEditorExtender/HtmlEditorExtender.cs
@@ -173,23 +173,6 @@ public string Decode(string value) {
result = Regex.Replace(result, "&", "&", RegexOptions.IgnoreCase);
result = Regex.Replace(result, " ", "\xA0", RegexOptions.IgnoreCase);
- result = Regex.Replace(result, "[^<]<[^>]*expression[^>]*>", "", RegexOptions.IgnoreCase | RegexOptions.ECMAScript);
-
- result = Regex.Replace(result, "[^<]<([^>]*)(data\\:[^>]*)>", m => {
- var tagGroup = m.Groups[1].Value.ToLower();
- var urlGroup = m.Groups[2].Value.ToLower();
-
- if(tagGroup.StartsWith("img") && urlGroup.StartsWith("data:image/"))
- return m.Value;
-
- return "";
- }, RegexOptions.IgnoreCase | RegexOptions.ECMAScript);
-
- result = Regex.Replace(result, "[^<]<[^>]*script(?!\\w)[^>]*>", "", RegexOptions.IgnoreCase | RegexOptions.ECMAScript);
- result = Regex.Replace(result, "[^<]<[^>]*filter[^>]*>", "", RegexOptions.IgnoreCase | RegexOptions.ECMAScript);
- result = Regex.Replace(result, "[^<]<[^>]*behavior[^>]*>", "", RegexOptions.IgnoreCase | RegexOptions.ECMAScript);
- result = Regex.Replace(result, "[^<]<[^>]*javascript\\:[^>]*>", "", RegexOptions.IgnoreCase | RegexOptions.ECMAScript);
- result = Regex.Replace(result, "[^<]<[^>]*position\\:[^>]*>", "", RegexOptions.IgnoreCase | RegexOptions.ECMAScript);
// Check Whether EnableSanitization is disabled or not.
if(EnableSanitization && Sanitizer != null) {
@@ -205,6 +188,8 @@ public string Decode(string value) {
elementWhiteList.Add("img", new[] { "src" });
result = Sanitizer.GetSafeHtmlFragment(result, elementWhiteList);
+ } else {
+ result = RemoveInsecureHtml(result);
}
// HtmlAgilityPack vanishes self-closing
tag, so replace it after sanitization
@@ -213,6 +198,38 @@ public string Decode(string value) {
return result;
}
+ static string RemoveInsecureHtml(string html) {
+ var reFlags = RegexOptions.IgnoreCase | RegexOptions.Singleline;
+
+ html = Regex.Replace(html, @"(?]*>.*?(]*>|$)", "", reFlags);
+
+ html = Regex.Replace(html, @"(?]+)([^>]*)>", m => {
+ var tag = m.Groups[1].Value;
+
+ if(tag.StartsWith("!--"))
+ return m.Value;
+
+ var attrs = m.Groups[2].Value;
+ var dropAttrs = false;
+
+ // Non-image data URLs
+ dropAttrs = dropAttrs || Regex.IsMatch(attrs, @"\bdata:(?!image/)", reFlags);
+
+ // Insecure/harmful CSS props
+ dropAttrs = dropAttrs || Regex.IsMatch(attrs, @"\b(expression|filter|behavior|position)\s*:", reFlags);
+
+ // JavaScript URLs
+ dropAttrs = dropAttrs || Regex.IsMatch(attrs, @"\bjavascript:", reFlags);
+
+ if(dropAttrs)
+ return "<" + tag + ">";
+
+ return m.Value;
+ }, reFlags);
+
+ return html;
+ }
+
// On Init add popup div and ajaxfileupload control to support Add image
protected override void OnInit(EventArgs e) {
base.OnInit(e);
From 5572a81b2268e972a5029399cb973f50512de668 Mon Sep 17 00:00:00 2001
From: AlekseyMartynov
Date: Tue, 21 Apr 2020 14:40:26 +0300
Subject: [PATCH 2/3] Test CSS props
---
AjaxControlToolkit.Tests/HtmlEditorExtenderTests.cs | 10 ++++++++++
.../HtmlEditorExtender/HtmlEditorExtender.cs | 3 ++-
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/AjaxControlToolkit.Tests/HtmlEditorExtenderTests.cs b/AjaxControlToolkit.Tests/HtmlEditorExtenderTests.cs
index 98f20fe68..c83db08d8 100644
--- a/AjaxControlToolkit.Tests/HtmlEditorExtenderTests.cs
+++ b/AjaxControlToolkit.Tests/HtmlEditorExtenderTests.cs
@@ -110,6 +110,16 @@ public void RemoveInsecureHtml() {
var comment = "";
Assert.AreEqual(comment, html.Decode(comment));
+
+ Assert.AreEqual(
+ "",
+ html.Decode(
+ "
" +
+ "
" +
+ "
" +
+ "