kkFileViews任意文件读取漏洞原理解析

在学习的过程中,了解到kkFileView存在任意文件读取、SSRF、文件上传漏洞。

为了更深刻的理解其原理,我从git拉取了项目,由于该漏洞在最新版本已经修复,所以这只是历史版本中存在的。

写这篇文章来提醒自己代码中容易出问题的地方。

环境准备

来到kkFileView官网,发现支持Gitee,直接进去用git clone下来

kkFileViews任意文件读取漏洞原理解析_第1张图片

git clone https://gitee.com/kekingcn/file-online-preview.git

闲话少叙,直接开始看源代码。

1.任意文件包含漏洞

根据其他文章介绍,版本<=3.6.0存在此漏洞。加上这个连接就可以读取服务器上的文件//getCorsFile?urlPath=file:///etc/passwd

git tag  # 查看所有标签
git checkout v3.6.0 # 切换分支

然后用idea打开这个项目,直接搜索到controller中的getCorsFile接口,源代码如下。可以看到作者本意是为了解决跨域问题,没有想到被利用读取任意文件。

在代码中也没有任何的过滤,才会导致任意文件读取漏洞。

byte[] bytes = NetUtil.downloadBytes(url.toString());罪魁祸首在于这一行代码,没有对文件路径做出任何限制。

/**
     * 根据url获取文件内容
     * 当pdfjs读取存在跨域问题的文件时将通过此接口读取
     *
     * @param urlPath  url
     * @param response response
     */
    @RequestMapping(value = "/getCorsFile", method = RequestMethod.GET)
    public void getCorsFile(String urlPath, HttpServletResponse response) {
        logger.info("下载跨域pdf文件url:{}", urlPath);
        try {
            URL url = WebUtils.normalizedURL(urlPath);
            byte[] bytes = NetUtil.downloadBytes(url.toString());
            IOUtils.write(bytes, response.getOutputStream());
        } catch (IOException | GalimatiasParseException e) {
            logger.error("下载跨域pdf文件异常,url:{}", urlPath, e);
        }
    }

本地复现一下,和预期完全一样:

kkFileViews任意文件读取漏洞原理解析_第2张图片

修复方法

现在我切换到下一个版本,来看看作者是如何修复的。

 没想到下一个版本直接v4.0.0了

git checkout v4.0.0

我发现4.0.0并没有修复,4.2.0才开始修复这个漏洞。代码如下,可以看到加了非常多的过滤。

最新版本我就不贴出来了,反正有更多的过滤。

@GetMapping("/getCorsFile")
    public void getCorsFile(String urlPath, HttpServletResponse response) throws IOException {
        try {
            urlPath = WebUtils.decodeUrl(urlPath);
        } catch (Exception ex) {
            logger.error(String.format(BASE64_DECODE_ERROR_MSG, urlPath),ex);
            return;
        }
        HttpURLConnection urlcon;
        InputStream inputStream = null;
        if (urlPath.toLowerCase().startsWith("file:") || urlPath.toLowerCase().startsWith("file%3")) {
            logger.info("读取跨域文件异常,可能存在非法访问,urlPath:{}", urlPath);
            return;
        }
        logger.info("下载跨域pdf文件url:{}", urlPath);
        if (!urlPath.toLowerCase().startsWith("ftp:")){
            try {
                URL url = WebUtils.normalizedURL(urlPath);
                urlcon=(HttpURLConnection)url.openConnection();
                urlcon.setConnectTimeout(30000);
                urlcon.setReadTimeout(30000);
                urlcon.setInstanceFollowRedirects(false);
                if (urlcon.getResponseCode() == 302 || urlcon.getResponseCode() == 301) {
                    urlcon.disconnect();
                    url =new URL(urlcon.getHeaderField("Location"));
                    urlcon=(HttpURLConnection)url.openConnection();
                }
                if (urlcon.getResponseCode() == 404 || urlcon.getResponseCode() == 403 || urlcon.getResponseCode() == 500 ) {
                    logger.error("读取跨域文件异常,url:{}", urlPath);
                    return ;
                } else {
                    if(urlPath.contains( ".svg")) {
                        response.setContentType("image/svg+xml");
                    }
                    inputStream=(url).openStream();
                    IOUtils.copy(inputStream, response.getOutputStream());
                    urlcon.disconnect();
                }
            } catch (IOException | GalimatiasParseException e) {
                logger.error("读取跨域文件异常,url:{}", urlPath);
                return ;
            } finally {
                IOUtils.closeQuietly(inputStream);
            }
        } else {
            try {
                URL url = WebUtils.normalizedURL(urlPath);
                if(urlPath.contains(".svg")) {
                    response.setContentType("image/svg+xml");
                }
                inputStream = (url).openStream();
                IOUtils.copy(inputStream, response.getOutputStream());
            } catch (IOException | GalimatiasParseException e) {
                logger.error("读取跨域文件异常,url:{}", urlPath);
                return ;
            } finally {
                IOUtils.closeQuietly(inputStream);
            }
        }
    }

引用

https://www.cnblogs.com/xbbth/p/17446987.html

你可能感兴趣的:(elasticsearch,大数据,搜索引擎)