Json.NET 序列化对象转义值以防止 XSS
本文关键字:XSS 转义 NET 序列化 对象 Json | 更新日期: 2023-09-27 18:35:17
使用 Json.NET
JsonConvert.SerializeObject(new { Property = "<script>alert('o hai');</script>" })
返回
{"Property":"<script>alert('o hai');</script>"}
序列化对象是否可以转义该值以防止恶意脚本执行?我宁愿不对对象本身进行更改。
编辑:理想情况下,我想将清理集成到序列化对象调用中,而无需在序列化对象之前或之后处理对象。
编辑:JsonConvert.SerializeObject
的字符串输出被分配给脚本块中的全局变量,我相信这就是XSS问题所在。
在版本 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 的金弹,但根据您的示例,应该可以帮助您减轻它。
这可能并不理想,但这是我的解决方案(至少目前):
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
的)
在 .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"}
文档
如何在 .NET 中序列化和反序列化 JSON 在序列化行为部分中说:
默认编码器转义非 ASCII 字符、ASCII 范围内的 HTML 敏感字符以及必须根据 JSON 规范转义的字符。
另请检查 JavaScriptEncoder.UnsafeRelaxedJsonEscaping 的备注,因为它包含一系列以 Not 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
的文档
UnsafeRelaxedJsonEscaping
备注:
与默认编码器不同,此编码器实例不会转义 HTML 敏感字符,如 <、> &。因此,必须谨慎使用;例如,如果输出数据位于内容类型已知且字符集设置为 UTF-8 的响应中,则可以使用它。
与默认编码不同,引号编码为 " 而不是 ''u0022。
与默认编码(仅允许 UnicodeRanges.BasicLatin)不同,使用此编码器实例允许 UnicodeRanges.All 进行转义。
与默认编码器不同,此编码器实例允许某些其他字符(如"+")以未转义的方式进行,因此必须谨慎使用。
不,JSON.NET 是一个 JSON 序列化程序。它不是XSS消毒器。您可以从Microsoft中查看AntiXSS库。这是一篇关于 MSDN 用法的文章(有点过时,但仍然相关)。