我的Node.js代码被指存SQL注入风险,如何排查与修复?
为什么这段Node.js代码存在安全风险?如何修复?
首先明确:这段代码不存在SQL注入风险(完全没涉及数据库操作),主管的判断有误;但它确实存在路径遍历和参数注入风险,可能被误判为命令注入。
为什么会被误认为有命令注入?
你用的childProcess.spawnSync('cat', [filename])本身是安全的——因为用数组传递参数时,Node.js会直接执行cat程序,不会通过系统shell解析参数。用户输入的任何shell元字符(比如;、&&、$(rm -rf /))都会被当作文件名的一部分,不会被执行。
但它的核心问题在于:
- 路径遍历攻击:用户可以输入
../../../../etc/passwd这类路径,直接读取系统敏感文件(比如密码文件),突破你原本的文件访问限制。 - 参数注入:如果用户输入
--help,cat会输出自身的帮助信息;输入-的话,cat会等待标准输入,导致请求挂起,消耗服务器资源。
如何修复这些安全问题?
核心思路是严格限制用户输入的范围,确保只能访问你允许的文件:
1. 限制访问目录
指定一个固定的目录(比如项目下的files文件夹),只允许用户访问该目录内的文件。
2. 校验文件名合法性
过滤掉包含特殊字符(比如../、/、\)的文件名,只允许字母、数字、下划线、点和短横线这类合法字符。
3. 强制检查路径范围
用Node.js的path模块解析绝对路径,确保最终路径落在你允许的目录内,彻底防止路径遍历。
修复后的代码示例
const express = require('express') const childProcess = require('child_process') const path = require('path') const app = express() // 定义允许访问的目录,比如项目根目录下的files文件夹 const ALLOWED_DIR = path.resolve(__dirname, 'files') app.get('/', (req, res) => { res.send(` <h1>File viewer</h1> <form method='GET' action='/view'> <input name='filename' /> <input type='submit' value='Submit' /> </form> `) }) app.get('/view', (req, res) => { const { filename } = req.query if (!filename) { return res.send('请输入文件名') } // 校验文件名:只允许字母、数字、下划线、点、短横线 if (!/^[a-zA-Z0-9_\-.]+$/.test(filename)) { return res.send('文件名包含非法字符') } // 生成绝对路径 const filePath = path.resolve(ALLOWED_DIR, filename) // 检查路径是否在允许的目录内,防止路径遍历 if (!filePath.startsWith(ALLOWED_DIR)) { return res.send('无权访问该文件') } try { const child = childProcess.spawnSync('cat', [filePath]) if (child.status !== 0) { res.send(`读取失败:${child.stderr.toString()}`) } else { res.send(child.stdout.toString()) } } catch (err) { res.send(`读取文件出错:${err.message}`) } }) app.listen(8000, '127.0.0.1')
额外建议
- 不要用
child_process.exec这类通过shell执行命令的方法(除非必须),因为它会解析用户输入的shell元字符,真正存在命令注入风险。 - 如果只是读取文件,完全可以用Node.js内置的
fs.readFile或fs.readFileSync,没必要调用系统的cat命令,减少不必要的系统调用风险。
内容的提问来源于stack exchange,提问作者bwayo joel
相关产品推荐
相关产品推荐

