前言

   学了一两个月的Java代码审计,对一些审计有了一定了解了。所以决定审计一下JavaWeb CMS,随便申请一下CVE。
   认真严肃的挑选了一波之后,我选择了这个CMS,可能是缘分,也可能是好玩吧。主要看的是这个项目有QQ群,可以加群讨论一下问题,方便更好的研究。先加群不说别的。gitee地址GitHub地址


环境搭建

  环境的搭建很简单,几种方式可以选择。第一种直接git项目的源码,idea打开项目,然后idea会自动导入下载maven。

第二种方式是去GitHub或者Gitee上下载发行版。
gitee下载地址
github下载地址


任意文件上传漏洞

   Arbitrary file upload vulnerability文件上传漏洞存在于管理员后台中的模板管理。




漏洞分析

   断点调试,断点设置在E:\Soures\jfinal_cms\src\main\java\com\jflyfox\modules\filemanager\FileManagerController.java模板页面的操作的都是由FileManangerController.java控制。

  1. HttpServletRequest request = getRequest();有点Java知识的人都认识这个,所以第一个断点设置在这里。
  2. 第二个断点,审计的上传漏洞,肯定设置在上传方法里。

漏洞源码

判断是否为空的操作

public JSONObject add() {
        Iterator<?> it = this.files.iterator();
        if (!it.hasNext()) {
            this.error(lang("INVALID_FILE_UPLOAD"));
            return null;
        }

   项目主说这里修改一下就好了,但默认是这样子的,可见开发者自以为是可以防止任意上传文件漏洞,但其实这里默认是这样子设置。

   默认设置是一次最多上传5个文件,文件大小不超过16MB。

long maxSize = NumberUtils.parseLong(MAX_SIZE);
                    if (getConfig("upload-size") != null) {
                        maxSize = Integer.parseInt(getConfig("upload-size"));
                        if (maxSize != 0 && item.getSize() > (maxSize * 1024 * 1024)) {
                            this.error(sprintf(lang("UPLOAD_FILES_SMALLER_THAN"), maxSize + "Mb"));
                            error = true;
                        }
                    }

   这里maxSize是默认为0。


   下面的一段代码是判断是否只能上传图片,在配置文件E:\Soures\jfinal_cms\src\main\resources\conf\filemanager.properties下可以看到文件复写和上传文件大小设置是为0的(0代表的是没有限制),默认是可以上传其他文件(upload-imagesonly=false)。

if (!isImage(item.getName())
                            && (getConfig("upload-imagesonly") != null && getConfig("upload-imagesonly").equals("true") || this.params
                            .get("type") != null && this.params.get("type").equals("Image"))) {
                        this.error(lang("UPLOAD_IMAGES_ONLY"));
                        error = true;
                    }

                    if (error) {
                        break;
                    }

   创建临时文件,后面会用到。作用是先将上传的文件以临时文件的存放着,然后把复制到上传目录下,重新命名删除临时文件。

tmpFile = new File(this.fileRoot + TMP_PATH + "filemanager_" + System.currentTimeMillis() + ".tmp");
                    File filePath = tmpFile.getParentFile();
                    if (!filePath.exists()) {
                        filePath.mkdirs();
                    }
                    item.write(tmpFile);
                }
            }

        } catch (Exception e) {
            logger.error("INVALID_FILE_UPLOAD", e);
            this.error(lang("INVALID_FILE_UPLOAD"));
        }

   文件上传后的操作,也就是上面说到的复制重命名,最后将临时文件删除。

// file rename
        try {
            if (!error && tmpFile != null) {
                String allowed[] = {".", "-"};

                if ("add".equals(params.get("mode"))) {
                    fileInfo = new JSONObject();
                    String respPath = "";

                    String currentPath = "";
                    String fileName = params.get("_fileName");
                    String filePath = "";
                    try {
                        currentPath = params.get("currentpath");
                        respPath = currentPath;
                        currentPath = new String(currentPath.getBytes("ISO8859-1"), "UTF-8"); // 中文转码
                        currentPath = getFilePath(currentPath);
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    filePath = FileManagerUtils.rebulid(this.fileRoot + currentPath);

                    LinkedHashMap<String, String> strList = new LinkedHashMap<String, String>();
                    strList.put("fileName", fileName);
                    fileName = (String) cleanString(strList, allowed).get("fileName");

                    if (getConfig("upload-overwrite").equals("false")) {
                        fileName = this.checkFilename(filePath, fileName, 0);
                    }
点击收藏 | 2 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖