这是一个2015年的老漏洞,由于我最近在学习干系的知识,以是拿出来温习一下。

搭建测试环境

vulhub( https://github.com/phith0n/vulhub)是我学习各种漏洞的同时,创建的一个开源项目,旨在通过大略的两条命令,编译、运行一个完全的漏洞测试环境。

jspglassfishGlassFish 目次穿越破绽测试进程 Angular

如何拉取项目、安装docker和docker-compose我就不多说了,详见vulhub项目主页。
来到GlassFish这个漏洞的详细页面 https://github.com/phith0n/vulhub/tree/master/glassfish/4.1.0,可以查看一些简要解释。

在主机上拉取vulhub项目后,进入该目录,实行docker-compose build和docker-compose up -d两条命令,即可启动全体环境。

本测试环境默认对外开放两个端口:8080和4848。
8080是web运用端口,4848是管理GlassFish的端口,漏洞涌如今4848端口下,但无需登录管理员账号即可触发。

文件读取漏洞利用

漏洞事理与利用方法 https://www.trustwave.com/Resources/Security-Advisories/Advisories/TWSL2015-016/?fid=6904。
利用该目录穿越漏洞,可以列目录以及读取任意文件:

glassfish/domains/domain1/config/admin-keyfile是储存admin账号密码的文件,如上图,我们通过读取这个文件,拿到超级管理员的密码哈希
(解释一下,这个测试环境启动前,我通过修正docker-compose.yml,将超级管理员的密码改为了123456)

密码加密办法?

可见,我们读到的密码是一串base64编码后的字符串,并且得到一个关键字:ssha256,这种“加密”方法可能和sha256有关。
但,利用echo strlen(base64_decode(...));这个办法将上述base64字符串解码后丈量长度,创造长为40字节

我们知道,常见的哈希算法,md5长度为16字节,sha1长度为20字节,sha256长度为32字节,sha512长度为64字节,并没有长度为40字节的哈希算法呀?

很明显,SSHA256里该当掺杂有其他字符。

以是,我们须要研究研究GlassFish源码。
官网有SVN,但下载速率太慢。
我们可以上Github下载打包好的源码 https://github.com/dmatej/Glassfish/archive/master.zip (不过这个源码比较老了)

下载往后创造,压缩包竟然都有1个多G,在如此大的代码中,找一个哈希算法,真的不随意马虎。
不过在费尽千辛万苦后我还是找到了卖力打算哈希的类:SSHA。

https://github.com/dmatej/Glassfish/blob/master/main/nucleus/common/common-util/src/main/java/org/glassfish/security/common/SSHA.java

这个类有两个比较主要的方法,encode和compute。
compute卖力对明文进行哈希打算,encode卖力将前者的打算结果编码成base64。

encode函数剖析

先从大略的来,encode函数:

可见,该函数兼容两种哈希算法,isSHA表示的是长度为20字节的sha1,!isSHA表示的长度为32字节的sha256。

根据我们通过文件读取漏洞得到的哈希长度和SSHA256这个关键词,我可以100%推测该哈希是sha256。
看到System.arraycopy(salt, 0, res, resultLength, salt.length);这一行我就明白了:为什么我们读取到的哈希长度是40字节?

由于还有8字节是salt。
全体算法大概是这样:

hash结果是32字节,salt长度8字节,将两者拼接后base64编码,终极得到我们读取到的那个哈希值。

把稳,上述所有的算法都是“raw data”。
我们平时看到的a356f21e901b...这样的哈希结果是经由了hex编码的,本文不涉及任何hex编码。

compute函数剖析

再来剖析一下繁芜一点的函数compute:

这个函数接管三个参数:SALT、明文和算法。
其紧张过程如下:

1. 拼接明文和SALT,组成一个新的字符序列BUFF

2. 打算BUFF的哈希结果

3. 如果哈希算法是sha256,则再打算99次哈希结果,前一次的打算结果是下一次打算的参数

将全体过程翻译成PHP代码以方便理解与测试:

破解密码

测试一下我的代码是否精确。
首先通过任意文件读取漏洞读取到目标做事器密文是{SSHA256}52bI8VDr9aLll3hQHhJS/45141bDudXHDMyFx97dBzL9wVu03KQDtw==,将其进行base64解码后,拿到末端8个字节,是为salt,值为\xfd\xc1\x5b\xb4\xdc\xa4\x03\xb7。

填入php代码中,打算明文123456的结果:

可见,打算结果和我通过漏洞读取的结果同等,解释打算过程没有问题。

不过我大略看了一下,hashcat并不支持这种哈希算法,以是如果须要破解密文的话,估计得自己编写干系破解的代码了。
好在算法并不难,直策应用我给出的实例代码,循环跑字典即可。

Getshell

破解了密码,进入GlassFish后台,是可以直接getshell的。

点击Applications,右边的deploy:

支配一个新运用,直接上传war包(附件中给一个测试环境java1.8能利用的包,网上找的老版本jspspy,加上自己改了一下兼容性,然后打包了。
2016版的jspspy我没找着,该jspspy不能担保没有后门):

然后访问http://your-ip:8080/jspspy/jspspy.jsp即可,密码xxxxxx: