反序列化漏洞

摘要:
描述反序列化的原理:序列化是将对象转换为字节流。然而,当用户可以控制输入的反序列化数据时,序列化字符解释了Java反序列化的API实现:此方法序列化参数指定的obj对象,需要在执行反序列化的地方传入攻击者的序列化代码。通过本地java程序序列化一个带有后门漏洞的jsp(一般来说,这个jsp中的代码将是文件上传和web版本SHELL),服务器将反序列化数据并生成一个webshell文件。
反序列化

原理介绍

序列化就是把对象转换成字节流,便于保存在内存、文件、数据库中;反序列化即逆过程,由字节流还原成对象。Java中的ObjectOutputStream类的writeObject()方法可以实现序列化,类ObjectInputStream类的readObject()方法用于反序列化。比如你可以将字符串对象先进行序列化,存储到本地文件,然后再通过反序列化进行恢复。

漏洞成因

序列化和反序列化本身并不存在问题。但当输入的反序列化的数据可被用户控制,那么攻击者即可通过构造恶意输入,让反序列化产生非预期的对象,在此过程中执行构造的任意代码。

例如java反序列化,漏洞发生在反序列化过程,MyObject类实现了Serializable接口,并重写了readObject()函数(从源输入流中读取字节序列,反序列化成对象)。

序列化字符解释

反序列化漏洞第1张

java反序列化

Java中的API实现:

  位置: Java.io.ObjectOutputStream  java.io.ObjectInputStream

  序列化:ObjectOutputStream类 --> writeObject()

        注:该方法对参数指定的obj对象进行序列化,把字节序列写到一个目标输出流中
          按Java的标准约定是给文件一个.ser扩展名

  反序列化: ObjectInputStream类 --> readObject()  

        注:该方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。

反序列化漏洞第2张

使用场景:
• http参数,cookie,sesion,存储方式可能是base64(rO0),压缩后的base64(H4sl),MII等
• Servlets HTTP,Sockets,Session管理器 包含的协议就包括JMX,RMI,JMS,JNDI等(xacxed)
• xml Xstream,XMLDecoder等(HTTP Body:Content-Type:application/xml)
• json(Jackson,fastjson) http请求中包含

引发:如果Java应用对用户输入,即不可信数据做了反序列化处理,那么攻击者可以通过构造恶意输入,让反序列化产生非预期的对象,非预期的对象在产生过程中就有可能带来任意代码执行。
  
原因: 类ObjectInputStream在反序列化时,没有对生成的对象的输入做限制,使攻击者利用反射调用函数进行任意命令执行。
     CommonsCollections组件中对于集合的操作存在可以进行反射调用的方法
  
根源:Apache Commons Collections允许链式的任意的类函数反射调用
   问题函数:org.apache.commons.collections.Transformer接口

利用:要利用Java反序列化漏洞,需要在进行反序列化的地方传入攻击者的序列化代码。

思路:攻击者通过允许Java序列化协议的端口,把序列化的攻击代码上传到服务器上,再由Apache Commons Collections里的TransformedMap来执行。
   至于如何使用这个漏洞对系统发起攻击,举一个简单的思路,通过本地java程序将一个带有后门漏洞的jsp(一般来说这个jsp里的代码会是文件上传和网页版的SHELL)序列化,
将序列化后的二进制流发送给有这个漏洞的服务器,服务器会反序列化该数据的并生成一个webshell文件,然后就可以直接访问这个生成的webshell文件进行进一步利用。 

启发

开发者:
  为了确保序列化的安全性,可以对于一些敏感信息加密;
  确保对象的成员变量符合正确的约束条件;
  确保需要优化序列化的性能。
漏洞挖掘:
  (1)通过代码审计/行为分析等手段发现漏洞所在靶点
  (2)进行POC分析构造时可以利用逆推法

漏洞修补

Java反序列化漏洞的快速排查和修复方案

目前打包有apache commons collections库并且应用比较广泛的主要组件有Jenkins WebLogic Jboss WebSphere  OpenNMS。
其中Jenkins由于功能需要大都直接暴露给公网。

首先确认产品中是否包含上述5种组件
使用grep命令或者其他相关搜索命令检测上述组件安装目录是否包含库Apache Commons Collections。搜索下列jar。
commons-collections.jar
*.commons-collections.jar
apache.commons.collections.jar
*.commons-collections.*.jar
如果包含请参考下述解决方案进行修复。
通用解决方案

更新Apache Commons Collections库
  Apache Commons Collections在 3.2.2版本开始做了一定的安全处理,新版本的修复方案对相关反射调用进行了限制,对这些不安全的Java类的序列化支持增加了开关。

NibbleSecurity公司的ikkisoft在github上放出了一个临时补丁SerialKiller
  lib地址:https://github.com/ikkisoft/SerialKiller
  下载这个jar后放置于classpath,将应用代码中的java.io.ObjectInputStream替换为SerialKiller
  之后配置让其能够允许或禁用一些存在问题的类,SerialKiller有Hot-Reload,Whitelisting,Blacklisting几个特性,控制了外部输入反序列化后的可信类型。

  严格意义说起来,Java相对来说安全性问题比较少,出现的一些问题大部分是利用反射,最终用Runtime.exec(String cmd)函数来执行外部命令的。

  如果可以禁止JVM执行外部命令,未知漏洞的危害性会大大降低,可以大大提高JVM的安全性。

  禁止JVM执行外部命令,是一个简单有效的提高JVM安全性的办法。可以考虑在代码安全扫描时,加强对Runtime.exec相关代码的检测。

Weblogic反序列化漏洞汇总

反序列化漏洞第3张

CVE-2015-4852 Commons Collections

借用Java反序列化和Apache Commons Collections这一基础类库实现远程命令执行。这个漏洞横扫WebLogic、WebSphere、JBoss、Jenkins、OpenNMS的最新版。

漏洞出现在WLS Security组件,允许远程攻击者执行任意命令。攻击者通过向TCP端口7001发送T3协议流量,其中包含精心构造的序列化Java对象利用此漏洞。

(T3 协议在 WebLogic Server 和其他 Java 程序,包括客户端及其他 WebLogic Server 实例间传输数据)

Weblogic
影响版本:Oracle WebLogic Server, 10.3.6.0, 12.1.2.0, 12.1.3.0, 12.2.1.0 版本。
临时解决方案
1 使用 SerialKiller 替换进行序列化操作的 ObjectInputStream 类;
2 在不影响业务的情况下,临时删除掉项目里的
“org/apache/commons/collections/functors/InvokerTransformer.class” 文件;
官方解决方案
官方声明: http://www.oracle.com/technetwork/topics/security/alert-cve-2015-4852-2763333.html
Weblogic 用户将收到官方的修复支持

Jboss
临时解决方案
1 删除 commons-collections jar 中的 InvokerTransformer, InstantiateFactory, 和InstantiateTransfromer class 文件
官方解决方案
https://issues.apache.org/jira/browse/COLLECTIONS-580
https://access.redhat.com/solutions/2045023


jenkins
临时解决方案
  1 使用 SerialKiller 替换进行序列化操作的 ObjectInputStream 类;
  2 在不影响业务的情况下,临时删除掉项目里的“org/apache/commons/collections/functors/InvokerTransformer.class” 文件;
官方解决方案: Jenkins 发布了 安全公告 ,并且在1.638版本中修复了这个漏洞。
官方的补丁声明链接:
https://jenkins-ci.org/content/mitigating-unauthenticated-remote-code-execution-0-day-jenkins-cli
https://github.com/jenkinsci-cert/SECURITY-218


websphere
  Version8.0,Version7.0,Version8.5 and 8.5.5 Full Profile and Liberty Profile
临时解决方案
1 使用 SerialKiller 替换进行序列化操作的 ObjectInputStream 类;
2 在不影响业务的情况下,临时删除掉项目里的“org/apache/commons/collections/functors/InvokerTransformer.class” 文件
在服务器上找org/apache/commons/collections/functors/InvokerTransformer.class类的jar,目前weblogic10以后都在Oracle/Middleware/modules下    
com.bea.core.apache.commons.collections_3.2.0.jar,创建临时目录tt,解压之后删除InvokerTransformer.class类后
再改成com.bea.core.apache.commons.collections_3.2.0.jar
覆盖Oracle/Middleware/modules下,重启所有服务。如下步骤是linux详细操作方法:
A)mkdir tt
B)cp -r Oracle/Middleware/modules/com.bea.core.apache.commons.collections_3.2.0.jar ./tt
C)jar xf Oracle/Middleware/modules/com.bea.core.apache.commons.collections_3.2.0.jar
D)cd org/apache/commons/collections/functors
E)rm -rf InvokerTransformer.class
F)jar cf com.bea.core.apache.commons.collections_3.2.0.jar org/* META-INF/*
G)mv com.bea.core.apache.commons.collections_3.2.0.jar Oracle/Middleware/modules/
H)重启服务

重启服务时候要删除server-name下的cache和tmp
例如rm -rf ~/user_projects/domains/base_domain/servers/AdminServer/cache
rm -rf  ~/user_projects/domains/base_domain/servers/AdminServer/tmp

php反序列化

PHP通过serialize()unserialize()来进行序列化和反序列化。

PHP反序列化漏洞是指未对用户输入的序列化字符串进行检测,导致攻击者控制反序列化过程,在反序列化的过程中自动触发了某些魔术方法,从而导致代码执行、sql注入、目录遍历等问题。

PHP反序列化用到的魔术方法:PHP魔术方法

void __wakeup (void)  #unserialize函数会检查是否存在wakeup方法,如果存在则先调用wakeup方法,做一些必要的初始化连数据库等操作
void __construct ([ mixed $args [, $... ]] ) 
#PHP5允行在一个类中定义一个方法作为构造函数。具有构造函数的类会在每次创建新对象时先调用此方法
void __destruct (void)  
#PHP5引入析构函数的概念,析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。
public string __toString ( void )  #用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。此方法必须返回一个字符串,否则将发出一条 E_RECOVERABLE_ERROR 级别的致命错误。

PHP类中的特殊函数魔术函数在某些情况下会自动调用,如construct当一个对象被创建时调用,destruct当一个对象销毁时被调用,__toString当一个对象被当作字符串使用。
在反序列化时,如果反序列化对象中存在魔法函数,使用unserialize函数的同时也会触发,一旦能控制unserialize函数的入口,就有可能引发注入漏洞。

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";}
反序列化后脚本结束时就会调用destruct函数,同时会覆盖test变量输出hello

防御手段

weblogic防御

• 过滤T3协议,限定可连接的IP
• 设置Nginx反向代理,实现t3协议和http协议隔离
• JEP290(JDK8u121,7u131,6u141),这个机制主要是在每层反序列化过程中都加了一层黑名单处理

原生反序列化防御

• 不要反序列化不可信的数据
• 给反序列数据加密签名,并确保解密在反序列之前
• 给反序列化接口添加认证授权
• 反序列化服务只允许监听在本地或者开启相应防火墙
• 升级第三方库
• 升级JDK,JEP290


经典反序列化漏洞

Shiro RememberMe 1.2.4 反序列化命令执行漏洞

Apache Shiro 在 Java 的权限及安全验证框架中占用重要的一席之地,在它编号为550的 issue 中爆出严重的 Java 反序列化漏洞。下面,我们将模拟还原此漏洞的场景以及分析过程。

漏洞分析

从官方的 issue 上来看,漏洞的利用点是在cookie里的rememberMe参数,这个参数的值是AES加密再base64之后设置在cookie中的。在服务端对rememberMe的cookie值的操作应该是先base64解码然后AES解密再反序列化,就导致了反序列化RCE漏洞。

服务端接收rememberMe的cookie值:

rememberMe的cookie值=>base64解码=>AES解密=>反序列化

我们要利用那么POC就需要先反序列化然后再AES加密最后base64编码

Payload产生的过程:

命令=>序列化=>AES加密=>base64编码=>payloadfunction()

在shrio中AES加密有一个iv向量但是没有用到所以随机生成一个就了,重要的是密钥密钥,如果没有修改默认的密钥那么就很容易就知道密钥了,之后就是编写POC了。


Java反序列化漏洞分析

反序列化漏洞汇总

Java反序列化漏洞通用利用分析

反序列化漏洞学习笔记+靶场实战

Shiro RememberMe 1.2.4 反序列化漏洞详细复现

免责声明:文章转载自《反序列化漏洞》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Mysql全文索引的使用NPOI操作Excel简单示例下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

【封装那些事】 未利用封装

未利用封装 客户代码使用显式类型检查(使用一系列if-else或switch语句检查对象的类型),而不利用出层次结构内已封装的类型变化时,将导致这种坏味。 为什么要利用封装? 一种臭名昭著的坏味是,在客户代码中使用条件语句(if-else或switch语句)来显式地检查类型,并根据类型执行相应的操作。我们这里讨论的是:要检查的类型都封装在了层次结构中,但...

MySQL插入重复数据

MySQL中批量insert into时防止更新插入重复数据去重的方法,主要是讲到了ignore,Replace,ON DUPLICATE KEY UPDATE三种方法 方案一:使用ignore关键字 如果是用主键primary或者唯一索引unique区分了记录的唯一性,避免重复插入记录可以使用: INSERT IGNORE INTO `table_nam...

让我们一起学习如何使用AIDL,它其实并不难(Android)

前言 该篇文件讲述的是AIDL最基本的使用(创建、调用),关于对于AIDL更深的认识,在后续的随笔中,会持续与大家分享并探讨。 正文 AIDL的定义(什么是AIDL?) AIDL的应用场景(AIDL可以做什么?) 如何写一个AIDL的应用?(代码) AIDL概述(定义) AIDL:Android Interface Definition Langua...

JSP:服务器端和前端互传中文信息出现乱码

在前端和服务器端交互的过程中主要是通过HTTP协议进行交互的,而在Servlet接口中有提供一个HttpServlet类用于创建应用于HTTP协议的Servlet. 在Servlet容器中提供了ServletRequest和ServletResponse两个类,通过这两个类的对象来获得数据和发送数据。到这里我们就知道如果需要设置编码格式,那么我们就需要设置...

Java序列化(转)

引言 将 Java 对象序列化为二进制文件的 Java 序列化技术是 Java 系列技术中一个较为重要的技术点,在大部分情况下,开发人员只需要了解被序列化的类需要实现 Serializable 接口,使用 ObjectInputStream 和 ObjectOutputStream 进行对象的读写。然而在有些情况下,光知道这些还远远不够,文章列举了笔者遇到...

String中intern方法的作用

前言 读完这篇文章你可以了解,String对象在虚拟机内存中的存放,intern的作用,这么多String对象的创建到底有什么区别,String 创建的对象有几个!! 正题 先科普几个知识点1.常量池存放于方法区中 2.jdk1.6 方法区放在永久代(java堆的一部分),jdk1.7 特别将字符串常量池移动到了的堆内存中(使用参数-XX:PermSize...