Node.js:通过Express参数获取文件是否安全?需防注入吗?
你的这段Node.js路由代码存在严重安全风险,必须修复!
嘿,这段代码绝对不安全,而且存在典型的路径遍历漏洞——攻击者完全可以轻松访问到/content/includes目录以外的文件,必须立刻添加防护措施!
为什么会有风险?
直接将用户可控的req.params.slug拼接到文件路径里,是路径遍历攻击的典型场景。举个例子:如果攻击者请求/api/includes/../secret,拼接后的路径会变成__dirname/content/includes/../secret.html,这相当于直接跳到上级目录读取secret.html文件。要是攻击者用多组../,甚至能遍历到系统级敏感文件(比如Linux下的/etc/passwd、Windows下的系统配置文件)。
必须做路径遍历防护!
当然需要,而且是优先级极高的修复。这里的“注入防护”具体指路径遍历攻击的防护,核心目标是确保最终生成的文件路径始终严格限制在你预期的/content/includes目录范围内。
实用修复方案(组合使用效果最佳)
- 限制输入字符:用正则表达式约束
slug只能包含合法文件名字符(比如字母、数字、下划线、短横线),直接过滤掉../、\这类危险字符。 - 使用安全的路径拼接方法:借助Node.js的
path模块(path.join或path.resolve)拼接路径,它会自动处理简单的路径遍历序列,但这还不够,必须配合路径校验。 - 强制校验路径范围:先把目标目录转为绝对路径,再检查最终生成的文件路径是否以这个绝对路径开头,确保不会跳出预期目录。
修复后的示例代码
const path = require('path'); const fs = require('fs'); // 定义允许访问的目录绝对路径,避免相对路径歧义 const allowedDir = path.resolve(__dirname, 'content/includes'); app.get('/api/includes/:slug', (req, res) => { const slug = req.params.slug; // 第一步:校验输入格式,拒绝非法字符 if (!/^[a-z0-9_-]+$/i.test(slug)) { return res.sendStatus(400); // 返回非法请求状态码 } // 第二步:用path.join安全拼接路径 const filePath = path.join(allowedDir, `${slug}.html`); // 第三步:双重校验,确保路径未跳出允许范围 if (!filePath.startsWith(allowedDir)) { return res.sendStatus(403); // 返回禁止访问状态码 } // 最后检查文件是否存在并返回 if (fs.existsSync(filePath)) { res.sendFile(filePath); } else { res.sendStatus(404); } });
这样处理后,就能有效阻断路径遍历攻击,确保用户只能访问/content/includes目录下的合法.html文件。
内容的提问来源于stack exchange,提问作者Erik Hofer
相关产品推荐
相关产品推荐

