endsWith()不能用于安全白名单校验,因其仅匹配后缀、不解析真实扩展名,易被路径伪造、大小写混淆、多余点号等绕过;必须先规范提取并小写转换扩展名,再用Set精确比对。
直接用 string.endswith() 校验文件扩展名存在严重安全隐患,**不能单独使用它来做安全白名单校验**。它只能作为初步筛选的辅助手段,必须配合更严格的解析和比对逻辑。
为什么 endsWith() 本身不安全?
它只检查字符串末尾是否匹配,完全不解析真实扩展名,攻击者很容易绕过:
-
伪造路径干扰:上传文件名为
"evil.jpg..\webshell.jsp","webshell.jsp".endsWith(".jsp")返回true,但实际服务器可能按.jpg处理或因路径遍历触发漏洞; -
大小写混淆:
"SCRIPT.JS".endsWith(".js")是false,但很多 Web 服务器对扩展名不区分大小写; -
多余点号或空格:如
"safe.txt."、"data.json ",endsWith(".json")会失败,但某些环境仍可能执行; -
无扩展名或点号开头:如
".htaccess"或"Dockerfile",单纯靠endsWith容易漏判或误判。
正确做法:先提取真实扩展名,再比对白名单
核心步骤是「规范解析 + 严格比对」,而不是字符串后缀匹配:
- 从原始文件名中**提取最后一段有效扩展名**(去掉路径、处理多点、忽略末尾空白);
- 将提取结果**统一转为小写**(避免大小写绕过);
- 用
Set.of(".jpg", ".png", ".pdf").contains(ext)等方式做精确匹配; - 对空扩展名或非法格式(如只有
.)明确拒绝。
示例代码(Java):
Tika










