Json.NET SerializeObject转义值以防止XSS

时间:2012-05-25 14:29:25

标签: c# .net json json.net

使用Json.NET

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

返回

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

是否有可能通过SerializeObject转义值以防止恶意脚本执行?我宁愿不对对象本身进行更改。

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

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

4 个答案:

答案 0 :(得分:37)

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的金银子,但应该根据你的例子帮助你减轻它。

答案 1 :(得分:17)

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

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

答案 2 :(得分:4)

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

答案 3 :(得分: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的备注,因为它包含以开头的一系列备注,不同于默认的


我不想逃脱

需要设置

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 for UnsafeRelaxedJsonEscaping

  

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

     

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

     

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

     

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