由于Json.Net TypeNameHandling auto,外部JSON容易受到攻击吗? [英] External json vulnerable because of Json.Net TypeNameHandling auto?
问题描述
我正在运营一个小型网站,用户可以在其中上传JSON中定义的自定义对象".最近,我了解了使用JSON自动类型反序列化的可能威胁: 如果 TL/DR :在没有任何明显的 TypeNameHandling 外部来源.反序列化时,应使用自定义 SerializationBinder 来验证传入的类型比没有. 完整答案 Newtonsoft Json 和AlvaroMuñoz&中的TypeNameHandling注意事项Oleksandr Mirosh的 blackhat纸都取决于使用 Json.NET做两件事可以帮助防止此类攻击.首先,它忽略未知属性.因此,只需向其值包含
如果期望的多态值类型与任何攻击小工具类型都不兼容,则攻击将失败.如果您没有 即使在数据模型中没有任何明显的未类型化成员的情况下,也可能构成攻击小工具的情况包括: 未类型化的集合的反序列化.如果要反序列化任何类型的无类型集合或词典,例如 示例小提琴仅显示此内容. 反序列化与 反序列化实现 一个明显的例子是 通过设置 反序列化标记为如果您设置 反序列化类型不会被序列化-如果存在则将被反序列化.例如.考虑以下类型: 感谢Json.NET的条件序列化功能,即 这就是我能想到的.如您所见,验证在大型对象图中从未尝试反序列化与某些攻击小工具兼容的多态类型基本上是不重要的.因此,我强烈建议对自定义 I'm operating a small website where users can upload custom "objects" defined in JSON. Recently I've learned about possible threats using JSON with automatic type deserialization: JSON problem. I think I understand the problematics but I have to ask to be sure. If I only deserialize the incoming JSON with a given specific type (here Edit:
More information: I have tested the JSON from the previously mentioned website: If TL/DR: In the absence of any obvious 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. Full Answer The attacks described in How to configure Json.NET to create a vulnerable web API, TypeNameHandling caution in Newtonsoft Json and Alvaro Muñoz & Oleksandr Mirosh's blackhat paper all depend on using the Json.NET does two things that help protect against such attacks. Firstly, it ignores unknown properties. Thus simply adding an additional, unknown property to a JSON payload whose value contains a MyObject
具有System.Object
或dynamic
键入的字段obj
,我可以重现威胁.但是我想知道的是:即使MyObject是一个非常复杂的对象(包含很多(派生的)子对象,但是它们都不是System.Object
或具有System.Object
或dynamic的),我却准备不好的用户json是安全的字段(也不是List<Object>
之类的东西)?例如.我可以想象,即使没有找到MyObject
中的相应字段,由于$type
信息,Json.NET也会执行类似于创建对象的操作.object
或dynamic
成员的情况下,您可能会是安全的,但您不能保证是安全的.为了进一步降低风险,您应该遵循 Newtonsoft文档中的建议:
当您的应用程序反序列化JSON时,应谨慎使用
TypeNameHandling
设置诱骗接收者构造一个攻击小工具-这种类型的实例在构造,填充或处置时会对接收系统造成攻击. "$type"
属性的JSON有效负载中添加一个额外的未知属性,就不会造成危害.其次,在多态值的反序列化过程中,当解析"$type"
属性时,它将检查解析的类型是否与object
,dynamic
或IDynamicMetaObjectProvider
类型的可序列化成员,则可能是这样.但不确定!
. Json.NET 默认情况下支持此接口,并且有可能某些外部库中一种看似无害的类型在您不知情的情况下反序列化了其流构造器中的未类型化成员.ArrayList
,List<object>
,Dictionary<string, dynamic>
或 CollectionBase
.此类型早于.Net引入泛型之前,它表示半类型"集合,其中,项的类型在添加时会在运行时进行验证.由于验证是在构建之后进行的,因此存在一个可以构建攻击小工具的窗口.object
以外的攻击小工具共享通用基本类型或接口的值. TempFileCollection
实现ICollection
和ObjectDataProvider
实现了INotifyPropertyChanged
和ISupportInitialize
.如果您有任何声明为这些接口中任何一个的多态成员或值,那么您将很容易受到攻击.Sytem.Exception
(或其任何子类型),它在 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.IgnoreSerializableAttribute = false
.但是,默认值为true
,因此,如果不更改此设置,则应该确定.public MyType
{
public object tempData;
public bool ShouldSerializeTempData() { return false; }
}
MyType
制作攻击小工具有效载荷.SerializationBinder
的附加保护这样可以确保不会反序列化任何意外的类型.MyObject
) JsonConvert.DeserializeObject<MyObject>(json, settings);
and no type inside MyObject
and no subtype of any member of MyObject
has the type System.Object
or dynamic
there is nothing that can go bad, right?TypeNameHandling
of settings
is set to TypeNameHandling.Auto
(let's not question this decision it probably could work with None
, but I want to understand the question with it set to Auto
.){
"obj": {
"$type": "System.IO.FileInfo, System.IO.FileSystem",
"fileName": "rce-test.txt",
"IsReadOnly": true
}
}
MyObject
has a System.Object
or dynamic
typed field obj
I can reproduce the threat. But what I want to know: I'm on the safe side with bad prepared user-json even if MyObject is a very complex Object with lots of (derived) sub objects but NONE of them is or has a System.Object
or a dynamic field (also not something like List<Object>
)? E.g. I could imagine that Json.NET does something like creating objects because of the $type
information even if no according field in MyObject
can be found.object
or dynamic
members, you may well be safe, but you are not guaranteed to be safe. To further decrease your risk you should follow the recommendations from the Newtonsoft documentation:
TypeNameHandling
setting of Json.NET to trick the receiver into constructing an attack gadget - a instance of a type that when constructed, populated or disposed effects an attack on the receiving system. "$type"
property should do no harm. Secondly, during deserialization of a polymorphic value, when resolving the "$type"
property, it checks to see whether the resolved type is compatible with the expected type in 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));
}
If the expected type of the polymorphic value is not compatible with any attack gadget type, the attack will fail. Provided you have no serializable members of type object
, dynamic
or IDynamicMetaObjectProvider
, this is likely to be true. But not certain!
Cases in which an attack gadget might get constructed even without any obvious untyped members in your data model include:
Deserialization of untyped collections. If you are deserializing any sort of untyped collection or dictionary such as
ArrayList
,List<object>
,Dictionary<string, dynamic>
orHashTable
, then your system is vulnerable to attack gadgets contained in the collection's items.Deserialization of any of the dozens of collections inheriting from
CollectionBase
. This type predates the introduction of generics in .Net and represents a "semi-typed" collection, in which the types of the items are validated in runtime as they are added. Since the validation occurs after construction, there is a window in which an attack gadget might get constructed.Sample fiddle showing just this.
Deserialization of values that share a common base type or interface with an attack gadget other than just
object
.TempFileCollection
implementsICollection
andIDisposable
.ObjectDataProvider
implementsINotifyPropertyChanged
andISupportInitialize
. If you have any polymorphic members or values that are declared to be any of these interfaces, you are vulnerable.Deserialization of types that implement
ISerializable
. Json.NET supports this interface by default, and it is possible that a seemingly-harmless type in some external library is deserializing untyped members inside its streaming constructor without your knowledge.One obvious example is
Sytem.Exception
(or any of its subtypes) which deserializes an untyped dictionary"Data"
inside its streaming constructor which corresponds to the untyped dictionaryException.Data
. If you are deserializing anException
(contained in a log file for example, which is very common), the following JSON should effect an attack:{ "$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 } }, }
The attack can be mitigated without creation of a custom serialization binder by setting
DefaultContractResolver.IgnoreSerializableInterface = true
. Of course, this may cause problems with serialization of certain .Net class library types.Deserializing types marked with
[Serializable]
can have a similar problem if you setDefaultContractResolver.IgnoreSerializableAttribute = false
. However, the default istrue
, so you should be OK if you don't change this setting.Deserializing types with members that you think are not serialized -- but will be deserialized if present. E.g. consider the following type:
public MyType { public object tempData; public bool ShouldSerializeTempData() { return false; } }
Thanks to Json.NET's conditional serialization functionality, the
tempData
member will never be serialized, so you might think you're in the clear. But it will be deserialized if present! An attacker who decompiles your code and notices such a member will be able to craft an attack gadget payload forMyType
.
And that's just what I was able to think of off the top of my head. As you can see, verifying that, in a large object graph, there is never an attempt to deserialize a polymorphic type that is compatible with some attack gadget is substantially nontrivial. Thus I'd strongly recommend the additional protection of a custom SerializationBinder
that ensures that no unexpected types are deserialized.
这篇关于由于Json.Net TypeNameHandling auto,外部JSON容易受到攻击吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!