在反序列化之前清除 XSS JSON
cleaning JSON for XSS before deserializing
我正在使用 Newtonsoft JSON 解串器。如何清除 XSS(跨站点脚本)的 JSON?是在反序列化之前清理 JSON 字符串还是编写某种自定义 converter/sanitizer?如果是这样 - 我不是 100% 确定解决这个问题的最佳方法。
下面是一个 JSON 的例子,它注入了一个危险的脚本并且需要 "cleaning." 我想要在反序列化之前管理它。但是我们需要假设各种XSS场景,包括BASE64编码的脚本等,所以问题比简单的REGEX字符串替换更复杂。
{ "MyVar" : "hello<script>bad script code</script>world" }
这是我的反序列化器的快照(JSON -> 对象):
public T Deserialize<T>(string json)
{
T obj;
var JSON = cleanJSON(json); //OPTION 1 sanitize here
var customConverter = new JSONSanitizer();// OPTION 2 create a custom converter
obj = JsonConvert.DeserializeObject<T>(json, customConverter);
return obj;
}
JSON 是从第 3 方 UI 界面发布的,因此它相当公开,因此需要服务器端验证。从那里,它被序列化为各种对象,通常存储在数据库中,稍后在基于 HTML 的 UI 中直接检索和输出,因此必须减轻脚本注入。
有趣!!谢谢你的提问。我们通常在 Web 表单方面使用 html.urlencode。我有一个企业网站 api 运行 有这样的验证。我们创建了一个自定义正则表达式来验证。请看看这个 MSDN link。
这是为解析名为 KeyValue 的请求而创建的示例模型(比方说)
public class KeyValue
{
public string Key { get; set; }
}
第 1 步:尝试使用自定义正则表达式
var json = @"[{ 'MyVar' : 'hello<script>bad script code</script>world' }]";
JArray readArray = JArray.Parse(json);
IList<KeyValue> blogPost = readArray.Select(p => new KeyValue { Key = (string)p["MyVar"] }).ToList();
if (!Regex.IsMatch(blogPost.ToString(),
@"^[\p{L}\p{Zs}\p{Lu}\p{Ll}\']{1,40}$"))
Console.WriteLine("InValid");
// ^ means start looking at this position.
// \p{ ..} matches any character in the named character class specified by {..}.
// {L} performs a left-to-right match.
// {Lu} performs a match of uppercase.
// {Ll} performs a match of lowercase.
// {Zs} matches separator and space.
// 'matches apostrophe.
// {1,40} specifies the number of characters: no less than 1 and no more than 40.
// $ means stop looking at this position.
第 2 步: 使用 HttpUtility.UrlEncode - this newtonsoft website link 建议以下实现。
string json = @"[{ 'MyVar' : 'hello<script>bad script code</script>world' }]";
JArray readArray = JArray.Parse(json);
IList<KeyValue> blogPost = readArray.Select(p => new KeyValue {Key =HttpUtility.UrlEncode((string)p["MyVar"])}).ToList();
好的,我打算 尝试 使这篇文章简短一些,因为要写出完整的内容需要大量工作。但是,从本质上讲,您需要关注需要清理的数据的上下文。从对原始 post 的评论来看,听起来 JSON 中的某些值将用作将要呈现的 HTML,而这个 HTML 来自不受信任的来源。
第一步是提取需要作为 HTML 清理的任何 JSON 值,对于这些对象中的每一个,您需要通过 HTML 运行 它们] 解析器并删除不在白名单中的所有内容。不要忘记您还需要一个属性白名单。
HTML Agility Pack 是在 C# 中解析 HTML 的良好起点。如何做这部分在我看来是一个单独的问题 - 并且可能是链接问题的副本。
在我看来,您对 base64 字符串的担忧似乎有点过分了。这不像您可以简单地将 aW5zZXJ0IGg0eCBoZXJl
放入 HTML 文档中,浏览器将呈现它。它可以通过 javascript(您的白名单将阻止)滥用,并且在某种程度上,通过 data:
url(但这并不是那么糟糕,因为 javascript 将 运行 在数据页面的上下文中。不好,但你不会自动吞噬 cookie)。如果您必须允许 a
标签,则部分过程需要验证 URL 是 http(s)(或您想要允许的任何方案)。
理想情况下,你会避免这种不舒服的情况,而是使用类似 markdown 的东西 - 然后你可以简单地转义 HTML 字符串,但这并不总是我们可以控制的。不过,您仍然需要进行一些 URL 验证。
我正在使用 Newtonsoft JSON 解串器。如何清除 XSS(跨站点脚本)的 JSON?是在反序列化之前清理 JSON 字符串还是编写某种自定义 converter/sanitizer?如果是这样 - 我不是 100% 确定解决这个问题的最佳方法。
下面是一个 JSON 的例子,它注入了一个危险的脚本并且需要 "cleaning." 我想要在反序列化之前管理它。但是我们需要假设各种XSS场景,包括BASE64编码的脚本等,所以问题比简单的REGEX字符串替换更复杂。
{ "MyVar" : "hello<script>bad script code</script>world" }
这是我的反序列化器的快照(JSON -> 对象):
public T Deserialize<T>(string json)
{
T obj;
var JSON = cleanJSON(json); //OPTION 1 sanitize here
var customConverter = new JSONSanitizer();// OPTION 2 create a custom converter
obj = JsonConvert.DeserializeObject<T>(json, customConverter);
return obj;
}
JSON 是从第 3 方 UI 界面发布的,因此它相当公开,因此需要服务器端验证。从那里,它被序列化为各种对象,通常存储在数据库中,稍后在基于 HTML 的 UI 中直接检索和输出,因此必须减轻脚本注入。
有趣!!谢谢你的提问。我们通常在 Web 表单方面使用 html.urlencode。我有一个企业网站 api 运行 有这样的验证。我们创建了一个自定义正则表达式来验证。请看看这个 MSDN link。
这是为解析名为 KeyValue 的请求而创建的示例模型(比方说)
public class KeyValue
{
public string Key { get; set; }
}
第 1 步:尝试使用自定义正则表达式
var json = @"[{ 'MyVar' : 'hello<script>bad script code</script>world' }]";
JArray readArray = JArray.Parse(json);
IList<KeyValue> blogPost = readArray.Select(p => new KeyValue { Key = (string)p["MyVar"] }).ToList();
if (!Regex.IsMatch(blogPost.ToString(),
@"^[\p{L}\p{Zs}\p{Lu}\p{Ll}\']{1,40}$"))
Console.WriteLine("InValid");
// ^ means start looking at this position.
// \p{ ..} matches any character in the named character class specified by {..}.
// {L} performs a left-to-right match.
// {Lu} performs a match of uppercase.
// {Ll} performs a match of lowercase.
// {Zs} matches separator and space.
// 'matches apostrophe.
// {1,40} specifies the number of characters: no less than 1 and no more than 40.
// $ means stop looking at this position.
第 2 步: 使用 HttpUtility.UrlEncode - this newtonsoft website link 建议以下实现。
string json = @"[{ 'MyVar' : 'hello<script>bad script code</script>world' }]";
JArray readArray = JArray.Parse(json);
IList<KeyValue> blogPost = readArray.Select(p => new KeyValue {Key =HttpUtility.UrlEncode((string)p["MyVar"])}).ToList();
好的,我打算 尝试 使这篇文章简短一些,因为要写出完整的内容需要大量工作。但是,从本质上讲,您需要关注需要清理的数据的上下文。从对原始 post 的评论来看,听起来 JSON 中的某些值将用作将要呈现的 HTML,而这个 HTML 来自不受信任的来源。
第一步是提取需要作为 HTML 清理的任何 JSON 值,对于这些对象中的每一个,您需要通过 HTML 运行 它们] 解析器并删除不在白名单中的所有内容。不要忘记您还需要一个属性白名单。
HTML Agility Pack 是在 C# 中解析 HTML 的良好起点。如何做这部分在我看来是一个单独的问题 - 并且可能是链接问题的副本。
在我看来,您对 base64 字符串的担忧似乎有点过分了。这不像您可以简单地将 aW5zZXJ0IGg0eCBoZXJl
放入 HTML 文档中,浏览器将呈现它。它可以通过 javascript(您的白名单将阻止)滥用,并且在某种程度上,通过 data:
url(但这并不是那么糟糕,因为 javascript 将 运行 在数据页面的上下文中。不好,但你不会自动吞噬 cookie)。如果您必须允许 a
标签,则部分过程需要验证 URL 是 http(s)(或您想要允许的任何方案)。
理想情况下,你会避免这种不舒服的情况,而是使用类似 markdown 的东西 - 然后你可以简单地转义 HTML 字符串,但这并不总是我们可以控制的。不过,您仍然需要进行一些 URL 验证。