:在没有任何明显的object
或dynamic
成员,则 很可能 是安全的,但你不能 保证 是安全的。为了进一步降低风险,您应该遵循Newtonsoft文档中的建议:
当您的应用程序从外部源反序列化JSON时,应谨慎使用TypeNameHandling。反序列化除None以外的其他值时,应使用自定义SerializationBinder验证传入的类型。
在Newtonsoft Json 和AlvaroMuñoz&Oleksandr Mirosh的blackhat论文中, 如何配置Json.NET来创建易受攻击的Web API ,TypeNameHandling警告中 描述的攻击都取决于使用Json.NET 的设置来诱骗接收者构造 -一种实例,在构造,填充或放置时会对接收系统造成攻击。TypeNameHandling
Json.NET做两件事可以帮助防止此类攻击。首先,它忽略未知属性。因此,只需向其值包含一个"$type"
属性的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)); }
如果多态值的预期类型与任何攻击小工具类型都不兼容,则攻击将失败。只要你有型的无序列化的成员object
,dynamic
或者IDynamicMetaObjectProvider
,这很可能是真的。但不确定!
即使数据模型中没有任何明显的非类型化成员,也可能构成攻击小工具的情况包括:
未类型化 集合的 反序列化。如果你是反序列化任何类型的非类型化的集合或字典,如ArrayList
,List<object>
,Dictionary<string, dynamic>
或HashTable
,那么你的系统很容易受到攻击包含在收集的物品的小工具。
对从继承的数十个集合中的任何一个进行反序列化CollectionBase
。此类型早于.Net引入泛型之前,它表示“半类型”集合,其中,项的类型在添加时会在运行时进行验证。由于验证是在构造之后进行的,因此存在一个可能会构造攻击小工具的窗口。
对与攻击工具(不仅仅是)共享通用基本类型或接口的值进行反序列化object
。 TempFileCollection
实施ICollection
和IDisposable
。 ObjectDataProvider
实施INotifyPropertyChanged
和ISupportInitialize
。如果您有任何声明为这些接口中任何一个的多态成员或值,则很容易受到攻击。
实现的类型的反序列化ISerializable
。Json.NET 默认情况下支持此接口,并且某些外部库中看似无害的类型可能会在您不知情的情况下反序列化其流构造函数中的未类型化成员。
一个明显的例子是Sytem.Exception
(或其任何子类型),它"Data"
在其流构造函数中反序列化未类型字典,该流构造函数对应于未类型字典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
}
},
}
true`](https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Serialization_DefaultContractResolver_IgnoreSerializableInterface.htm)。当然,这可能会导致某些.Net类库类型的序列化问题。
[Serializable]
如果设置,则反序列化标记为的类型可能会有类似的问题DefaultContractResolver.IgnoreSerializableAttribute = false
。但是,默认值为true
,因此,如果不更改此设置,则应该确定。
使用您 认为 未序列化的成员反序列化类型-如果存在则将反序列化。例如考虑以下类型:
public MyType
{ public object tempData; public bool ShouldSerializeTempData() { return false; } }
借助Json.NET的条件序列化功能,该tempData
成员将永远不会被序列化,因此您可能会觉得很清楚。但是,如果存在它将被反序列化 !攻击者对您的代码进行反编译,并注意到这样的成员将能够为构建攻击小工具有效载荷MyType
。
这就是我能够想到的。如您所见,验证在大型对象图中从未尝试反序列化与某些攻击小工具兼容的多态类型是很重要的。因此,我强烈建议对自定义项进行附加保护,以SerializationBinder
确保不会反序列化任何意外类型。