Java 反序列化安全实例解析
jhkk9794
8年前
<h3><strong>什么是序列化</strong></h3> <p>序列化 (Serialization)是指将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。</p> <p>简单来说:</p> <p><strong>序列化 :</strong> 将数据结构或对象转换成二进制串的过程。</p> <p><strong>反序列化 :</strong>将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/2323422f9c2a0ac48ff5fc0360f6f77c.png"></p> <p>下面是将字符串对象先进行序列化,存储到本地文件,然后再通过反序列化进行恢复的样例代码:</p> <p>public static void main(String args[]) throws Exception {</p> <p>String obj ="hello world!";</p> <p>// 将序列化对象写入文件object.db中</p> <p>FileOutputStream fos =new FileOutputStream("object.db");</p> <p>ObjectOutputStream os= new ObjectOutputStream(fos);</p> <p>os.writeObject(obj);</p> <p>os.close();</p> <p>// 从文件object.db中读取数据</p> <p>FileInputStream fis =new FileInputStream("object.db");</p> <p>ObjectInputStream ois= new ObjectInputStream(fis);</p> <p>// 通过反序列化恢复对象obj</p> <p>String obj2 =(String)ois.readObject();</p> <p>ois.close();</p> <p>}</p> <h3><strong>反序列化漏洞原理</strong></h3> <p>反序列化漏洞的本质就是反序列化机制打破了数据和对象的边界,导致攻击者注入的恶意序列化数据在反序列化过程中被还原成对象,控制了对象就可能在目标系统上面执行攻击代码。Java序列化应用于RMI JMX JMS 技术中。</p> <p>漏洞危害</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/5b0db6ef058a615ff2684d21a89e6cf9.jpg"></p> <h3><strong>案例一:Apache ActiveMQ 5.12.0 远程代码执行漏洞(JMS)</strong></h3> <p>Apache ActiveMQ 5.13.0 之前5.x版本中存在安全漏洞,该漏洞源于程序未能限制可在代理中序列化的类。远程攻击者可借助特制的序列化的Java Message Service (JMS) ObjectMessage对象利用该漏洞执行任意代码。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/c8f06954b3f14e8fc3eaaad6d7fd084e.jpg"> <img src="https://simg.open-open.com/show/6c054b88d616ba94a88aec530b747acc.jpg"> <img src="https://simg.open-open.com/show/ee71fe3f2b4dee3b712dd0d393d3a9d6.jpg"></p> <p>受到影响的消息系统如下:</p> <p>Apache ActiveMQ 5.12.0 and earlier</p> <p>HornetQ 2.4.0 and earlier</p> <p>Oracle OpenMQ 5.1 and earlier</p> <p>IBM Websphere MQ 8.0.0.4 and earlier</p> <p>Oracle Weblogic 12c and earlier</p> <p>Pivotal RabbitMQ JMS client 1.4.6 and earlier</p> <p>IBM MessageSight MessageSight V1.2 JMSClient and earlier</p> <p>SwiftMQ JMS client 9.7.3 and earlier</p> <p>Apache ActiveMQ Artemis client 1.2.0 and earlier</p> <p>Apache Qpid JMS client 0.9.0 and earlier</p> <p>Amazon SQS Java Messaging Library 1.0.0 and earlier</p> <h3><strong>案例二:JBoss 反序列化漏洞(JMX)</strong></h3> <p>Jboss 利用的是HTTP协议,可以在任何端口上运行,默认安装在8080端口中。JMX是一个java的管理协议,在Jboss中的JMXInvokerServlet可以使用HTTP协议与其进行通话。这一通信功能依赖于java的序列化类。</p> <p>本地构造恶意的序列化对象</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/e18b59c9ad1e50a727bd342af670cd95.png"></p> <p>构造恶意的序列化对象发送给目标主机:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/5e86752c4a77fb2732ef2c8771f38c76.png"></p> <p style="text-align:center"><img src="https://simg.open-open.com/show/923a4fb25c73aff89abc18636bdecc4a.jpg"></p> <p>执行系统命令:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/5247e04d04ea0b52cb031fc34df5d414.png"></p> <p>RedHat 发布JBoss相关产品的解决方案:</p> <p>https://access.redhat.com/solutions/2045023</p> <p>受影响的JBoss产品有:</p> <p>Environment</p> <p>Red Hat JBossA-MQ 6.x</p> <p>Red Hat JBossBPM Suite (BPMS) 6.x</p> <p>Red Hat JBossBRMS 6.x</p> <p>Red Hat JBossBRMS 5.x</p> <p>Red Hat JBossData Grid (JDG) 6.x</p> <p>Red Hat JBossData Virtualization (JDV) 6.x</p> <p>Red Hat JBossData Virtualization (JDV) 5.x</p> <p>Red Hat JBossEnterprise Application Platform 6.x</p> <p>Red Hat JBossEnterprise Application Platform 5.x</p> <p>Red Hat JBossEnterprise Application Platform 4.3.x</p> <p>Red Hat JBossFuse 6.x</p> <p>Red Hat JBossFuse Service Works (FSW) 6.x</p> <p>Red Hat JBossOperations Network (JBoss ON) 3.x</p> <p>Red Hat JBossPortal 6.x</p> <p>Red Hat JBossSOA Platform (SOA-P) 5.x</p> <p>Red Hat JBossWeb Server (JWS) 3.x</p> <h3><strong>案例三: Jenkins Remoting的相关API是用于实现分布式环境中master和slave节点或者master和CLI的访问,API没有身份认证并且支持序列化对象。</strong></h3> <p>CVE-2016-0788通过Jenkins Remoting巧妙地开启JRMP,JRMP触发反序列化操作,从而进行漏洞的利用。作者已经提供了完整利用POC:</p> <p>在远程服务器开启JRMI端口:</p> <p><img src="https://simg.open-open.com/show/8524008758b54ad8e459b607954f3fe3.jpg"></p> <p>连接远程服务端口,发送恶意序列化数据包:</p> <p><img src="https://simg.open-open.com/show/7a0ed5d73e3aa38fc2a8ea6cc798574e.jpg"></p> <p>这样在Jenkins的根目录就会生成一个pwned文件。</p> <p>受影响的版本:</p> <p>All Jenkins main line releases up to and including 1.649</p> <p>All Jenkins LTS releases up to and including 1.642.1</p> <p>漏洞防御</p> <p>1 、反序列化对象白名单控制,在 resolveClass 方法中校验对象名字。</p> <p>public class LookAheadObjectInputStream <strong> extends </strong></p> <p>ObjectInputStream {</p> <p><strong>ublic </strong></p> <p>LookAheadObjectInputStream(InputStreaminputStream)</p> <p><strong>hrows </strong></p> <p>IOException{</p> <p><strong>super </strong></p> <p>(inputStream);</p> <p>}</p> <p><em>/**</em></p> <p> </p> <p><em>* Only deserializeinstances of our expected Bicycle class</em></p> <p> </p> <p><em>*/</em></p> <p> </p> <p>@Override</p> <p><strong>rotected </strong> Class<?> resolveClass(ObjectStreamClass desc) <strong> throws </strong></p> <p>IOException,</p> <p>ClassNotFoundException {</p> <p><strong>if </strong> (!desc.getName().equals(Bicycle. <strong> class </strong></p> <p>.getName())) {</p> <p><strong>throw new </strong></p> <p>InvalidClassException(</p> <p> </p> <p><strong>"Unauthorized deserializationattempt" </strong></p> <p>,desc.getName());</p> <p>}</p> <p> </p> <p><strong>return super </strong></p> <p>.resolveClass(desc);</p> <p>}</p> <p>}</p> <p>2 、序列化数据采用对称加密进行传输,接口调用增加身份认证。 ( 此种方法仅仅能提升攻击成本 )</p> <p>3 、因为序列化机制不能保证数据的完整和和保密性,如果类中存在敏感数据并且那么这个类还需要序列化,需要在特定对象的一个域上关闭 serialization ,在这个域前加上关键字 transient 即可。</p> <p> </p> <p> </p> <p>来自:https://mp.weixin.qq.com/s?__biz=MjM5MDI3MjA5MQ==&mid=2697265541&idx=1&sn=f9213cc92c94b44008c88a33f0d95704&chksm=8376feb1b40177a760563756f462af90710ca674b50e960f9f94909bac7645454e1f6153fd43&mpshare=1&scene=1&srcid=1103wyXPlTkl13uzW6puDDvv&pass_ticket=cl60 V1ikV7TwRcttTGZL3I9MWyqlf/lm8pcdHbeV64=</p> <p> </p>