Closed Guardian-JTZ closed 2 months ago
blossom 存在任意文件上传漏洞, 同时还可以将文件上传到任意位置, 上传一些特殊的文件来将对应文件覆盖
POST /picture/file/upload HTTP/1.1 Host: 192.168.102.131:9999 Content-Length: 1416 Authorization: Bearer c23e29a1efb94189ada35a496a02b158 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.6167.85 Safari/537.36 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryIqDGz43F5B9QiIHz Accept: */* Origin: http://192.168.102.131:9999 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Connection: close ------WebKitFormBoundaryIqDGz43F5B9QiIHz Content-Disposition: form-data; name="pid" -1 ------WebKitFormBoundaryIqDGz43F5B9QiIHz Content-Disposition: form-data; name="filename" Bash.png ------WebKitFormBoundaryIqDGz43F5B9QiIHz Content-Disposition: form-data; name="repeatUpload" false ------WebKitFormBoundaryIqDGz43F5B9QiIHz Content-Disposition: form-data; name="file"; filename="Bash.png" Content-Type: image/png .... ------WebKitFormBoundaryIqDGz43F5B9QiIHz--
查看后台源码, 可以发现并没有过多的进行限制或过滤操作, 上传的文件名、文件路径全部都可以由客户端进行控制
@Transactional(rollbackFor = Exception.class) public PictureEntity insert(MultipartFile file, String filename, Long pid, Long userId, Boolean repeatUpload) { PictureEntity pic = new PictureEntity(); pic.setUserId(userId); pic.setId(PrimaryKeyUtil.nextId()); // 文件原名 pic.setSourceName(file.getOriginalFilename()); // 文件后缀, 后缀无法修改 pic.setSuffix(FileUtil.getSuffix(pic.getSourceName())); // 文件名以传入文件名为优先 if (StrUtil.isBlank(filename)) { pic.setName(file.getOriginalFilename()); } else { pic.setName(filename); if (StrUtil.isBlank(FileUtil.getSuffix(filename))) { pic.setName(filename + "." + pic.getSuffix()); } } pic.setSize(file.getSize()); final String domain = paramService.getDomain(); final String rootPath = osManager.getDefaultPath(); final String uid = "/U" + userId; final String pname = "/" + pic.getName(); // 上传文件夹为空, 则上传至默认文件夹, 默认文件夹是系统提供的无法删除的文件夹, ID为 userId * -1 if (pid == null || pid <= 0) { pic.setPid(userId * -1); pic.setPathName(rootPath + uid + pname); } else { FolderEntity folder = folderService.selectById(pid); XzException400HTTP.throwBy(ObjUtil.isNull(folder), "上传文件夹[" + pid + "]不存在, 请核对后再上传"); final String storePath = StrUtil.isBlank(folder.getStorePath()) ? "/" : folder.getStorePath(); pic.setPid(pid); pic.setPathName(rootPath + uid + storePath + pname); } pic.setPathName(pic.getPathName().replaceAll("//", "/")); pic.setUrl(domain + pic.getPathName()); PictureEntity originPic; if ((originPic = baseMapper.selectByPathName(pic.getPathName())) != null) { // 如果允许重复上传, 则修改大小 if (repeatUpload) { PictureEntity upd = new PictureEntity(); upd.setId(originPic.getId()); upd.setSize(pic.getSize()); upd.setCreTime(new Date()); baseMapper.updById(upd); pic.setId(originPic.getId()); } else { throw new XzException400HTTP("图片[" + pic.getPathName() + "]已存在, 请重命名文件或选择其他路径!"); } } else { baseMapper.insert(pic); } // 入库后进行文件上传操作 try (InputStream inputStream = file.getInputStream()) { osManager.put(pic.getPathName(), inputStream); } catch (IOException e) { throw new XzException500("图片[" + pic.getPathName() + "]上传异常,请重试"); } return pic; }
借此可以构造特殊的请求来进行上传, (为了便于演示, 我在这里修改 /etc/passwd 文件) 进入系统进行查看, 可以发现产生了对应的文件
/etc/passwd
如果遭到入侵, 攻击者可能会利用此来修改原始用户的公私钥文件或者其他配置文件造成危害
限制文件上传的路径
This issue has been open 30 days with no activity. This will be closed in 7 days.
This issue has been automatically marked as stale because it hasn't had any recent activity.
介绍
blossom 存在任意文件上传漏洞, 同时还可以将文件上传到任意位置, 上传一些特殊的文件来将对应文件覆盖
示例
查看后台源码, 可以发现并没有过多的进行限制或过滤操作, 上传的文件名、文件路径全部都可以由客户端进行控制
借此可以构造特殊的请求来进行上传, (为了便于演示, 我在这里修改
/etc/passwd
文件) 进入系统进行查看, 可以发现产生了对应的文件如果遭到入侵, 攻击者可能会利用此来修改原始用户的公私钥文件或者其他配置文件造成危害
修复
限制文件上传的路径