当前位置: 首页
数据库
Node.js防止MongoDB注入式查询的实用方法

Node.js防止MongoDB注入式查询的实用方法

热心网友 时间:2026-07-13
转载

对用户输入进行严格类型与格式校验,禁用$where、$regex等高危操作符,并构建四层纵深防护体系可有效防御MongoDBNoSQL注入。字符串字段须通过typeof与正则双重验证,$regex操作符需转义用户输入,$where应彻底禁用,同时避免依赖黑名单过滤或JSON parse()二次解析。

MongoDB 本身并不存在传统意义上的 SQL 注入,但如果在应用层直接将用户输入原封不动地塞入查询对象,就会引发 NoSQL 注入风险。要有效防范这一威胁,必须对字段进行严格的类型与格式校验,禁用 $where$regex 等高危操作符,并在此基础上构建一套四层纵深防护体系——这几个环节缺一不可。

Node.js如何防止MongoDB执行注入式查询?

直接传 req.bodyfindOne() 就是高危操作

将用户输入原样传递给 findOne()find()updateOne() 的第一个参数,相当于把查询逻辑的控制权拱手交给了攻击者。MongoDB 驱动不会做任何解析或拦截,它只是将 JavaScript 对象序列化为 BSON 发送给服务端——例如 { "$ne": null } 会被照单执行,这并非“无效语法”,而是一条合法的查询指令。

常见的翻车场景:db.users.findOne({ username: req.body.username }),攻击者提交 {"$ne": null},直接绕过登录校验;Model.find(req.query.filter),前端传 {"status": {"$in": ["active", "deleted"]}} 看着还行,但没人拦得住 {"$where": "sleep(1000)"}

  • 所有主流驱动(Node.js 原生驱动、Mongoose)行为一致:不校验、不重写、不拒绝非法结构
  • Mongoose 的 strict: true 默认只限制写入时的 schema 外字段,对查询条件完全无感
  • 别信“用了 Mongoose 就安全”——Model.find(req.body) 在任何版本下都等于裸奔

对字符串字段必须做 typeof + 正则双校验

username、email、title 这类字段,业务上本就应该是纯字符串,那就得用代码把它钉死。类型校验是第一道防线,格式校验是第二道,缺一不可。

  • 先用 typeof value === 'string' 排除对象、数组、null、undefined
  • 再用正则限定内容范围:/^[a-zA-Z0-9_]{3,20}$//^.+$/ 安全得多
  • 主动拒绝空字符串和前后空白:value.trim() === '' 需单独判断
  • Unicode 控制字符、零宽空格、BOM 头也要过滤,可用 value.replace(/\p{C}/gu, '') 清理

示例:

if (typeof req.body.username !== 'string' || !/^[a-zA-Z0-9_]{3,20}$/.test(req.body.username.trim())) {  return res.status(400).json({ error: 'Invalid username' });}

$regex$where$expr 必须隔离用户输入

这几个操作符是 NoSQL 注入的“特权通道”。哪怕前面做了严格的字符串校验,一旦放开它们接收原始输入,整个防御体系就形同虚设。

  • $regex 必须配合 $options: 'i',且对用户输入做转义:req.query.q.replace(/[.*+?^${}()|\[\]\\]/g, '\\$&')
  • $where 应彻底禁用——它允许执行任意 JavaScript,而且不走索引,性能和安全双崩
  • $expr 若必须使用,只能接受白名单内的固定表达式,不能拼接用户输入
  • 不要用 JSON.parse() 二次解析用户输入——可能触发原型污染或正则 DoS

错误写法:{ name: { $regex: req.query.q } };正确写法:

const escaped = req.query.q.replace(/[.*+?^${}()|\[\]\\]/g, '\\$&');db.users.find({ name: { $regex: escaped, $options: 'i' } });

别依赖“过滤 $ 符号”或“黑名单操作符”

简单粗暴地删掉 $ 或禁止 $ne$gt 等关键词,是典型的伪方案。MongoDB 会安静忽略无效操作符,导致查询逻辑意外放行数据。

  • 用户输入 {"status": {"$ne": "deleted"}},过滤后变成 {"status": {"ne": "deleted"}},MongoDB 不报错也不匹配,等价于 {}——查出全部文档
  • 攻击者可用 Unicode 编码绕过,比如 \u0024ne 代替 $ne
  • 黑名单永远追不上新操作符,$text$geoWithin$function(MongoDB 4.4+)都是潜在入口

真正有效的做法,是从源头切断恶意结构的传播路径:只允许你明确定义的字段名和值类型进入查询对象,其余一律拒之门外。复杂点在于字段语义各异——搜索字段要支持模糊匹配,ID 字段要校验 ObjectId 格式,时间范围字段要转为 Date 实例。没有银弹,只有按字段逐个收口。

来源:https://www.php.cn/faq/2781696.html

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
Redis 6.0 ACL权限控制:最小化命令授权提升安全性

Redis 6.0 ACL权限控制:最小化命令授权提升安全性

Redis6 0及以上版本启用ACL时,需确认版本并修改default用户默认全开权限。按业务边界创建用户,严格绑定keypattern(如~order:*),避免漏写通配符。命令权限按输入顺序生效,推荐细粒度列举而非类别。客户端连接必须显式传递用户名,否则回退至default用户导致权限失效。

时间:2026-07-13 07:07
导出数据库时包含创建数据库语句的选项设置

导出数据库时包含创建数据库语句的选项设置

使用mysqldump导出时,默认不包含建库语句,需添加--databases参数才能生成CREATEDATABASE和USE语句。同时,导出账号必须拥有SHOWDATABASES权限,否则会报错。注意--no-create-db参数会覆盖建库语句,导致不生成建库指令,导入前需检查目标库是否存在,并确保字符集兼容。

时间:2026-07-13 07:07
SQL嵌套查询使用Union与Intersect集合运算符过滤

SQL嵌套查询使用Union与Intersect集合运算符过滤

嵌套查询中不可直接在WHERE或IN中使用UNION或INTERSECT。正确做法是将集合运算符包裹在括号内作为派生表置于FROM子句中,并显式赋予别名。对于不支持INTERSECT的数据库,可用EXISTS嵌套替代。需注意列类型对齐、别名不可省略等细节。

时间:2026-07-13 07:07
如何在SQL中使用BIT_COUNT函数统计二进制位数量教程

如何在SQL中使用BIT_COUNT函数统计二进制位数量教程

BIT_COUNT函数统计无符号整数二进制中1的个数,输入必须为非负整数,字符串或负数会导致错误。使用前应确保字段为UNSIGNED类型或通过CAST转换。该函数不走索引,频繁查询建议缓存结果。MySQL特有,其他数据库需另写逻辑。对NULL返回NULL,需用IFNULL处理。

时间:2026-07-13 07:07
SQL中利用JOIN查找A表不存在B表的数据

SQL中利用JOIN查找A表不存在B表的数据

在SQL中查找A表存在而B表不存在的记录,最可靠的写法是使用LEFTJOIN并结合WHEREB idISNULL。需注意ON只用于连接逻辑,过滤条件应放在WHERE子句中;B表关联字段需要建立索引,并且要避免NULL值的陷阱。不建议使用NOTIN或EXCEPT,因为它们容易出错且性能较差。

时间:2026-07-13 07:06
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 热门数据榜