☰
JNPF快速开发平台任意文件读取漏洞剖析与安全加固指南
2026/9/26 8:46:38 网站建设 项目流程

做Java服务端开发或者搞安全工作的人,最近应该都注意到JNPF快速开发平台爆出任意文件读取漏洞的消息。作为一套被不少企业用在内部系统搭建上的低代码平台,这个漏洞的影响范围并不小,很多用JNPF做了内部OA、CRM、审批流系统的团队,都开始紧急排查自己的部署环境。这篇文章不放出可直接复制粘贴的利用代码,而是从漏洞原理、检测思路、修复方案三个层面把这件事讲透,顺便聊聊我在实际排查同类问题时踩过的坑。无论你是负责运维、安全,还是刚好在用JNPF做二次开发,都建议耐心看完。

1. 漏洞背景:JNPF平台是什么,为什么被盯上

1.1 JNPF快速开发平台的定位

JNPF是一套基于Java的低代码快速开发平台,主打表单建模、流程引擎、权限管理和报表设计,企业可以通过拖拽配置的方式快速生成业务系统,省掉大量重复CRUD代码。很多传统企业没有专门的研发团队,或者研发资源不足,就会选择这类平台来搭内部管理系统。

我见过不少公司把JNPF部署在公网服务器上,对接企业微信、钉钉,作为移动办公入口。这种情况下,平台本身暴露在互联网上,一旦出现任意文件读取漏洞,攻击者可以直接通过HTTP请求读取服务器上的敏感文件,不需要任何前置认证。这也是为什么这类型漏洞一旦公开,修复优先级都很高。

1.2 低代码平台为什么容易出文件读取类漏洞

低代码平台的架构决定了它比普通业务系统更容易踩中文件读取类漏洞,主要有三个原因。

第一,平台为了支持头像上传、附件下载、报表导出、模板预览,会大量封装文件处理接口。这些接口为了通用性,往往通过前端传入文件名或路径参数来控制读写目标,参数一旦可以被用户篡改,就会形成漏洞入口。

第二,低代码平台面向的是非专业开发者,平台本身要隐藏底层实现细节,开发者在配置过程中很难注意到接口内部的路径校验逻辑。平台方如果安全意识不够,这些隐患就会长期存在。

第三,快速开发平台的迭代节奏太快。功能迭代优先于安全加固,版本发布周期短,很多问题来不及完整回归就被带上线。加上不少企业用的是定制版、破解版或者基线的旧版本,安全补丁根本没人跟进。

2. 任意文件读取漏洞的技术原理与根因分析

2.1 任意文件读取漏洞是怎么发生的

拿生活里的场景打个比方。一栋写字楼的门禁卡本来只能刷开你所在楼层的门,但如果物业在发卡的时候没限制楼层权限,你拿着这张卡就能刷开整栋楼所有办公室的门。任意文件读取漏洞就是类似的问题:接口的设计意图是只允许读取某个指定目录(比如附件目录)下的文件,但代码里没有把路径限制住。

具体到JNPF这种平台,常见的漏洞代码形态往往是这样的:

String fileName = request.getParameter("fileName"); File file = new File(BASE_DIR + fileName); InputStream in = new FileInputStream(file);

这段代码的问题很明显:fileName完全由前端传入,后端直接拼接路径。如果fileName被设置为../../../etc/passwd,那么实际读取的就是系统中的敏感文件。判断一个接口是否安全的重点不是看它有没有拼接路径,而是看拼接之后有没有做路径规范化校验,以及拼接后的最终路径是否仍然落在预期目录内。

2.2 常见触发点与利用链条

任意文件读取的触发点不只在文件下载接口。根据我对同类低代码平台的经验,以下几个位置都容易出现类似问题:

  • 附件下载接口,文件名参数直接从URL获取。
  • 报表导出功能,导出模板路径可控。
  • 文件预览功能,通过指定路径读取文件内容并渲染。
  • 数据导入模板下载,模板路径拼接用户输入。
  • 工作流表单自定义模板文件读取。

攻击者利用任意文件读取漏洞,通常不会直接去看/etc/passwd这种系统文件,而是按照一套固定链条往下推进。先通过漏洞读取平台配置文件和数据库连接配置,拿到数据库地址、账号密码甚至加密密钥;再尝试连接数据库读取业务数据,或者利用已有的密钥进一步解密敏感数据;如果读取到了源码文件,还能进一步做代码审计,寻找更多可利用的漏洞。

这种链条式利用方式,才是任意文件读取漏洞真正危险的地方。它看起来只是“读文件”,实际上往往是整个内网渗透的第一步跳板。

2.3 从“能读文件”到“突破边界”的升级危害

很多人对文件读取漏洞的认知停留在“能看到服务器的一些文件”,但实际危害远不止于此。我举几个真实场景。

如果服务器上存放了SSL证书私钥,攻击者读取到私钥后,配合中间人攻击或流量劫持,可以伪装成该域名对访问流量进行解密。如果读取到应用源码,攻击者可以从中分析出其他更严重的漏洞,比如SQL注入、未授权访问、反序列化点,完成从文件读取到远程命令执行的跨越。

还有一个经常被忽略的点:Java平台本身有大量依赖配置文件,比如application.yml、application.properties、logback.xml,这些文件里往往记录了数据库口令、Redis密码、消息队列配置、第三方服务密钥。很多团队习惯把生产环境的配置直接写在文件里,一旦被读取,整个系统的基础设施信息全部暴露。

所以对待任意文件读取漏洞,不能以“只是读文件,不能写文件”为由降低风险等级。在攻防实战中,这可能是最舒服的突破口。

3. 漏洞影响范围与危害评估

3.1 影响的具体对象

这个漏洞的影响对象可以拆成几个维度看。

从部署位置看,JNPF部署在公网环境的情况最危险。攻击者不需要先进入内网,直接在公网就能发起请求,探测成本极低。部署在办公内网的,风险相对略低,但一旦内网被钓鱼攻破,同样会成为横向移动的跳板。

从版本看,官方已经发布安全更新版本的,只要升级到修复版本就能解决;如果没有对应的修复版本,或者使用的是定制版、二次开发版,则需要手动修复或者考虑临时下线相关功能。

从业务形态看,使用JNPF搭建的系统通常承载审批、数据查询、客户管理等功能,这些系统内部流转的数据本身就是敏感资产。平台一旦失守,业务数据直接从文件读取环节暴露。

3.2 能读哪些文件、意味着什么

我把攻击者可能读取的文件列一个表格,每一类对应不同的风险级别。

文件类型示例被读取后的影响
应用配置文件application.yml、application.properties泄露数据库口令、加密密钥、中间件配置
源码文件Controller类、Service接口实现类便于攻击者审计更多漏洞
系统账户文件/etc/passwd、/etc/shadow识别系统账户,为暴力破解做准备
证书密钥keystore、pem、key文件威胁通信链路安全,可能造成身份仿冒
备份与日志文件数据库备份、访问日志备份泄露敏感业务数据,日志泄露用户登录信息
安装部署文档Dockerfile、启动脚本了解环境搭建细节,定位更多入口

从这张表可以看到,攻击者成功读取文件后,几乎可以拿到继续深入的所有关键信息。安全团队在做风险评级的时候,这一类漏洞至少应该定到高危级别。

4. 检测思路与验证方法

4.1 合法的检测前提

在讲检测方法之前,我必须强调一条底线:所有检测验证必须在授权范围内进行。自己搭建的测试环境随便测,公司内部的系统必须有运维或安全负责人的书面授权,测试过程中不能影响生产业务。

这个漏洞的检测核心,就是判断接口是否存在“用户可控路径未做校验”的问题。但验证过程本身要克制,不要一上来就尝试读取/etc/passwd或者数据库配置文件。一方面这类操作容易造成敏感信息泄露,形成二次风险;另一方面,很多系统对这类路径有额外防护,测试请求反而会触发告警,干扰判断。

4.2 请求特征与路径检查思路

检测思路可以从两个方向入手。

第一个方向是静态代码排查。如果你手上有JNPF的源码,直接搜索文件操作相关代码,重点关注new File()、FileInputStream、FileReader、Files.newInputStream这几个关键词,逐个检查前端传入的参数是否直接进入文件路径。

第二个方向是黑盒请求特征判断。这类漏洞在HTTP请求上的典型特征包括:URL中出现下载、预览、导出等动作关键词;请求参数中有fileName、filePath、path、template等路径相关关键词;参数值中存在相对路径或编码后的路径穿越特征。下面这段Python代码可以用作简单的特征检测:

import re def check_url(url): dangerous_keywords = ["download", "export", "preview", "getFile", "readFile"] path_params = ["fileName", "filePath", "path", "template", "realPath"] traversal_patterns = [r"\.\./", r"\.\.%2f", r"%2e%2e%2f", r"%252e%252e%252f"] for keyword in dangerous_keywords: if keyword.lower() in url.lower(): print(f"[+] 发现文件操作路径: {keyword}") for param in path_params: if param.lower() in url.lower(): print(f"[+] 发现路径参数: {param}") for pattern in traversal_patterns: if re.search(pattern, url, re.IGNORECASE): print(f"[!] 发现路径穿越特征: {pattern}")

这段代码只是辅助检测,不能只靠它判定漏洞存在。真正有效的做法是抓取正常业务流量作为基线,然后对比异常请求,看是否出现从未见过的参数组合和路径特征。

4.3 不碰文件的低风险验证方法

在确定接口存在路径参数后,验证方式要讲究。最好的做法是选取一个无害的、系统本身允许访问的公共文件作为验证目标。比如很多Java应用会包含WEB-INF/web.xml文件,由于这个文件本身就是应用结构的一部分,读取它不会直接造成严重的信息泄露风险,但足以证明路径控制失效。

验证时观察响应差异:如果请求不存在的路径返回404或空内容,而请求目标文件返回200且内容长度与文件大小匹配,说明接口确实存在任意文件读取特征。

我建议验证过程分三步走。第一步,准备一个测试环境或授权环境,并明确本次测试范围。第二步,从正常业务流量中寻找文件操作接口,确定可疑参数名。第三步,用无害文件验证,记录响应状态码和内容特征,形成截图和日志存档。整个过程不要触碰任何包含口令、密钥、证书、个人信息的敏感文件。

5. 修复方案与安全加固实践

5.1 代码层面的根因修复

最彻底的修复方式是在代码层面补齐路径校验逻辑。Java环境下,推荐使用Path.normalize()对路径做规范化,然后判断最终路径是否仍位于允许的基目录之内:

public void downloadFile(String fileName) { // 定义允许访问的基目录 Path baseDir = Paths.get("/data/app/attachments").toAbsolutePath().normalize(); // 将用户传入的文件名解析为绝对路径 Path targetPath = baseDir.resolve(fileName).toAbsolutePath().normalize(); // 校验解析后的路径是否还在基目录内 if (!targetPath.startsWith(baseDir)) { throw new SecurityException("非法文件路径"); } try (InputStream in = Files.newInputStream(targetPath)) { // 正常下载逻辑 } }

这段代码的核心逻辑是“先规范化,后判断前缀”。只做replace("../", "")这种字符串过滤是不行的,攻击者可以通过....//、URL编码、双重编码等方式绕过。使用normalize()可以自动处理.和..,再配合startsWith(baseDir)检查,就能挡住绝大部分路径穿越攻击。

另外还有一个建议:不要在URL参数中暴露真实文件路径。比较稳妥的方案是文件名使用UUID,将文件真实路径存放在服务端数据库或映射表中,用户下载时只传文件ID,由服务端做映射查询。

5.2 部署层面的加固措施

如果短时间内无法升级版本或修改代码,部署层面可以做几件事来缓解风险。

业务系统使用的操作系统账号,建议只授予文件读取所需的最小权限。JNPF部署目录之外的系统敏感文件,严格限制进程账号访问。对于Linux环境,可以通过chmod和ACL把/etc/shadow、/root目录的读取权限收紧。

应用服务器和网关层面,建议临时禁用或者隐藏不需要的文件下载、预览接口。如果JNPF提供了关闭某些功能的配置开关,先关掉。上线前排查一次原生的Tomcat/Undertow访问日志,确认当前是否有异常的路径穿越请求已经在探测。

数据库连接串和密钥不建议明文写在配置文件里,可以使用环境变量或专用的配置中心。即使某个文件被读取到,泄露的也不是真实密码。这块改造可能比较费劲,但对整体安全提升非常明显。

5.3 WAF规则与日志监控

WAF规则拦截虽然不能根除漏洞,但可以争取修复时间。以下规则特征可以作为参考:

  • 拦截URL中的../、..%2f、%2e%2e%2f、%252e%252e%252f等路径穿越特征。
  • 拦截文件名参数中出现/etc/、/root/、/proc/、/var/等绝对路径特征。
  • 拦截响应中包含application/octet-stream且Content-Length明显异常的下载行为。

日志监控同样重要。一旦漏洞公开,自动化扫描工具会在很短时间内扫描全网暴露的实例。我建议对JNPF相关的访问日志做专项告警:单IP在短时间内频繁请求文件下载接口且参数名高度一致,属于典型扫描特征;请求路径中出现平台源码中特有的目录结构,属于定向探测特征;响应状态码大量为200且Content-Length集中在敏感文件大小范围,说明可能已经被读取到了敏感内容。

6. 同类平台排查建议与踩坑记录

6.1 芋道等其他快速开发平台怎么自查

JNPF出了这个漏洞,让我第一时间想到的不是单纯修一个平台的问题,而是所有低代码、快速开发平台都该做一次自查。芋道、若依这类同类型的Java快速开发平台,底层思路都很相似:代码生成器、公共文件上传下载、模板导出、动态菜单。只要有一个平台在文件路径校验上疏忽了,其他平台大概率也存在同样的薄弱环节。

从网盘或者第三方渠道拿到的最新的平台版本,更新内容里往往只写了“新增某某功能”,没有明确列出安全修复条目。我在实际排查中发现,很多团队以为升级到最新版就安全了,结果最新版里依然带着老漏洞。这里提醒一下:软件版本更新记录,重点看“修复“、”安全“、”漏洞”这类关键词,不要只看功能更新。

如果使用的是魔改版本或者内部二次开发版本,不要轻易相信官方的修复方案,因为二次开发过程中很可能引入了新的文件操作接口,原版补丁覆盖不到。这种场景下,最稳妥的做法还是按第5节的代码方案,把全局的文件路径校验逻辑统一过一遍。

6.2 我在实际排查中踩过的坑

这次排查JNPF漏洞,我自己也踩了几个坑,分享出来免得大家重复踩。

第一个坑是只过滤了../就以为安全了。刚拿到手的时候第一反应是拦截路径穿越关键字,结果测试发现攻击者用URL编码形式,比如..%2f或者%2e%2e%2f,照样可以绕过。WAF层和代码层的过滤规则如果不做解码后的二次检查,等于没过滤。

第二个坑是多次解码导致规则失效。有些系统采用了多层转发架构,请求经过Nginx、Gateway、应用服务三层,每一层都有可能对URL做一次解码。发一次请求,路径穿越特征经过编码、再编码、再解码,最终在代码层还原成../。排查的时候只盯着最后一层应用日志看,看不到全貌。建议在网关入口做统一解码和校验,不要在每一层各管一段。

第三个坑是修了主站忘了管理后台。JNPF这类平台通常有前台业务接口和后台管理接口,漏洞很可能同时存在于两套接口。修完主站的下载接口,回头一看管理后台导出的路径参数没改,还是老代码。自查的时候一定把管理后台的功能模块单独拉出来单过一遍,别漏。

第四个坑是误伤正常业务。加过滤规则太激进,把所有包含路径参数的请求都拦了,结果正常用户上传的附件名称里带着“..”字样,直接下载不了。WAF规则上线前建议先用流量回放或者灰度验证,观察误报率,再全量开启。

6.3 内部自查清单

这里附一张自查清单,可以发给运维和开发同事照着执行。

自查项检查方法完成标准
版本确认查看当前部署版本号和官方安全通告对照明确当前版本是否受影响
源码搜索搜索new File、FileInputStream、Paths.get定位所有用户可控路径入口
路径校验检查是否存在normalize+startsWith校验所有文件读取接口均已做规范化校验
下载接口梳理下载所有提供文件下载功能的页面确保文件名参数改为ID映射方式
WAF规则添加路径穿越拦截规则并测试绕过测试全部失败
日志告警配置异常文件下载告警策略异常请求可实时告警
配置保护检查数据库口令、密钥是否明文存放敏感配置已迁移到环境变量或配置中心

把这些内容走完一遍,不敢说绝对不出问题,但至少能把同类风险的暴露面降到很低。

这次排查给我最大的感受是,低代码平台的安全问题不能只看漏洞点本身,要看整个平台的文件处理链路是否具备统一的防线。我见过太多团队在某个接口上打了补丁,结果同一条链路上还有几十个类似接口。实际在做修复的时候,与其一个接口一个接口堵,不如把文件处理的入口统一收口,做统一的路径校验和能力裁剪。这轮排查完之后,我自己的原则也变成了:凡是给用户传路径参数的接口,一律不信任前端输入,所有文件名走映射,所有路径走规范化校验。这套思路放到任何Java平台上都成立。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询