反序列化
原理介绍
序列化就是把对象转换成字节流,便于保存在内存、文件、数据库中;反序列化即逆过程,由字节流还原成对象。Java中的ObjectOutputStream类的writeObject()方法可以实现序列化,类ObjectInputStream类的readObject()方法用于反序列化。比如你可以将字符串对象先进行序列化,存储到本地文件,然后再通过反序列化进行恢复。
漏洞成因
序列化和反序列化本身并不存在问题。但当输入的反序列化的数据可被用户控制,那么攻击者即可通过构造恶意输入,让反序列化产生非预期的对象,在此过程中执行构造的任意代码。
例如java反序列化,漏洞发生在反序列化过程,MyObject类实现了Serializable接口,并重写了readObject()函数(从源输入流中读取字节序列,反序列化成对象)。
序列化字符解释
java反序列化
Java中的API实现:
位置: Java.io.ObjectOutputStream java.io.ObjectInputStream
序列化: ObjectOutputStream
类 --> writeObject()
注:该方法对参数指定的obj对象进行序列化,把字节序列写到一个目标输出流中
按Java的标准约定是给文件一个.ser扩展名
反序列化: ObjectInputStream
类 --> readObject()
注:该方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
使用场景:
• 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反序列化漏洞汇总
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了。