参考文章:一次简单的私活
L@2uR1te HW专项行动小组
1.前言
有段时间没发文章了,丢点以前的存货案例出来吧。这个是之前帮朋友搞的一次私活渗透测试(合法有授权!),用到了一些有意思的小tips。还是值得分享一下的。
2.从接口未鉴权到获取源码到java代审
首先是某个后台,分析JS之后得到了一堆接口,虽然很多未鉴权啊,但是乍一看没有可以深入利用的,如果是SRC,那么高危肯定到手,但是这个私活必须得更进一步,得进一个靶标web系统的后台或者给它getshell。
在对这些未鉴权接口进行分析的时候,我注意到了这么一个接口/list,准确来说是这个接口暴露的信息:
这个接口返回的信息里有一个新的接口,/get?path= 我们前面分析JS的时候并没有获取到这个接口,从返回包信息来看,这个接口是用来读图片内容的。乍一看,path后面跟着的东西像是某种解不开的key。但是仔细看会发现,这玩意怎么这么像是把每段路径base64编码,然后用/符分割。
所以上面那一段东西实际上对应着:
Get?path=Picture/test/tmp.jpg
大部分师傅肯定马上都能反应过来,这是典型的任意文件读取/下载漏洞的特征。那我们试试吧,根据上面的规则,使用如下payload:
Li4=/Li4=/Li4=/Li4=/Li4=/Li4=/Li4=/ZXRj/cGFzc3dk
也即
../../../../../../../etc/passwd
这不就下载回来了吗?然后我就一直在玩这个任意文件下载的点,我发现这是个docker环境,而且环境有点太过简单了,绝大部分文件下载/读取深入利用的常见路径都没找到啥信息。如果能下载到这个系统的源码就好了,那么有什么办法呢?
根据经验,linux+java环境下,目录遍历漏洞是很容易和任意文件下载/读取漏洞伴生出现的。如果开发者对File()之类的文件操作类使用不当,这两个问题就会一起出现。就比如你如果传入:
../../../../etc/passwd
此时的效果是读取或者下载passwd文件
而如果你单独传入:
../../../../etc/
效果则是获取/etc/目录下所有文件。这里我们尝试一波:
此时,我们可以遍历/etc/目录了。而当目录遍历与任意文件下载一起出现时,就意味着离getshell不远了,因为这样除了可以知道各种敏感配置文件的文件名,还可以知道源码文件名,接下来只需要耐心翻看目录,找找源码即可。最后也是顺利找到了:
那么接下来就是下载分析这个文件。进来之后老惯例,先看这个任意文件下载的成因:
如图,接收path这个参数,base64解码之后没有对这个路径进行处理,直接进行获取文件信息的操作,然后进行下载,一个很经典的任意文件下载问题。
那么我们继续审计这套源码,拉到配置文件里一看,也是找到了jwt secret啊
那我们接下来的目的就很明确了,就是跟一下这套系统的jwt鉴权的逻辑,找到拦截器的实现,其中AuthenticationInterceptor这个拦截器一眼就是和鉴权有关的,跟进preHandle方法看看
首先来到这里,我们可以看到系统接收请求头中的token参数,token为JWT token。可以看到JWT主要接受了几个键值,username、user-agent、ipAddress、agentHeader。我们来一个个解决。
首先username,经过密码喷洒,我知道这套系统有一个用户名为admin的用户,那username肯定是固定为admin的,这样可以就可以过掉那个权限判断的if分支。
接下来这个分支,看到对ipAddressOld、ipAddress进行了值是否相等的判断。然后对agentHeaderOld、agentHeader进行了值是否相等的判断,两个都必须要相等,否则提示token不安全。
ipAddressOld、agentHeaderOld都是JWT中我们可以控制的键。
因此我们现在需要研究ipAddress和agentHeader是如何赋值的,ipAddress的赋值来自IpAddrUtil工具类中的getIPAddress方法:
跟进:
幸好,这个ipAddress我们可以用X-Forwarded-For进行伪造。我们再研究agentHeader如何赋值:
是直接获取的UA头,现在我们可以知道,上面提到的几个关键要素我们都可以伪造,最后可以让preHandle方法返回true通过鉴权,现在我们就可以尝试伪造一个JWT key了。
其中保持agentHeader这个键值和我们浏览器的UA一样,然后待会我们用X-Forwarded-For头伪造成127.0.0.1即可,我们来看看效果:
该接口原本没法绕过鉴权,加上token和X-Forwarded-For后,可调用该接口:
当然,这里的密码是加盐MD5,解不出来,我们这里使用add_user接口进行添加用户:
这里居然报错了,看这个报错堆栈其实可以看出来是和Base64解码有关的。定位这段代码,发现是密码需要base64编码一下:
成功添加用户
成功登入后台。
算是比较有意思的一个攻击链。
3.heapdump泄露到拿下核心数据库
听起来很夸张,但操作起来还是蛮ez的,首先是全目录扫描的时候。找到一个actuator端点泄露
下回heapdump进行分析:
可以看到有两个密码,其中比较关键的是下面这个
xxxxxxxx6379
。众所周知6379就是redis的端口号,而这里刚好是redis服务的密码。那么我们猜想目标的密码规律就是
xxxxxxxx+服务端口号
我的一个习惯就是,当获取到目标的某些密码之后,不管它是内网服务还是外网服务的密码,我都会设法给它变形、拓展,然后对目标的所有服务进行密码爆破和喷洒,有时候能有奇效。
有了这个想法,我们生成一个密码字典,对目标的外网开放端口进行密码喷洒。最后还真喷洒到一个
xxxxxxxx3306
进去一看,是他们二十多个业务的数据库,基本上核心业务都在这了。
4.结语
主要内容就是上面这些,还有一些意义不大的水洞就不记录了。本文的一个核心就在于任意文件下载/目录遍历的这个伴生问题,算是个小tips,实战中很容易被忽略,如果这个点被忽略的话,可能就没有后续的各种操作了,以后遇到相关问题可以多注意一下!