Skip to content

Commit

Permalink
Merge branch 'release/v03.13'
Browse files Browse the repository at this point in the history
  • Loading branch information
tvatavuk committed Apr 27, 2022
2 parents 76a6c61 + f7d86a1 commit 6713ba5
Show file tree
Hide file tree
Showing 11 changed files with 215 additions and 8 deletions.
9 changes: 7 additions & 2 deletions Razor.Blade/Html5/Script.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace ToSic.Razor.Html5
using ToSic.Razor.Wip;

namespace ToSic.Razor.Html5
{
/// <summary>
/// Special tag for generating JsonLd markup
Expand All @@ -12,7 +14,10 @@ public class ScriptJsonLd : Script
public ScriptJsonLd(string content)
{
Type("application/ld+json");
TagContents = content;
// https://w3c.github.io/json-ld-syntax/#restrictions-for-contents-of-json-ld-script-elements
// Authors should avoid using character sequences in scripts embedded in HTML which may be confused
// with a comment-open, script-open, comment-close, or script-close.
TagContents = XssPrevention.JsonLdScriptEncoding(content);
}

/// <summary>
Expand Down
4 changes: 3 additions & 1 deletion Razor.Blade/Internals/Html.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
#if NET5_0_OR_GREATER
using System.Text.Json;
Expand All @@ -17,7 +19,7 @@ internal static string Encode(string value)
=> WebUtility.HtmlEncode(value)
?.Replace("&#39;", "&apos;");


/// <summary>
/// Internal string-based commands to keep data simple till ready for output
/// </summary>
Expand Down
36 changes: 36 additions & 0 deletions Razor.Blade/Internals/ReplaceExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace ToSic.Razor.Internals
{
public static class ReplaceExtension
{
/// <summary>
/// Returns a new string in which all occurrences of a specified string in the current instance are replaced with another specified string.
/// This is to be used in .NET Framework or .netstandard 2.0 because .NET 5+ already has this string.Replace() method
/// based on https://stackoverflow.com/a/36317315
/// </summary>
/// <param name="str">The string performing the replace method.</param>
/// <param name="find">The string find.</param>
/// <param name="oldValue">The string to be replaced.</param>
/// <param name="newValue">The string replace all occurrences of oldValue.</param>
/// <param name="comparisonType">Type of the comparison.</param>
/// <returns></returns>
public static string Replace(this string str, string find, string oldValue, string newValue, StringComparison comparisonType)
{
newValue = newValue ?? string.Empty;
if (string.IsNullOrEmpty(str) || string.IsNullOrEmpty(find) || string.IsNullOrEmpty(oldValue) || oldValue.Equals(newValue, comparisonType))
return str;
var findOffset = find.IndexOf(oldValue, 0, comparisonType);
if (findOffset < 0)
return str;
int foundAt;
while ((foundAt = str.IndexOf(find, 0, comparisonType)) != -1)
{
str = str.Remove(foundAt + findOffset, oldValue.Length).Insert(foundAt + findOffset, newValue);
}
return str;
}
}
}
4 changes: 2 additions & 2 deletions Razor.Blade/Razor.Blade.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net472;net5.0</TargetFrameworks>
<RootNamespace>ToSic.Razor</RootNamespace>
<Version>03.11.00</Version>
<Version>03.13.00</Version>
<AssemblyName>ToSic.Razor</AssemblyName>
<PackageId>ToSic.Razor</PackageId>
<Authors>ToSic.Razor</Authors>
Expand Down Expand Up @@ -36,7 +36,7 @@
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection">
<Version>2.2.0</Version>
<Version>2.1.1</Version>
</PackageReference>
</ItemGroup>

Expand Down
90 changes: 90 additions & 0 deletions Razor.Blade/Wip/XssPrevention.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System;
using ToSic.Razor.Internals;

namespace ToSic.Razor.Wip
{
/// <summary>
/// TODO: WIP
/// https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
/// https://cheatsheetseries.owasp.org/cheatsheets/DotNet_Security_Cheat_Sheet.html#a7-cross-site-scripting-xss
/// </summary>
public class XssPrevention
{
/// <summary>
/// Output Encoding for "JSON-LD Contexts"
/// https://w3c.github.io/json-ld-syntax/#restrictions-for-contents-of-json-ld-script-elements
/// https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#output-encoding-for-javascript-contexts
/// Authors should avoid using character sequences in scripts embedded in HTML which may be confused with a
/// comment-open, script-open, comment-close, or script-close.
/// Partial encode < and > characters with the \uXXXX unicode encoding format (X = Integer).
/// </summary>
/// <param name="unsafeJsonLd"></param>
/// <returns></returns>
public static string JsonLdScriptEncoding(string unsafeJsonLd) => unsafeJsonLd
.Replace("<!--", "<", @"\u003C", StringComparison.OrdinalIgnoreCase)
.Replace("<script", "<", @"\u003C", StringComparison.OrdinalIgnoreCase)
.Replace("-->", ">", @"\u003E", StringComparison.OrdinalIgnoreCase)
.Replace("</script", "<", @"\u003C", StringComparison.OrdinalIgnoreCase);

///// <summary>
///// Output Encoding for "HTML Contexts"
///// https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#output-encoding-for-html-contexts
///// Convert & to &amp;
///// Convert < to &lt;
///// Convert > to &gt;
///// Convert " to &quot;
///// Convert ' to &#x27;
///// Convert / to &#x2F;
///// </summary>
///// <param name="unsafeHtml"></param>
///// <returns></returns>
//internal static string HtmlEntityEncoding(string unsafeHtml) => unsafeHtml
// .Replace("&", "&amp;") // TODO: encode & only in case that unsafeHtml is not already entity encoded
// .Replace("<", "&lt;")
// .Replace(">", "&gt;")
// .Replace("\"", "&quot;")
// .Replace("'", "&apos;");

///// <summary>
///// TODO: Output Encoding for "HTML Attribute Contexts"
///// https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#output-encoding-for-html-attribute-contexts
///// Except for alphanumeric characters, encode all characters with the
///// HTML Entity &#xHH; format, including spaces. (HH = Hex Value)
///// </summary>
///// <param name="unsafeAttributeValue"></param>
///// <returns></returns>
//internal static string HtmlAttributeEncoding(string unsafeAttributeValue) => unsafeAttributeValue;

///// <summary>
///// TODO: Output Encoding for "URL Contexts"
///// https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#output-encoding-for-url-contexts
///// Standard percent encoding. URL encoding should only be used to encode parameter values,
///// not the entire URL or path fragments of a URL.
///// </summary>
///// <param name="unsafeParameterValue"></param>
///// <returns></returns>
//internal static string UrlParameterEncoding(string unsafeParameterValue) => unsafeParameterValue;

///// <summary>
///// TODO: Output Encoding for "JavaScript Contexts"
///// https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#output-encoding-for-javascript-contexts
///// Except for alphanumeric characters, encode all characters with the
///// \uXXXX unicode encoding format (X = Integer).
///// </summary>
///// <param name="unsafeJavaScript"></param>
///// <returns></returns>
//internal static string JavaScriptEncoding(string unsafeJavaScript) => unsafeJavaScript;

///// <summary>
///// TODO: Output Encoding for "CSS Contexts"
///// https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#output-encoding-for-css-contexts
///// CSS encoding supports \XX and \XXXXXX. Using a two character encode can cause problems if
///// the next character continues the encode sequence. There are two solutions:
///// (a) Add a space after the CSS encode (will be ignored by the CSS parser)
///// (b) use the full amount of CSS encoding possible by zero padding the value.
///// </summary>
///// <param name="unsafeCss"></param>
///// <returns></returns>
//internal static string CssHexEncoding(string unsafeCss) => unsafeCss;
}
}
4 changes: 2 additions & 2 deletions ToSic.Razor.Dnn/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("03.11.0.00")]
[assembly: AssemblyFileVersion("03.11.0.00")]
[assembly: AssemblyVersion("03.13.0.00")]
[assembly: AssemblyFileVersion("03.13.0.00")]
2 changes: 1 addition & 1 deletion ToSic.Razor.Dnn/ToSic_Razor_Blade_Dnn.dnn
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<dotnetnuke type="Package" version="5.0">
<packages>
<package name="ToSic.RazorBlade" type="Library" version="03.11.00">
<package name="ToSic.RazorBlade" type="Library" version="03.13.00">
<friendlyName>2sic RazorBlade</friendlyName>
<description>2sic RazorBlade</description>
<iconFile>icon.png</iconFile>
Expand Down
4 changes: 4 additions & 0 deletions ToSic.RazorBladeTests/HtmlTagsTests/ImgTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ public void ImgWithUmlaut()
public void ImgWithUmlautAndResizer()
=> Is("<img src='L%C3%A9onie%20M%C3%BCller.jpg?w=17'>", Tag.Img().Src("Léonie Müller.jpg?w=17"));

[TestMethod]
public void ImgWithMultipleParamsShouldConvertAmp()
=> Is("<img src='test.jpg?w=100&amp;h=100'>", Tag.Img().Src("test.jpg?w=100&h=100"));


[TestMethod]
public void ImgSizes()
Expand Down
31 changes: 31 additions & 0 deletions ToSic.RazorBladeTests/HtmlTagsTests/Script_JsonLdTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,36 @@ public void JsonLdObject()
new ScriptJsonLd(new { key = "value" }));
}

//[TestMethod]
//public void JsonLdStringXssExists()
//{
// Is("<script type='application/ld+json'>{\"key\":\"</script>\"}</script>",
// new ScriptJsonLd("{\"key\":\"</script>\"}"));
//}

[TestMethod]
public void ValidJsonLdString()
{
Is("<script type='application/ld+json'>{ \"name\": \"Jane Doe\", \"@context\": \"http://schema.org/\", \"@type\": \"Person\" }</script>",
new ScriptJsonLd("{ \"name\": \"Jane Doe\", \"@context\": \"http://schema.org/\", \"@type\": \"Person\" }"));
}

[TestMethod]
public void ValidJsonLdStringWithXss()
{
Is("<script type='application/ld+json'>{ \"name\": \"\\u003C/script>\\u003Cscript>\", \"@context\": \"http://schema.org/\", \"@type\": \"Person\" }</script>",
new ScriptJsonLd("{ \"name\": \"</script><script>\", \"@context\": \"http://schema.org/\", \"@type\": \"Person\" }"));
Is("<script type='application/ld+json'>{ \"name\": \"\\u003C!-- html comment --\\u003E\", \"@context\": \"http://schema.org/\", \"@type\": \"Person\" }</script>",
new ScriptJsonLd("{ \"name\": \"<!-- html comment -->\", \"@context\": \"http://schema.org/\", \"@type\": \"Person\" }"));
}

[TestMethod]
public void JsonLdObjectWithXss()
{
Is("<script type='application/ld+json'>{\"name\":\"\\u003C/script>\\u003Cscript>\"}</script>",
new ScriptJsonLd(new { name = "</script><script>" }));
Is("<script type='application/ld+json'>{\"name\":\"\\u003C!-- html comment --\\u003E\"}</script>",
new ScriptJsonLd(new { name = "<!-- html comment -->" }));
}
}
}
8 changes: 8 additions & 0 deletions ToSic.RazorBladeTests/TagTests/TagTestBase.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using ToSic.Razor.Blade;
using ToSic.Razor.Html5;
using ToSic.Razor.Markup;
Expand All @@ -11,6 +12,13 @@ namespace ToSic.RazorBladeTests.TagTests
public class TagTestBase

{
public TagTestBase()
{
// setup use of Newtonsoft.Json for serialization to
// ensure same behavior in tests as in 2sxc
Razor.StartUp.StartUp.RegisterToJson(JsonConvert.SerializeObject);
}

public void Is(string expected, TagBase result, string message = null)
{
Is(expected, result.ToString(), message);
Expand Down
31 changes: 31 additions & 0 deletions ToSic.RazorBladeTests/WIP/XssPreventionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ToSic.Razor.Wip;

namespace ToSic.RazorBladeTests.WIP
{
[TestClass]
public class XssPreventionTests
{
[TestMethod]
[DataRow("<script>alert('xss')</script><!-- html comment -->", @"\u003Cscript>alert('xss')\u003C/script>\u003C!-- html comment --\u003E")]
[DataRow(null, null)]
[DataRow("", "")]
[DataRow("nothing to do", "nothing to do")]
[DataRow("</script", "\\u003C/script")]
[DataRow("</scriptnewtag", "\\u003C/scriptnewtag")]
[DataRow("</ScRiPt>", "\\u003C/ScRiPt>")]
[DataRow("</script >", "\\u003C/script >")]
[DataRow(" </script", " \\u003C/script")]
[DataRow("\n</script\n\t>", "\n\\u003C/script\n\t>")]
[DataRow("<<<</script", "<<<\\u003C/script")]
[DataRow("<><></script", "<><>\\u003C/script")]
[DataRow("</ script >", "</ script >")]
[DataRow("< / script >", "< / script >")]
[DataRow("-->", "--\\u003E")]
[DataRow("-->>", "--\\u003E>")]
[DataRow("<-->>", "<--\\u003E>")]
[DataRow("-- >", "-- >")]
[DataRow(" --\t\n>\n ", " --\t\n>\n ")]
public void JsonLdScriptEncoding(string content, string expected) => Assert.AreEqual(expected, XssPrevention.JsonLdScriptEncoding(content));
}
}

0 comments on commit 6713ba5

Please sign in to comment.