代码之家  ›  专栏  ›  技术社区  ›  George Mauer

是否可以设置Json。Net忽略$类型?

  •  8
  • George Mauer  · 技术社区  · 7 年前

    this video on json deserialization attacks 它显示了这一位json,可以用来触发任何反序列化应用程序上的任意代码执行。

    Using ObjectDataProvider to execute arbitrary code

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

    在我的json设置中是否有方法告诉它永远不要写入或读取此属性?这不是我想要的。

    2 回复  |  直到 7 年前
        1
  •  11
  •   Shimmy Weitzhandler 500 - Internal Server Error    6 年前

    "$type" 信息仅在以下情况下写入 TypeNameHandling 已修改为 TypeNameHandling.None -- 这是默认值 . 如果您从未更改该值, “$类型” 永远不会发出信息。

    类似地 “$类型” TypeNameHandling = TypeNameHandling.None (这也是违约),如 docs :

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

    如果代码(或代码使用的类库)中没有任何内容修改 TypeName处理 除了 TypeNameHandling。没有一个 (通过 settings 或属性,例如 JsonPropertyAttribute.TypeNameHandling )那么代码执行攻击就无法工作。(有关Json.NET序列化程序的用法的更多详细信息,请参阅 Alvaro Muñoz & Oleksandr Mirosh's blackhat paper .

    还请注意,如果您使用 JToken.Parse() (或类似的静态方法,如 JObject.Parse() )而不是反序列化 JsonSerializer.Deserialize<T>() 然后出现 “$类型” 属性只会导致将这些属性填充到 JToken 层次结构,自 JToken。解析() 从不调用序列化程序。如果你还想脱掉那些 “$类型” 属性解析后,可以使用 JsonExtensions.RemoveTypeMetadata(this JToken root) 从…起 Deserialize string that was serialized with TypeNameHandling.All 就是为了做到这一点。

    话虽如此,如果 收集 被另一个应用程序序列化,使用 TypeNameHandling.Arrays TypeNameHandling.All 然后JSON中会有一个额外的嵌套级别。要在反序列化时将其剥离,请参见 IgnoreCollectionTypeConverter 从…起 Strategies for migrating serialized Json.NET document between versions/formats IgnoreArrayTypeConverter 从…起 Make Json.NET ignore $type if it's incompatible .

    最后,如果您使用的是第三方库 TypeName处理 在属性中,可以使用自定义协定解析器禁用该属性,如中所示 How to disable TypeNameHandling when specified in attributes by using JsonSerializerSettings in Json.NET? .

    如果您真的担心团队中的其他人可能会 TypeName处理 ,您可以创建自定义 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核心)。

        2
  •  2
  •   Vlad    5 年前

    不幸地 TypeNameHandling.None 被忽略。但您可以使用:

    public static JsonSerializerSettings JsonSerializationSettings
            = new JsonSerializerSettings
    {
        MetadataPropertyHandling = MetadataPropertyHandling.Ignore
    };