【问题标题】:Json.NET SerializeObject escape values to prevent XSSJson.NET SerializeObject 转义值以防止 XSS
【发布时间】:2012-05-25 14:29:25
【问题描述】:

使用 Json.NET

JsonConvert.SerializeObject(new { Property = "<script>alert('o hai');</script>" })

返回

{"Property":"<script>alert('o hai');</script>"}

值是否可以被 SerializeObject 转义以防止恶意脚本执行?我不希望对对象本身进行更改。

编辑:理想情况下,我希望将清理功能集成到 SerializeObject 调用中,而不必在 SerializeObject 之前或之后处理对象。

编辑:JsonConvert.SerializeObject 的字符串输出被分配给脚本块中的全局变量,我认为这是 XSS 问题所在。

【问题讨论】:

  • 在 .NET Core 3.0 中,System.Text.Json.JsonSerializer 默认转义 html 字符。 (详见下文)

标签: c# .net json json.net


【解决方案1】:

在 version 4.5.11 中添加了实现此功能的功能

这允许您在输出中添加各种类型的转义。

这是我的 LinqPad 测试:

    var settings = new JsonSerializerSettings();

    settings.StringEscapeHandling = StringEscapeHandling.EscapeHtml;

    var output = JsonConvert.SerializeObject(new { Property = "<script>alert('o hai');</script>" }, settings);

    Debug.Print(output);

输出

{"Property":"\u003cscript\u003ealert(\u0027o hai\u0027);\u003c/script\u003e"}

作为免责声明,这不是修复 xss 的金子弹,但根据您的示例应该可以帮助您减轻一点。

【讨论】:

  • 你成就了我的一天。这消除了很多杂物。 (请注意,如果我能让他们放弃老式的 ASP.NET 并使用 Durandal,我们就不会做这种低级的废话......)
  • 要在应用程序范围内执行此操作,您可以使用JsonConvert.DefaultSettings = () =&gt; new JsonSerializerSettings { StringEscapeHandling = StringEscapeHandling.EscapeHtml };
【解决方案2】:

这可能并不理想,但这是我的解决方案(至少目前是这样):

JsonConvert.SerializeObject(new { Property = "<script>alert('o hai');</script>" }, new HtmlEncodeStringPropertiesConverter());

使用一个简单的 JsonConverter 对值执行 HtmlEncode(如果它是一个字符串)

public class HtmlEncodeStringPropertiesConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(string);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteValue(Encoder.HtmlEncode(value.ToString()));
    }
}

(Encoder 是来自 AntiXSS 库的 Microsoft.Security.Application.Encoder)

【讨论】:

  • 糟糕,前面的评论没用。
  • 你有 obj = JsonConvert.DeserializeObject(json, settings);的例子吗
【解决方案3】:

在 .NET Core 3.0 中,System.Text.Json.JsonSerializer 默认转义 html 字符。

var text = "<script>alert('o hai');</script>";

var json = System.Text.Json.JsonSerializer.Serialize(new { Property = text });

Console.WriteLine(json);

输出

// .NETCoreApp,Version=v3.0
{"Property":"\u003Cscript\u003Ealert(\u0027o hai\u0027);\u003C/script\u003E"}

文档

How to serialize and deserialize JSON in .NET 在序列化行为部分说:

default encoder 转义非 ASCII 字符、ASCII 范围内的 HTML 敏感字符以及必须根据 the JSON spec 转义的字符。

请同时查看JavaScriptEncoder.UnsafeRelaxedJsonEscaping 的备注,因为它包含一系列以Unlike the Default 开头的备注。


我不想逃避它

JavaScriptEncoder.UnsafeRelaxedJsonEscaping 需要设置为关闭默认行为。

var options = new System.Text.Json.JsonSerializerOptions() { 
  Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
var json2 = System.Text.Json.JsonSerializer.Serialize(new { Property = text }, options); 
Console.WriteLine(json2);
{"Property":"<script>alert('o hai');</script>"}

UnsafeRelaxedJsonEscaping的文档

Remarks 为UnsafeRelaxedJsonEscaping:

与默认编码器不同,此编码器实例不会转义 HTML 敏感字符,例如 、&。因此,必须谨慎使用;例如,如果输出数据在内容类型已知且字符集设置为 UTF-8 的响应中,则可以使用它。

与默认编码不同,引号被编码为 " 而不是 \u0022。

与默认编码(仅允许 UnicodeRanges.BasicLatin)不同,使用此编码器实例允许 UnicodeRanges.All 不转义。

与默认编码器不同,此编码器实例允许某些其他字符(例如“+”)不转义,因此必须谨慎使用。

【讨论】:

    【解决方案4】:

    不,JSON.NET 是一个 JSON 序列化程序。它不是 XSS 消毒剂。您可以查看 Microsoft 的 AntiXSS 库。这是关于其用法的article on MSDN(有点过时但仍然相关)。

    【讨论】:

    • 我尝试了 AntiXSS,但在处理 JsonConvert.SerializeObject(object) 返回的字符串时,我还没有找到一种方法让它不进行过多的清理。如果我可以让 AntiXSS 编码仅在可能会执行此操作的属性值上运行。
    猜你喜欢
    • 2012-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-02
    • 2014-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多