是否可以将Json.Net设置为忽略$ type?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了是否可以将Json.Net设置为忽略$ type?相关的知识,希望对你有一定的参考价值。

观察this video on json deserialization attacks并显示这一点json,可用于在任何反序列化它的应用程序上触发任意代码执行。

Using ObjectDataProvider to execute arbitrary code

现在在我的应用程序中,我甚至从未使用过类型的json。我总是反序列化为动态对象或JObjects。我甚至不知道$type财产,直到今天早上另一个无关的谈话。

在我的json设置中是否有一种方法可以告诉它永远不会写或读取此属性?这不是我想要的东西。

答案

"$type"信息仅在TypeNameHandling被修改为TypeNameHandling.None以外的其他内容时编写 - 这是默认值。如果您从未更改过该值,则永远不会发出"$type"信息。

类似地,当"$type"(这也是默认值)时,在反序列化时忽略TypeNameHandling = TypeNameHandling.None属性,如docs中所述:

// for security TypeNameHandling is required when deserializing
Stockholder newStockholder =
  JsonConvert.DeserializeObject<Stockholder>(jsonTypeNameAuto, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto
});

如果您的代码(或代码使用的类库)中的任何内容都没有将TypeNameHandling修改为TypeNameHandling.None以外的其他内容(通过settingsJsonPropertyAttribute.TypeNameHandling等属性),则代码执行攻击无法正常工作。 (有关Json.NET的序列化程序使用的更准确的详细信息,请参阅Alvaro Muñoz & Oleksandr Mirosh's blackhat paper

另请注意,如果使用JToken.Parse()(或某些类似的静态方法,如JObject.Parse())进行语法分析而不是使用JsonSerializer.Deserialize<T>()进行反序列化,那么"$type"属性的存在将导致这些属性填充到JToken层次结构中,因为JToken.Parse()从不调用序列化程序。如果你想在解析之后去除那些"$type"属性,你可以使用JsonExtensions.RemoveTypeMetadata(this JToken root)Deserialize string that was serialized with TypeNameHandling.All来做到这一点。

话虽这么说,如果一个集合是由另一个使用TypeNameHandling.ArraysTypeNameHandling.All的应用程序序列化的,那么JSON中会有一个额外的嵌套级别。要在反序列化时去除它,请参阅IgnoreCollectionTypeConverterStrategies for migrating serialized Json.NET document between versions/formatsIgnoreArrayTypeConverterMake Json.NET ignore $type if it's incompatible

最后,如果您正在使用在属性中设置TypeNameHandling的第三方库,则可以使用How to disable TypeNameHandling when specified in attributes by using JsonSerializerSettings in Json.NET?中显示的自定义合约解析程序禁用该属性。

如果您真的担心团队中的其他人可能启用TypeNameHandling,您可以创建一个自定义ISerializationBinder,只要尝试解析类型或类型名称,就会抛出异常:

public class DisallowSerializationBindingBinder : ISerializationBinder
{
 #region ISerializationBinder Members

 public void BindToName(Type serializedType, out string assemblyName, out string typeName)
 {
  throw new JsonSerializationException("Binding of subtypes has been disabled");
 }

 public Type BindToType(string assemblyName, string typeName)
 {
  throw new JsonSerializationException("Binding of subtypes has been disabled");
 }

  #endregion
}

然后在JsonSerializerSettings中设置如下:

var settings = new JsonSerializerSettings
{
    SerializationBinder = new DisallowSerializationBindingBinder(),
};

并全局修改设置,如Set default global json serializer settings(对于控制台应用程序),How to set custom JsonSerializerSettings for Json.NET in MVC 4 Web API?(对于ASP.NET Web API)或JsonSerializerSettings and Asp.Net Core(对于asp.net核心)所示。

以上是关于是否可以将Json.Net设置为忽略$ type?的主要内容,如果未能解决你的问题,请参考以下文章

为啥当我使用 JSON.NET 反序列化时会忽略我的默认值?

JSON.Net 将集合序列化为数组数组

使用 JSON.net 将 JSON 解析为匿名对象 []

是否可以在C ++中以编程方式查询不同的DNS名称服务器,忽略系统设置?

使用 Json.Net 将 int 转换为 bool [重复]

将忽略脚本设置为 true 时,npm 的行为有何不同?