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
这确保没有意外的类型被反序列化。