c# - 由于 Json.Net TypeNameHandling auto 导致外部 json 易受攻击?

标签 c# json.net

我正在运营一个小型网站,用户可以在其中上传 JSON 中定义的自定义“对象”。最近我了解到使用 JSON 和自动类型反序列化可能存在的威胁:JSON problem .我想我明白问题所在,但我必须问清楚。如果我只用给定的特定类型反序列化传入的 JSON(这里是 MyObject)JsonConvert.DeserializeObject<MyObject>(json, settings);并且里面没有类型 MyObject并且没有 MyObject 的任何成员的子类型有类型 System.Objectdynamic没有什么会变坏的,对吧?
TypeNameHandlingsettings设置为 TypeNameHandling.Auto (让我们不要质疑这个决定,它可能适用于 None ,但我想理解它设置为 Auto 的问题。)

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

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

MyObject有一个 System.Objectdynamic输入字段obj我可以重现威胁。但我想知道的是:即使 MyObject 是一个非常复杂的对象,有很多(派生的)子对象,但没有一个是或具有 System.Object或动态字段(也不是类似 List<Object> 的东西)?例如。我可以想象 Json.NET 会因为 $type 而做一些类似创建对象的事情。信息,即使在 MyObject 中没有相应的字段可以被找寻到。

最佳答案

TL/DR : 在没有任何明显的情况下 objectdynamic成员(member)们,你们可能很安全,但不能保证你们是安全的。为了进一步降低风险,您应该遵循 Newtonsoft documentation 中的建议。 :

TypeNameHandling should be used with caution when your application deserializes JSON from an external source. Incoming types should be validated with a custom SerializationBinder when deserializing with a value other than 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 做了两件事来帮助防止此类攻击。首先,它忽略了未知的属性。因此,只需向值包含 "$type" 的 JSON 有效负载添加一个额外的未知属性即可。属性(property)不应该造成伤害。其次,在多态值的反序列化过程中,解析 "$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));
    }


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

即使您的数据模型中没有任何明显的无类型成员,也可能构建攻击小工具的情况包括:
  • 无类型集合的反序列化。如果您正在反序列化任何类型的无类型集合或字典,例如 ArrayList , List<object> , Dictionary<string, dynamic> HashTable ,那么您的系统很容易受到包含在集合项目中的小工具的攻击。
  • 对继承自 CollectionBase 的数十个集合中的任何一个进行反序列化.这种类型早于 .Net 中泛型的引入,代表一个“半类型”集合,其中项目的类型在添加时在运行时进行验证。由于验证是在构建之后进行的,因此存在一个可以构建攻击小工具的窗口。

    sample fiddle只显示这个。
  • 反序列化与攻击小工具共享公共(public)基本类型或接口(interface)的值,而不仅仅是 object . TempFileCollection 工具ICollectionIDisposable . ObjectDataProvider 工具INotifyPropertyChangedISupportInitialize .如果您有任何声明为这些接口(interface)的多态成员或值,则您很容易受到攻击。
  • 实现 ISerializable 的类型的反序列化. Json.NET supports this interface默认情况下,某些外部库中看似无害的类型可能会在您不知情的情况下反序列化其流构造函数中的无类型成员。

    一个明显的例子是 Sytem.Exception (或其任何子类型)反序列化无类型字典 "Data"在其 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 ,无需创建自定义序列化绑定(bind)器即可减轻攻击。 .当然,这可能会导致某些 .Net 类库类型的序列化出现问题。
  • 标有 [Serializable] 的反序列化类型如果您设置 DefaultContractResolver.IgnoreSerializableAttribute = false 可能会有类似的问题.但是,默认值为 true ,所以如果你不改变这个设置应该没问题。
  • 使用您认为未序列化的成员反序列化类型——但如果存在,将被反序列化。例如。考虑以下类型:
    public MyType
    {
        public object tempData;
        public bool ShouldSerializeTempData() { return false; }
    }
    

    感谢 Json.NET 的 conditional serialization功能,tempData member 永远不会被序列化,所以你可能认为你很清楚。但如果存在,它将被反序列化!反编译您的代码并注意到此类成员的攻击者将能够为 MyType 制作攻击小工具负载。 .

  • 这就是我能想到的。如您所见,验证在大型对象图中从未尝试反序列化与某些攻击小工具兼容的多态类型是非常重要的。因此,我强烈推荐自定义 SerializationBinder 的额外保护。这确保不会反序列化意外的类型。

    关于c# - 由于 Json.Net TypeNameHandling auto 导致外部 json 易受攻击?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49038055/

    相关文章:

    c# - 如何将剪贴板中的文本粘贴到文本框中的光标区域

    c# - 避免在域模型中使用 JsonIgnore 属性

    c# - 将空参数传递给 SignalR 客户端代理时为 "Value cannot be null"

    将日期解析为 MS JSON 日期格式的 Java 方法

    c# - 查询Json如何获取must数组内的元素

    c# - AllowHtml 不工作

    c# - 如何在不等待完成的情况下启动异步方法?

    c# - 使用NAudio C#减少映射扬声器和麦克风音量的延迟

    serialization - 基于查询参数的条件成员序列化?

    c# - Json.net JsonIgnore 不适用于嵌套类