专栏名称: 国舜股份
移动互联网时代的综合性网络安全解决方案供应商。专业的安全产品,专业的安全服务团队,全面的安全服务资质,安全不变,国舜同行。
目录
相关文章推荐
刀法研究所  ·  文心一言宣布将全面免费;ABC回应“比基尼安 ... ·  11 小时前  
刀法研究所  ·  亲历《哪吒2》联名,这是我们的复盘和建议|A ... ·  11 小时前  
玩物志  ·  情人节甜蜜来袭|充电贴贴,爱不离线 ·  昨天  
刀法研究所  ·  资生堂2024年营业利润下滑73%;%Ara ... ·  2 天前  
玩物志  ·  瑞幸涨价,「背刺」返乡打工人 ·  3 天前  
51好读  ›  专栏  ›  国舜股份

【漏洞预警】fastjson 1.2.61远程代码执行漏洞分析&复现

国舜股份  · 公众号  ·  · 2019-09-24 13:15

正文

0x00 前言

9月19日fastjson官方发布了1.2.61新版本,增加了autoType安全黑名单。但是新版本刚发布不到一周时间,又有大佬bypass其黑名单,成功绕过了黑名单防护,可以利用fastjson反序列化特性造成RCE。从漏洞公布的poc可知这次gadget是commons-configuration组件,该组件是java应用程序的配置管理类,用于协助管理各种格式的配置文件。

0x01 影响版本

fastjson: version <= 1.2.61 ,目前官方还没发布补丁,通杀所有版本。

0x02 漏洞分析

造成漏洞的根因是fastjson反序列化JSON字符串时,会自动调用构造方法和get/setXXX方法,下面看一段fastjson反序列化JSON串的测试代码,先定义User类:

package com.blacklist.test;
public class User {
User(){ System.out.println("构造方法被自动调用!"); }
private int age; private String name; private String address;
public String getAddress() { System.out.println("getAddress方法被自动调用!"); return address; } public void setAddress(String address) { System.out.println("setAddress方法被自动调用!"); this.address = address; } public int getAge() { System.out.println("getAge方法被自动调用!"); return age; } public void setAge(int age) { System.out.println("setAge方法被自动调用!"); this.age = age; } public String getName() { System.out.println("getName方法被自动调用!"); return name; } public void setName(String name) { System.out.println("setName方法被自动调用!"); this.name = name; } //一个拥有返回值的get方法 public String getTest(){ System.out.println("getTest方法被自动调用!"); return null; }}

使用fastjson反序列化一段JSON字符串成User对象:

package com.blacklist.test;
import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.alibaba.fastjson.parser.ParserConfig;
public class ExploitMain {
public static void main(String[] args) { //使用@type指定该JSON字符串应该还原成何种类型的对象 String userInfo = "{\"@type\":\"com.blacklist.test.User\",\"name\":\"curz0n\", \"age\":18}"; //开启setAutoTypeSupport支持autoType ParserConfig.global.setAutoTypeSupport(true); //反序列化成User对象 JSONObject user = JSON.parseObject(userInfo); }}

执行代码,输出结果如下:

构造方法被自动调用!setName方法被自动调用!setAge方法被自动调用!getAddress方法被自动调用!getAge方法被自动调用!getName方法被自动调用!getTest方法被自动调用!

可以看见fastjson反序列化字符串时会依次自动调用对象的构造方法,setXXX方法,getXXX方法。注意,被反序列化的字符串中没有address和getTest方法的相关的要素,但是fastjson依然自动调用了get方法。如果这些get/setXXX方法里面存在JNDI Reference注入漏洞(

这部分知识详情可参考笔者发布的上一篇文章 《CVE-2019-14540远程代码执行漏洞分析&复现》

),那就可以借助fastjson的特性执行我们指定的任意代码,造成RCE。
从公布的poc可知这次利用的gadget是commons-configuration组件的 org.apache.commons.configuration2.JNDIConfiguration.setPrefix(final String prefix) 方法,源码如下:


    public void setPrefix(final String prefix)    {        this.prefix = prefix;
// clear the previous baseContext baseContext = null; }

setPrefix方法就是初始化成员变量,并使baseContext等于null,逻辑很简单,看不出任何问题。那我们就先看一下JNDIConfiguration的构造方法,无参构造方法调用带1个参数的构造方法,然后new一个InitialContext对象,调用带有2个参数的构造方法,代码如下所示:

    public JNDIConfiguration(final String prefix) throws NamingException    {        this(new InitialContext(), prefix);    }

带两个参数的构造方法详情如下,把InitialContext对象赋值给成员变量context:

    public JNDIConfiguration(final Context context, final String prefix)    {        this.context = context; //new InitialContext()        this.prefix = prefix;        initLogger(new ConfigurationLogger(JNDIConfiguration.class));        addErrorLogListener();    }

接着分析代码,看哪里调用了context变量,最后定位到getBaseContext方法,代码详情如下:

    public Context getBaseContext() throws NamingException    {        if (baseContext == null)        {            baseContext = (Context) getContext().lookup(prefix == null ? "" : prefix);        }
return baseContext; }

因为在setPrefix方法中设置了baseContext等于null,所以会进入if判断,接着getContext方法返回InitialContext对象,并调用lookup方法,其传入的参数变量正好是setPrefix方法设置的参数变量,可以被用户控制,这是典型的JNDI Reference注入漏洞的代码特征。因为fastjson特性,会自动调用具有返回值的getXXX方法,所以可以断定getBaseContext方法可以造成远程代码执行漏洞。

0x03 漏洞复现

环境准备

Eclipse工程结构如下:







请到「今天看啥」查看全文