freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

Z3专栏 | Java代码审计之类加载的利用
z3 2021-12-28 12:11:42 197861
所属地 辽宁省

介绍

本篇学习ClassLoader加载类。之前学习过反序列化,只要构造一段序列化数据,被java反序列化就会造成rce。而加载类,只要这个类被加载,且被初始化,就可以执行我们想要的代码,它们两个区别:

反序列化漏洞利用是通过构造利用链,利用当前环境中已有类的组合,达到调用Runtime.exec实现命令执行的目的。
加载恶意类是将恶意类加载到JVM中,当这个类被初始化时,就会执行类内的静态代码块,造成代码执行。

通过代码执行,可以调用Runtime.exec,也可以执行其它代码,所以这里的代码执行的灵活度比命令执行更高。
例如当前环境下有杀软/edr,命令执行被拦截,那我们可以执行java代码,做一些简单操作,如一些文件操作,读文件,写入webshell,做代理进内网等等。

序列化数据是对象,它包含了对象的属性,类名,但不包含方法。而ClassLoader加载的.class是字节码文件,它是类,包含了一个类的所有信息,当然也包括方法,变量(只有变量名,只有类被初始化时,变量才有值)。

URLClassLoader

测试

URLClassLoader可以加载远程class文件。

注意:在本地测试时,要删除本地生成的class,不然会先在本地查找class,如果找到,就不会去远程获取。
如图,在idea中,删除out目录下的class就可以,注意别把Main类的class删掉。

例:
将下面类编译为Test.class,放到服务器,python-m http.server 8080

编写main类,调用远程class文件,通过反射调用start函数。

运行

报错找不到Test类。在服务器上看,已经收到了请求,说明确实从远程加载了Test.class,但为什么会报错找不到Test类?

调试分析

调试下URLClassLoader.loadClass过程,看它如何加载类。首先调用了URLClassLoader父类的loadClass,然后调用了上级的loadClass(双亲委派过程)

又调用了上级loadClass

调用了最顶层的loadClass方法findBootstrapClassOrNull

然后再一层层退出,直到Application ClassLoader层,获取到类Test类

再调试看下findClass获取到Test类的过程。如图,获取到资源对象res,然后传给defineClass

在获取Resource对象res时,会经过getLoader方法时,对url判断,如果/结尾,则读取当前地址后的Test.class文件,如果不是/结尾,则把最后的文件当做压缩包读取,然后解压,读取压缩包内的Test.class文件。

当地址使用http://127.0.0.1:1234/Test.class时,会将Test.class下载到本地,并将它当做jar包(zip包)解压,获取里面的Test类。因为Test.class不是压缩包,所以抛出打开压缩包错误的异常。

继续跟踪URLClassPath类的defineClass方法。先获取到Test.class的字节码,然后将字节码信息,和字节码来源,传给了父类SecureClassLoader的defineClass。

然后就是SecureClassLoader的defineClass调用ClassLoader的defineClass,最后给了native方法defineClass1,反回一个Class对象。

所以,开始的问题解决方法就是把地址改为http://127.0.0.1:1234/
成功运行。

当通过反射调用start函数,两句话同时输出,说明loadClass过程没有对类初始化,当使用类(本例中调用了类的函数)时才对类初始化。
注意:使用Class.forName加载类,会对类进行初始化。

总结

使用URLClassLoader,传入的地址,如果以/结尾,则会当做目录,去这个目录下找类,否则就会将这个地址后的文件当做jar包,从jar包中找类。

可以直接将字节码传给SecureClassLoader或ClassLoader的defineClass方法,创建Class对象。

loadClass过程没有对类初始化,当使用类时才对类初始化。

为什么要学习URLClassLoader?因为后面学习从远程加载,很多类本质上都是通过URLClassLoader加载类。

加载字节码

上个例子调试过程中已经发现了,可以直接将字节码传给SecureClassLoader或ClassLoader的defineClass方法,创建Class对象。下面实际测试下。
首先获取字节码,由于Test.class内的二进制不能直接用可见字符串表示,所以将它使用base64编码,在调用时将它解码。

使用python将Test.class文件内的字节码通过base64编码输出(read_bin是我自定义的读取二进制的函数)。

java代码如图

成功运行,第一句话在实例化Test对象时输出,第二句在调用start方法时输出

利用TemplatesImpl加载字节码

实战漏洞利用中,很少有机会可以让我们执行代码,通过反射调用defineClass去创建类。

最常见的还是反序列化漏洞。回忆下之前学习过的CC链,其中有几条链中就遇到过,在CC2中第一次遇到,并做了详细分析。

在ysoserial中封装好了,直接调用Gadgets.createTemplatesImpl就可以获取一个命令执行的对象,

这Gadgets.createTemplatesImpl方法中,使用Javaassist动态生成字节码,并在字节码中插入静态代码

块,写入Runtime.exec方法,然后将字节码写入到TemplatesImpl对象的_bytecode变量中,还设置了_name变量。如图

构造好的这个TemplatesImpl对象只要调用newTransformer方法,就会加载字节码,就会命令执行

调用链是newTransformer->getTransletInstance->defineTransletClasses加载class

_name不设置行不行?

如图,如果不设置_name,在getTransletInstance中就会直接return,

具体TemplatesImpl对象加载字节码的过程原理,在前面CC2文章有详细分析。

下面测试下手动构造TemplatesImpl对象(之前CC2中试过用Gadgets.createTemplatesImpl构造)这里有两个坑。

在调用newTransformer方法时会用到_tfactory变量,如果不设置直接调用newTransformer方法就会报错。但是这个变量在TemplatesImpl对象反序列化时会自动生成,所以可以直接生成_tfactory变量或把TemplatesImpl对象先序列化再反序列化

字节码对应的类,要继承AbstractTranslet,才能被成功初始化,执行静态代码块

Test类代码如图

Main类如图

成功执行静态代码块的内容

本例中的字节码时我们手动编译的,但在Gadgets.createTemplatesImpl方法中可以看到,ysoserial库通过Javaassist库生成的字节码。Javaassist库暂时就先不研究了。

BCEL ClassLoader

p神文章写的很好,直接看吧 https://www.leavesongs.com/PENETRATION/where-is-bcel-classloader.html

总结

1、加载类需要用到ClassLoader,而ClassLoader有双亲委派机制,一般使用的都是AppClassLoader。

2、loadClass时会对对象初始化,但是Class.forName会对对象初始化。

3、可以通过反射,调用ClassLoader的defineClass方法,使用字节码创建Class对象。

4、可以构造TemplatesImpl对象,在反序列化时加载并初始化构造好的字节码,执行静态代码块。

# java漏洞 # java # java反序列化 # Java代码审计 # JAVA安全
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 z3 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
java代码审计学习
z3 LV.4
  • 27 文章数
  • 89 关注者
Java 反序列化回显链研究:漏洞检测工程化
2022-04-01
Z3专栏 | CommonsCollections3分析
2022-03-19
MeterSphere未授权导致的rce漏洞分析、复现、exp编写
2022-02-11
文章目录