草庐IT

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

coder 2024-05-29 原文

我正在运营一个小型网站,用户可以在其中上传 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# - 由于 Json.Net TypeNameHandling auto 导致外部 json 易受攻击?的更多相关文章

    1. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

      我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

    2. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

      在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

    3. c# - 如何在 ruby​​ 中调用 C# dll? - 2

      如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

    4. C# 到 Ruby sha1 base64 编码 - 2

      我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

    5. ruby-on-rails - 如何使用 Rack 接收 JSON 对象 - 2

      我有一个非常简单的RubyRack服务器,例如:app=Proc.newdo|env|req=Rack::Request.new(env).paramspreq.inspect[200,{'Content-Type'=>'text/plain'},['Somebody']]endRack::Handler::Thin.run(app,:Port=>4001,:threaded=>true)每当我使用JSON对象向服务器发送POSTHTTP请求时:{"session":{"accountId":String,"callId":String,"from":Object,"headers":

    6. 基于C#实现简易绘图工具【100010177】 - 2

      C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

    7. ruby - 用 YAML.load 解析 json 安全吗? - 2

      我正在使用ruby2.1.0我有一个json文件。例如:test.json{"item":[{"apple":1},{"banana":2}]}用YAML.load加载这个文件安全吗?YAML.load(File.read('test.json'))我正在尝试加载一个json或yaml格式的文件。 最佳答案 YAML可以加载JSONYAML.load('{"something":"test","other":4}')=>{"something"=>"test","other"=>4}JSON将无法加载YAML。JSON.load("

    8. Ruby 守护进程导致 ActiveRecord 记录器 IOError - 2

      我目前正在用Ruby编写一个项目,它使用ActiveRecordgem进行数据库交互,我正在尝试使用ActiveRecord::Base.logger记录所有数据库事件具有以下代码的属性ActiveRecord::Base.logger=Logger.new(File.open('logs/database.log','a'))这适用于迁移等(出于某种原因似乎需要启用日志记录,因为它在禁用时会出现NilClass错误)但是当我尝试运行包含调用ActiveRecord对象的线程守护程序的项目时脚本失败并出现以下错误/System/Library/Frameworks/Ruby.frame

    9. ruby - 从外部访问类的实例变量 - 2

      我理解(我认为)Ruby中类变量和类的实例变量之间的区别。我想知道如何从该类外部访问该类的实例变量。从内部(即在类方法中而不是实例方法中),它可以直接访问,但是从外部,有没有办法做MyClass.class.[@$#]variablename?我没有任何具体原因要这样做,只是学习Ruby并想知道是否可行。 最佳答案 classMyClass@my_class_instance_var="foo"class上述yield:>>foo我相信Arkku演示了如何从类外部访问类变量(@@),而不是类实例变量(@)。我从这篇文章中提取了上述内

    10. ruby - 从另一个私有(private)方法中使用 self.xxx() 调用私有(private)方法 xxx,导致错误 "private method ` xxx' called” - 2

      我正在尝试获得良好的Ruby编码风格。为防止意外调用具有相同名称的局部变量,我总是在适当的地方使用self.。但是现在我偶然发现了这个:classMyClass上面的代码导致错误privatemethodsanitize_namecalled但是当删除self.并仅使用sanitize_name时,它会起作用。这是为什么? 最佳答案 发生这种情况是因为无法使用显式接收器调用私有(private)方法,并且说self.sanitize_name是显式指定应该接收sanitize_name的对象(self),而不是依赖于隐式接收器(也是

    随机推荐