跳转至

NoSql注入

NoSql是什么?

NoSQL(Not Only SQL 的缩写)泛指非关系型的数据库,主要针对的是键值、文档以及图形类型数据存储。并且,NoSQL 数据库天生支持分布式,数据冗余和数据分片等特性,旨在提供可扩展的高可用高性能数据存储解决方案。

一个常见的误解是 NoSQL 数据库或非关系型数据库不能很好地存储关系型数据。NoSQL 数据库可以存储关系型数据—它们与关系型数据库的存储方式不同。

NoSQL 数据库代表:HBase、Cassandra、MongoDB、Redis。

SQL和NoSql的区别

比较维度 SQL数据库 NoSQL数据库
数据存储模型 结构化存储,具有固定行和列的表格 非结构化存储。文档:JSON 文档,键值:键值对,宽列:包含行和动态列的表,图:节点和边
发展历程 开发于 1970 年代,重点是减少数据重复 开发于 2000 年代后期,重点是提升可扩展性,减少大规模数据的存储成本
例子 Oracle、MySQL、Microsoft SQL Server、PostgreSQL 文档:MongoDB、CouchDB,键值:Redis、DynamoDB,宽列:Cassandra、 HBase,图表:Neo4j、 Amazon Neptune、Giraph
ACID属性 提供原子性、一致性、隔离性和持久性 (ACID) 属性 通常不支持 ACID 事务,为了可扩展、高性能进行了权衡,少部分支持比如 MongoDB 。不过,MongoDB 对 ACID 事务 的支持和 MySQL 还是有所区别的。
性能 性能通常取决于磁盘子系统。要获得最佳性能,通常需要优化查询、索引和表结构。 性能通常由底层硬件集群大小、网络延迟以及调用应用程序来决定。
扩展 垂直(使用性能更强大的服务器进行扩展)、读写分离、分库分表 横向(增加服务器的方式横向扩展,通常是基于分片机制)
用途 普通企业级的项目的数据存储 用途广泛比如图数据库支持分析和遍历连接数据之间的关系、键值数据库可以处理大量数据扩展和极高的状态变化
查询语法 结构化查询语言 (SQL) 数据访问语法可能因数据库而异

NoSQL数据库有什么优势?

NoSQL 数据库非常适合许多现代应用程序,例如移动、Web 和游戏等应用程序,它们需要灵活、可扩展、高性能和功能强大的数据库以提供卓越的用户体验。

  • 灵活性: NoSQL 数据库通常提供灵活的架构,以实现更快速、更多的迭代开发。灵活的数据模型使 NoSQL 数据库成为半结构化和非结构化数据的理想之选。
  • 可扩展性: NoSQL 数据库通常被设计为通过使用分布式硬件集群来横向扩展,而不是通过添加昂贵和强大的服务器来纵向扩展。
  • 高性能: NoSQL 数据库针对特定的数据模型和访问模式进行了优化,这与尝试使用关系数据库完成类似功能相比可实现更高的性能。
  • 强大的功能: NoSQL 数据库提供功能强大的 API 和数据类型,专门针对其各自的数据模型而构建。

NoSQL数据库有哪些类型?

NoSQL 数据库主要可以分为下面四种类型:

  • 键值:键值数据库是一种较简单的数据库,其中每个项目都包含键和值。这是极为灵活的 NoSQL 数据库类型,因为应用可以完全控制 value 字段中存储的内容,没有任何限制。Redis 和 DynanoDB 是两款非常流行的键值数据库。
  • 文档:文档数据库中的数据被存储在类似于 JSON(JavaScript 对象表示法)对象的文档中,非常清晰直观。每个文档包含成对的字段和值。这些值通常可以是各种类型,包括字符串、数字、布尔值、数组或对象等,并且它们的结构通常与开发者在代码中使用的对象保持一致。MongoDB 就是一款非常流行的文档数据库。
  • 图形:图形数据库旨在轻松构建和运行与高度连接的数据集一起使用的应用程序。图形数据库的典型使用案例包括社交网络、推荐引擎、欺诈检测和知识图形。Neo4j 和 Giraph 是两款非常流行的图形数据库。
  • 宽列:宽列存储数据库非常适合需要存储大量的数据。Cassandra 和 HBase 是两款非常流行的宽列存储数据库。

Mongodb Sql注入

Mongodb中的基础语法

MongoDB 创建数据库

MongoDB 创建数据库的语法格式如下:

SQL
use DATABASE_NAME

如果数据库不存在,则创建数据库,否则切连接并换到指定数据库,是不是很方便!

以下实例我们创建了数据库 love:

SQL
> use users
switched to db users
> db
users
>

MongoDB 创建集合

MongoDB 中我们使用 createCollection() 方法来创建集合。其语法格式如下:

Text Only
db.createCollection(name, options)

参数说明:

  • name:要创建的集合名称
  • options:可选参数,指定有关内存大小及索引的选项

如下实例,我们在 users 数据库中创建一个 all_users 集合:

SQL
> use users
switched to db users
> db.createCollection("all_users")
{ "ok" : 1 }
>

MongoDB 插入文档

在 MongoDB 中我们可以使用 insert() 方法向集合中插入文档,语法如下:

Text Only
db.COLLECTION_NAME.insert(document)

如下实例,我们向存储在 users 数据库的 all_users 集合中插入一个文档:

SQL
> db.all_users.insert({name: 'whoami', 
    description: 'the admin user',
    age: 19,
    status: 'A',
    groups: ['admins', 'users']
})

我们也可以将文档数据定义为一个变量,然后再执行插入操作将变量插入。

MongoDB 更新文档

在 MongoDB 中我们可以使用 update() 或 save() 方法来更新集合中的文档。

  • update() 方法

update() 方法用于更新已存在的文档。语法格式如下:

SQL
db.collection.update(
   <query>,
   <update>,
   {
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>
   }
)

参数说明:

  • query:update 操作的查询条件,类似 sql update 语句中 where 子句后面的内容。
  • update:update 操作的对象和一些更新的操作符(如 $set)等,可以理解为 sql update 语句中 set 关键字后面的内容。
  • multi:可选,默认是 false,只更新找到的第一条记录,如果这个参数为 true,就把按条件查出来多条记录全部更新。

接着我们通过 update() 方法来将年龄 age 从 19 更新到 20:

SQL
> db.lover.update({'age':19}, {$set:{'age':20}})
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
>
> db.all_users.find().pretty()
{
    "_id" : ObjectId("60fa854cf8aaaf4f21049148"),
    "name" : "whoami",
    "description" : "the admin user",
    "age" : 20,
    "status" : "A",
    "groups" : [
        "admins",
        "users"
    ]
}
>

成功将 age 从 19 改为了 20。

以上语句只会修改第一条发现的文档,如果你要修改多条相同的文档,则需要设置 multi 参数为 true。

SQL
> db.lover.update({'age':'19'}, {$set:{'age':20}}, {multi:true})
  • save() 方法

save() 方法通过传入的文档来替换已有文档,_id 主键存在就更新,不存在就插入。语法格式如下:

SQL
db.collection.save(
   <document>,
   {
     writeConcern: <document>
   }
)

参数说明:

  • document:文档数据。

如下实例中我们替换了 _id 为 60fa854cf8aaaf4f21049148 的文档数据:

SQL
> db.all_users.save({
    "_id" : ObjectId("60fa854cf8aaaf4f21049148"),
    "name" : "whoami",
    "description" : "the admin user",
    "age" : 21,
    "status" : "A",
    "groups" : [
        "admins",
        "users"
    ]
})

MongoDB 查询文档

在 MongoDB 中我们可以使用 find() 方法来查询文档。find() 方法以非结构化的方式来显示所有文档。其语法格式如下:

Text Only
db.collection.find(query, projection)

参数说明:

  • query:可选,使用查询操作符指定查询条件,相当于 sql select 语句中的 where 子句。
  • projection:可选,使用投影操作符指定返回的键。

如下实例我们查询了集合 all_users 中的 age 为 20 的数据:

SQL
> db.all_users.find({"age":"20"})
{ "_id" : ObjectId("60fa854cf8aaaf4f21049148"), "name" : "whoami", "description" : "the admin user", "age" : "20", "status" : "A", "groups" : [ "admins", "users" ] }
>

如果你需要以易读的方式来读取数据,可以使用 pretty() 方法以格式化的方式来显示所有文档:

SQL
> db.all_users.find({"age":20}).pretty()
{
    "_id" : ObjectId("60fa854cf8aaaf4f21049148"),
    "name" : "whoami",
    "description" : "the admin user",
    "age" : 20,
    "status" : "A",
    "groups" : [
        "admins",
        "users"
    ]
}
>

MongoDB 与 RDBMS Where 语句的比较

如果你熟悉常规的 SQL 数据,通过下表可以更好的理解 MongoDB 的条件语句查询:

操作 格式 范例 RDBMS 中的类似语句
等于 {<key>:<value>} db.love.find({"name":"whoami"}).pretty() where name = 'whoami'
小于 {<key>:{$lt:<value>}} db.love.find({"age":{$lt:19}}).pretty() where age < 19
小于或等于 {<key>:{$lte:<value>}} db.love.find({"age":{$lte:19}}).pretty() where likes <= 19
大于 {<key>:{$gt:<value>}} db.love.find({"age":{$gt:19}}).pretty() where likes > 19
大于或等于 {<key>:{$gte:<value>}} db.love.find({"age":{$gte:19}}).pretty() where likes >= 19
不等于 {<key>:{$ne:<value>}} db.love.find({"age":{$ne:19}}).pretty() where likes != 19

MongoDB AND 条件

MongoDB 中的 find() 方法可以传入多个键值对,每个键值对以逗号隔开,即常规 SQL 的 AND 条件。语法格式如下:

SQL
> db.all_users.find({"status":"B", "age":20})
{ "_id" : ObjectId("60fa8ef8f8aaaf4f2104914e"), "name" : "bob", "description" : "the normal user", "age" : 20, "status" : "B", "groups" : [ "normals", "users" ] }
>

以上实例中类似于 RDBMS 中的 WHERE 语句:WHERE status='B' AND age=20

MongoDB OR 条件

MongoDB OR 条件语句使用了关键字 $or 来表示,语法格式如下:

SQL
> db.col.find(
   {
      $or: [
         {key1: value1}, {key2:value2}
      ]
   }
).pretty()

如下实例,我们查询键 status 值为 A 或键 age 值为 19 的文档。

SQL
> db.all_users.find({$or:[{"status":"A", "age":"19"}]})
{ "_id" : ObjectId("60fa8ec6f8aaaf4f2104914c"), "name" : "bunny", "description" : "the normal user", "age" : 19, "status" : "A", "groups" : [ "lovers", "users" ] }
>

AND 和 OR 联合使用

以下实例演示了 AND 和 OR 联合使用,类似于 RDBMS 中的 WHERE 语句: where age>19 AND (name='whoami' OR status='A')

SQL
> db.all_users.find({"age":{$gt:19}, $or: [{"name":"whoami"}, {"status":"A"}]})
{ "_id" : ObjectId("60fa9176f8aaaf4f21049150"), "name" : "whoami", "description" : "the admin user", "age" : 20, "status" : "A", "groups" : [ "admins", "users" ] }
>

参考文章

  1. Nosql 注入从零到一-先知社区
  2. 奇安信攻防社区-MongoDB数据库渗透测试及漏洞复现