代码之家  ›  专栏  ›  技术社区  ›  Anika Leser

由于json,外部json易受攻击。Net TypeNameHandling自动?

  •  18
  • Anika Leser  · 技术社区  · 7 年前

    我正在运营一个小网站,用户可以上传JSON中定义的自定义“对象”。最近,我了解到使用JSON和自动类型反序列化可能带来的威胁: JSON problem . 我想我理解这些问题,但我必须问清楚。如果我只使用给定的特定类型反序列化传入的JSON(这里 MyObject ) JsonConvert.DeserializeObject<MyObject>(json, settings); 内部无类型 MyObject(我的对象) 并且没有任何成员的子类型 MyObject(我的对象) 具有类型 System.Object dynamic 没有什么会变坏的,对吧?

    TypeNameHandling 属于 settings 设置为 TypeNameHandling.Auto (我们不要质疑这个决定,它可能会起作用 None ,但我想理解设置为 Auto .)

    编辑: 更多信息:我已经在前面提到的网站上测试了JSON:

    {
        "obj": {
            "$type": "System.IO.FileInfo, System.IO.FileSystem",
            "fileName": "rce-test.txt",
            "IsReadOnly": true
        }
    }
    

    如果 MyObject(我的对象) 有一个 系统对象 动态 类型化字段 obj 我可以复制这种威胁。但我想知道的是:即使MyObject是一个非常复杂的对象,有很多(派生的)子对象,但没有一个是或有一个 系统对象 或动态场(也不是 List<Object> )? E、 我可以想象Json。NET做了一些类似于创建对象的事情,因为 $type 信息,即使在中没有相应字段 MyObject(我的对象) 可以找到。

    1 回复  |  直到 7 年前
        1
  •  30
  •   dbc    6 年前

    TL/DR :在没有任何明显 object dynamic 成员,您 很可能 要安全,但你不是 放心 为了安全起见。为了进一步降低风险,您应该遵循 Newtonsoft documentation :

    TypeNameHandling 当应用程序从外部源反序列化JSON时,应谨慎使用。传入类型应使用自定义 SerializationBinder 使用非None的值反序列化时。

    完整答案

    中描述的攻击 How to configure Json.NET to create a vulnerable web API , TypeNameHandling caution in Newtonsoft Json 和Alvaro Mu±oz&Oleksandr Mirosh的 blackhat paper 所有这些都取决于使用 TypeNameHandling setting Json的。NET来诱使接收器构造 攻击小工具 -一种类型的实例,在构造、填充或处置时会对接收系统造成攻击。

    Json。NET做了两件有助于防范此类攻击的事情。首先,它忽略未知属性。因此,只需向JSON负载添加一个额外的未知属性,该负载的值包含 "$type" 财产不应造成损害。其次,在反序列化多态值期间,在解析 “$类型” 属性,它检查解析的类型是否与中的预期类型兼容 JsonSerializerInternalReader.ResolveTypeName() :

        if (objectType != null
    #if HAVE_DYNAMIC
            && objectType != typeof(IDynamicMetaObjectProvider)
    #endif
            && !objectType.IsAssignableFrom(specifiedType))
        {
            throw JsonSerializationException.Create(reader, "Type specified in JSON '{0}' is not compatible with '{1}'.".FormatWith(CultureInfo.InvariantCulture, specifiedType.AssemblyQualifiedName, objectType.AssemblyQualifiedName));
        }
    

    如果多态值的预期类型与任何攻击小工具类型不兼容,则攻击将失败。前提是您没有类型为的可序列化成员 对象 , 动态 IDynamicMetaObjectProvider ,这很可能是真的。但不确定!

    即使在数据模型中没有任何明显的非类型成员,也可能构造攻击小工具的情况包括:

    • 非类型化的反序列化 收藏 . 如果要反序列化任何类型的非类型集合或字典,如 ArrayList , List<object> , Dictionary<string, dynamic> HashTable ,则您的系统易受集合项中包含的小工具的攻击。

    • 对继承自的数十个集合中的任何一个进行反序列化 CollectionBase . 这种类型早于年引入泛型。Net,表示一个“半类型”集合,在该集合中,项的类型在添加时在运行时进行验证。由于验证发生在构造之后,因此存在一个窗口,可以在其中构造攻击小工具。

      样品 fiddle 只显示这个。

    • 反序列化与攻击小工具共享公共基类型或接口的值,而不仅仅是 对象 . TempFileCollection 机具 ICollection IDisposable . ObjectDataProvider 机具 INotifyPropertyChanged ISupportInitialize . 如果您有任何多态成员或值被声明为这些接口中的任何一个,则易受攻击。

    • 实现的类型的反序列化 ISerializable . Json。净额 supports this interface 默认情况下,某些外部库中看似无害的类型可能会在其流式构造函数中反序列化非类型成员,而您并不知道。

      一个明显的例子是 Sytem.Exception (或其任何子类型)反序列化非类型字典 "Data" 内部its streaming constructor 对应于非类型化词典 Exception.Data . 如果要反序列化 Exception (例如,包含在日志文件中,这是非常常见的),以下JSON应该会导致攻击:

      {
        "$type": "System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
        "ClassName": "System.Exception",
        "Message": "naughty exception",
        "Data": {
          "$type": "System.Collections.ListDictionaryInternal, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
          "data": {
            "$type": "System.IO.FileInfo, System.IO.FileSystem",
            "fileName": "rce-test.txt",
            "IsReadOnly": true    
          }
        },
      }
      

      通过设置 DefaultContractResolver.IgnoreSerializableInterface = true . 当然,这可能会导致某些的序列化出现问题。Net类库类型。

    • 反序列化标记为的类型 [Serializable] 如果设置 DefaultContractResolver.IgnoreSerializableAttribute = false . 但是,默认值为 true ,因此,如果不更改此设置,则应该可以。

    • 反序列化包含您所指定成员的类型 认为 未序列化,但如果存在,将反序列化。E、 g.考虑以下类型:

      public MyType
      {
          public object tempData;
          public bool ShouldSerializeTempData() { return false; }
      }
      

      感谢Json。净额 conditional serialization 功能 tempData 成员将永远不会被序列化,因此您可能会认为您已经清楚了。但会的 反序列化 如果存在!反编译您的代码并发现这样一个成员的攻击者将能够为 MyType .

    这正是我脑子里想出来的。如您所见,在大型对象图中,验证是否从未尝试反序列化与某个攻击小工具兼容的多态类型基本上是不重要的。因此,我强烈建议对一种习俗进行额外的保护 SerializationBinder 这确保没有意外的类型被反序列化。