技术分享使用反序列化漏洞干掉你的JMS

2019-04-04 约 2576 字 预计阅读 6 分钟

声明:本文 【技术分享使用反序列化漏洞干掉你的JMS】 由作者 笑然 于 2016-11-21 12:42:00 首发 先知社区 曾经 浏览数 4402 次

感谢 笑然 的辛苦付出!

介绍

Java反序列化漏洞大家应该都非常熟悉了,想必大家手里都有各种各样的利用这类漏洞的工具。其被称为是2015年被低估的“破坏之王”可见其影响之大。Java反序列化漏洞的成因和PHP反序列化漏洞的成因差不多,都是由于程序接收不可信的序列化数据后直接将其反序列化导致的。这又印证了那句老话:一切的输入都是有害的。

Java序列化与反序列化

Java中可以将对象序列化为字节流来方便对象的传输。在Java中很多地方都会用到对象序列化这种技术,我想这大概是Java反序列漏洞危害那么大的一个原因之一吧。在Java中有很多的看似与序列化没关系的东西都使用了序列化。比如一下的一些流行的协议,他们都是基于Java序列化的。

这样也就暴露很多潜在的攻击面。Java中只有实现了java.io.Serializable 或者 java.io.Externalizable接口的类才能被序列化和反序列化.能够被反序列的类通过使用 java.io.ObjectOutputStream 将对象转换为字节流,在通过使用 java.io.ObjectInputStream 将字节流反序列化为对象。而漏洞就发生在将输入的字节流反序列化为对象这一步。和 PHP 的反序列漏洞利用基本一致。我们能控制的有对象的属性,在Java反序列对象的过程中有一些 魔术方法会被调用比如 readObject() readResolve()等。如果某个可被反序列化的类实现了上述的某个方法,我们就有可能可以做到一些有趣的事情。下面来一个简单的Demo加深下理解。假设存在下面这样一个可被反序列化的类,同时该类在程序当前类路径中。

可以看到该类实现了 readObject 方法,在该方法中又调用了Runtime.getRuntime().exec(command) 来执行一条系统命令,其参数为类的一个属性值,而属性值是我们可控的所以我们就能实现一个代码执行了。当然现实中并没有这么直接,而是需要许多条件的,需要利用一些gadgets构造POP链实现一些有趣的事.如果目标应用使用了一些具有漏洞的库那就很简单了,直接上神奇Ysoserial生成payload发送给应用反序列化可以干掉它喽。就像这样

Java消息服务(Java Message Service)

Java 消息服务(Java Message Service,JMS)应用程序接口是一个Java 平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。下面来看看支持JMS的产品。

可以看到JMS这个东西还是很受欢迎的。下面看看JMS的一个基础的运行流程是怎么样的。

其中主要的组成部分有一些几点。

  1. JMS Broker :一般作为一个独立的服务运行,用来接受JMS的连接,并存储和分发消息.可以使用任何语言来实现。
  2. JMS Client: 与Broker交互,生产者/消费者模型,即一个客户端提交消息,一个客户端获取消息
  3. Connect : 使用一些特定的协议通信。
  4. Session: 仅仅在需要管理时使用。

下面看看怎样使用API来发送和接收JMS消息

发送消息:

接收消息

前面提到过,在Java中有很多东西都是基于序列化的,JMS也是如此.我们先来看看JMS 消息的结构.

Message主要由三部分组成,分别是Header,Properties和Body, 解释如下:

Header: 消息头,所有类型的这部分格式都是一样的

Properties: 属性,按类型可以分为应用设置的属性,标准属性和消息中间件定义的属性

Body: 消息正文,指我们具体需要消息传输的内容。

JMS 消息的类型有很多,具体为

在这么多的类型中,有一种类型的消息,促成了攻击。他就是: javax.jms.ObjectMessage ,我们来看看官网是怎么介绍它的。

可以看到这个消息内部有一个可以序列化的对象,这就有趣了。下面接着看看ObjectMessage消息是怎样定义的

它有一个 getObject 方法,这个方法会将输入的消息反序列化。现在可反序列化的点已经找到,下面就是找找怎么样实现利用了。

漏洞挖掘

针对这种漏洞的挖掘思路很简单:找到接收不可信 ObjectMessage 的地方 之后分析程序所使用的一些库,看看能不能找到一些gadgets来构造一个 POP链,实现一个漏洞利用。实际上基本所有实现了ObjectMessage的组件中,都不会对输入的消息进行身份验证,直接拿去反序列化了。下面看看最近在这方面出现的漏洞。

下面是其中一个漏洞概要的截图。

可见这类漏洞发送的罪魁祸首就是 getObject 函数接收了不可信的输入。

漏洞利用

漏洞原理搞清楚了,进行利用就非常简单了。漏洞的本质就是接收不可信数据进行反序列化。那么我们就把发送包含payload对象序列化之后的数据的ObjectMessage发送到有漏洞的程序那就ok了。

整个一个漏洞利用的流程可以用下图来形象的解释。

攻击者假装为JMS 生产者向Broker提交一个带有恶意payload的ObjectMessage之后 Broker把消息分发给 JMS消费者,其拿个这样一个消息后对其中的序列化对象部分进行反序列化,触发漏洞,然后实现代码执行。而往往JMS消费者不会只有一个,所以现实中的情况会是这样。

有趣...

在实际构造exploit时并没有上面讲的那么轻松,一个成功的exploit 所要考虑的东西还是挺多的,比如:

1.jre的版本

2.应用程序所使用的库.

3.哪些库会在程序运行时的类路径中

4.是否开启 Java Security Manager

........

单纯的手工白盒分析是非常麻烦的,于是有了下面这个黑盒自动化工具来帮助我们.

JMET(Java Message Exploitation Tool)

下载地址:https://github.com/matthiaskaiser/jmet

工具支持的应用:

实战

目标:

看看目前了解到的的信息

1.一个网络管理软件

2.运行在 Jboss 5上.

3.使用了HornetQ的 JMS实现方式

4.审计方式为 本地或者 LDAP

5.十分依赖 JMS

下面来看看JMS的攻击面:

可以看到实现了很多MessageLister 来监听消息,其中使用了TextMessage 和 ObjectMessage.下面看一个有漏洞的实现

这里调用了ObjectMessage.getObject(),那么上JMET,由于JBOSS’ HornetQ需要登录,这里提供了账号和密码.

然后服务器上就弹了一堆的计算器.

说明该程序存在漏洞

总结

1.和其他的依赖于Java序列化机制的东西一样,JMS也会受到反序列化漏洞的影响.

2.所有发现的有漏洞的JMS应用都缺少对数据输入的验证.

关键词:[‘安全技术’, ‘漏洞分析’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now