前言
无意中浏览到某小众OA官网且可以下载到源码,随机审计一波,最后成功Getshell,大佬勿喷
目录结构
环境搭建
WIN11 + PhpStudy(Mysql) + Redis + IDEA(Tomcat 8.0)
将sql文件导入到phpstudy(Mysql)中,同时启动Redis服务,配置好数据库环境
采用白+黑进行审计,从功能点出发,在个人资料处图像可以进行上传
开始抓包进行文件上传,后缀和文件内容均没有做校验,且返回上传的路径和文件名,本以为可以直接getshell,但却无法解析,且该文件并没有落地
代码审计
根据数据包的路径(/func/upload/uploadImages)直接搜索路由,成功找到上传函数
首先会对db的值进行判断,根据db的值来决定上传文件的保存方式
初始上传的时候,db=1,而if的GlobalConstant.FILE_UPLOADER_SAVE_FILE=0,故直接进入到else if
新的文件名 = 上传时间 + 10位随机数 + 原始上传文件的后缀名
String extend = FileUtils.getExtend(fileName);// 获取文件扩展名
String noextfilename = DateUtils.getDataString(DateUtils.SDF_YYYYMMDDHHMMSS) + StringUtil.random(10);//自定义文件名称
String myfilename= noextfilename+"."+extend;//自定义文件名称
文件存储在数据库中,并将文件名通过map保存,最后返回在数据包中
db可控,在上传的时候,将db=1改为db=0,进入到if
会创建新的上传目录,新的目录 = Web根目录 + upload + 上传时间(年月日),若不存在则进行新建
String realPath = request.getSession().getServletContext().getRealPath("/") + "/upload/" + strYYYYMMDD + "/";// 文件的硬盘真实路径
String path = "upload/" + strYYYYMMDD + "/";
File file = new File(realPath);
if (!file.exists()) {
file.mkdirs();// 创建根目录
}
新的文件名的命名方式跟else if基本一致,在获取文件的后缀名的时候,并未进行检查和过滤,直接进行拼接,从而造成了文件上传漏洞
最后将上传文件内容直接复制到新创建的文件
FileCopyUtils.copy(mf.getBytes(), savefile);
最后通过map进行存储,且将文件上传路径和文件名分别存储在 filePath、saveName
Map<String, Object> map = new HashMap<String, Object>();
map.put("filePath", GlobalConstant.CONFIG_FILE_SAVE_DB_URL + myfilename);
map.put("saveName", noextfilename);
上传回显的Jsp Webshell,将db在上传的时候改为db=0,成功上传,可执行命令