NOSQL注入总结
NOSQL注入与SQL注入的区别
关系型数据库 (SQL):数据存储在表中,使用结构化查询语言 (SQL) 进行增删改查。SQL注入的核心是操纵字符串拼接来破坏原有查询逻辑。
非关系型数据库 (NoSQL):数据存储形式多样(文档、键值对、图、列族),没有统一的查询语言。它使用API调用或对象查询,通常直接与应用程序的编程语言(如JavaScript、Python)集成。
根本区别:
- SQL注入:攻击者操纵的是查询语言本身。
- NoSQL注入:攻击者操纵的是查询API的参数或解析器的输入。它更像是一种逻辑注入或代码注入。
分类
主要存在于MongoDB与Redis中
MongoDB
-
运算符注入
MongoDB查询支持丰富的运算符,如
$ne
(不等于),$gt
(大于),$where
,$regex
等。如果用户输入被直接解析为查询对象的一部分,攻击者就可以注入这些运算符。Payload 1: 绕过登录认证
-
原始正常请求:
{ "username": "admin", "password": "secret123" }
-
恶意注入请求:
{ "username": "admin", "password": {"$ne": ""} // 或 {"$ne": null} }
-
最终生成的查询语句:
User.findOne({ username: "admin", password: {"$ne": ""} })
-
解释:这个查询的意思是“查找用户名为admin,且密码不等于空字符串的用户”。只要admin用户的密码不为空,这个条件就恒为真,从而绕过登录验证。
Payload 2: 布尔盲注 - 探测数据
- 目标:判断用户名是否存在。
-
恶意请求:
{ "username": {"$regex": "^a"}, // 用户名是否以'a'开头 "password": {"$ne": ""} }
- 根据返回结果(成功或失败)来判断条件真假,从而逐字符提取信息,与传统SQL布尔盲注原理类似。
-
Redis
Redis作为内存键值数据库,也存在注入问题,通常源于恶意构造协议或命令。
漏洞示例:一个使用EVAL
命令执行Lua
脚本的应用,如果用户输入被拼接进脚本。
- 原始命令:
EVAL "return redis.call('GET', ARGV[1])" 1 user:123
- 恶意输入:
user:123"); redis.call('SET', 'admin:password', 'hacked'); --
-
最终命令:
return redis.call('GET', "user:123"); redis.call('SET', 'admin:password', 'hacked'); --")
- 解释:通过闭合引号和注释符,注入了新的Redis命令,修改了管理员密码。
防御
- 参数化查询
- 输入验证过滤/转义
- 权限最小化原则
- 禁用危险函数
-
使用ORM/ODM
提供验证,强制字段的类型,是恶意语句变为字符串。
关系型与非关系型数据库区别
特点 | 关系型数据库 (RDBMS) | 非关系型数据库 (NoSQL) |
---|---|---|
数据模型 | 表格(行、列) | 文档、键值、列族、图等 |
模式 (Schema) | 固定,强约束 | 动态、灵活 |
查询语言 | SQL | API / JSON / 特定查询语言 |
事务支持 | ACID,强一致性 | BASE,最终一致性 |
扩展性 | 纵向扩展为主,横向扩展难 | 横向扩展为主,分布式友好 |
性能与应用场景 | 复杂查询,金融、库存、ERP | 高并发、大数据、缓存、社交、IoT |
关系型数据库注重数据一致性和结构化,适合事务型系统;
非关系型数据库注重高性能和可扩展性,适合海量、快速变化的数据场景。