什么是 NoSQL 数据库?
NoSQL(NoSQL= Not Only SQL),意即“不仅仅是 SQL",泛指非关系型的数据库 。
随着互联网 web2.0 网站的兴起,传统的关系数据库在应付 web2.0 网站,特别是超大规模和高并发的 SNS 类型的 web2.0 纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL 数据库的产生就是为了解决大规模数据集合多重数据种类 带来的挑战,尤其是大数据应用难题,包括超大规模数据的存储。
为什么要用 NoSQL?
随着互联网的不断发展, 各类型的应用层出不穷,在这个云计算的时代,对技术提出了更多的需求,主要体现在这四个方面:
低延迟的读写速度 :应用快速的反应能极大地提升用户的满意度
海量的数据和流量 :对于搜索这样大型应用而言,需要利用 PB 级别的数据和能应对百万级的流量
大规模集群的管理 :分布式应用能更简单的部罟和管理
庞大运营成本的考量 :在硬件成本、软件成本和人力成本能够有大幅度地降低
举例:例如谷歌或 Facebook 每天为他们的用户收集万亿比特的数据。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展
NoSQL 与 SQL 的区别
SQL 数据库 | NOSQL 数据 |
|
---|---|---|
存储方式 | SQL 数据存在特定结构的 表 中 | 可以是 JSON 文档、哈希表或者其他方式,比较 灵活可拓展 |
表数据集合的数据的关系 | 定义好表和字段结构后才能添加数据 ,表结构可以在被定义之后更新,但是如果有比较大的结构变更的话就会变得比较复杂 | 数据可以 在任何时候任何地方添加 ,不需要先定义表 |
JOIN 查询 | 支持 JOIN 多表查询 | 暂未提供 类似 JOIN 的查询方式。大部 NOSQL 使用 非规范化的数据存储方式 存储数据 |
数据耦合性 | SQL 中不允许删除已经被使用的外部数据 | 可以随时删除任何数据 |
事务 | 提供事务 | 没有事务这个概念,每个数据集的操作都是原子级的 |
NoSQL 的代表数据库
NoSQL 的应用
目前许多大型互联网项目都会选用 MySQL(或任何关系型数据库) + NoSQL 的组合方案
举例:
关系型数据库适合存储结构化数据 ,如用户的帐号、地址:
这些数据通常需要做结构化查询
这些数据的规模、增长的速度通常是可以预期的
事务性、一致性
NoSQL 适合存储非结构化数据 ,如文章、评论:
这些数据通常用于模糊处理 ,如全文搜索、机器学习
这些数据是海量的 ,而且增长的速度是难以预期的
根据数据的特点,NoSQL 数据库通常具有无限(至少接近)伸缩性
按 key 获取数据效率很高,但是对 join 或其他结构化査询的支持就比铰差
MongoDB 介绍
MongoDB 是流行的 NoSQL 数据库,它是个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。默认端口号为 27017
MongoDB 的特点
MongoDB 和其他的数据库一样,都支持常见存储操作,但是它可以存储任何的数据,包括文件。
MongoDB 允许在服务端执行脚本,可以用 javascript 编写某个函数,直接在服务端执行,也可以把函数的定义存储在服务端,下次直接调用即可。
MongoDB 数据操作使用 JSON 形式的标记。
MongoDB 支持各种编程语言:RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言。
MongoDB 使用 db 关键字代表当前数据库。
MongoDB 语句
MongoDB 数据类型
MongoDB 基本 操作
MongDB的启动
开启服务: sudo mongodb
登陆 mongodb数据库:mongodb --host 127.0.0.1
数据库的操作
查看所有的数据库:show dbs
切换数据库:use数据库名
查看集合: show collections
数据库的创建:use 数据库名。有值自动创建 。当use的时候,系统就会自动创建—个数据库。
删除数据库:进入数据库后db.dropDatabase();
注意:如果没有选择任何数据库,会删除默认的test数据库
集合的操作
查看集合:show collections
创建集合:db.createCollection("xxx")
删除集合:db.xxx.drop()
文档(行)的增删改
增加数据:db.xx.insert({key:value})
举例:db.chunqiu.insert({id:1,name:"web",age:10})
删除数据: db.xx.remove(删除的条件)
全部删除:db.xx.remove({})
根据条件删除,默认是删除所有符合条件的数据: db.xx.remove({age:10})
只删除符合条件的第一个: db.xx.remove({gender:true},{justOne:true})
更改操作:db.update({查找的条件},{修改的内容})
修改内容:默认其他原有字段删除了,替换掉原有数据:db.xx.update({age:10},{name:"NoSQL"})
保持原有的字段,加一个修饰$set:默认只修改第一个且对已存在的原有属性是替换,不存在的属性是添加
db.stu.update({age:10}, {$set:{like:"study"}})
说明:把like:"study"添加到数据里面,并不是换
文档查询简单语句:
基本查询:db.xx.find({查询条件})
查询所有的数据: db.xx.find() 或db.xx.find()
默认查出所有符合条件的数据:db.xx.find({age:10})
查找符合条件的第一个:db.xx.findOne({age:10})
格式化输出— pretty()函数:db.xx.find({age:10}).pretty()
常用条件
$lt | < |
---|---|
$lte | ≤ |
$gt | > |
$gte | ≥ |
$ne | ≠ |
$in | in |
$nin | not in |
$all | all |
$or | or |
$not | 反匹配(1.3.3及以上版本) |
$regex | 正则 |
条件查询:
举例:
db.xx.find({age:{$lt:20}}) 查询年龄小于20岁的
db.xx.find({age:{$ne:18}}) 查询年龄不等于18岁的
逻辑运算:$and , $or
$and:默认的的查询条件就是且的关系
举例:
db.xx.find({age:28,gender:true})
db.xx.find({$and :[age:28},{gender:true}]}) 查询年龄是28岁且性别为女
$or:或的关系
举例:
db.xx.find({$or :[age:{$lt:30},{gender:false}]}) 查询年龄小于30岁, 或者性别为男
重言式/永真式(重要)
JavaScript注λ(难度较大)
联合查询注入(被淘汰)
mongoshell拼接注入(难度中等,危害大)、
PHP数组注入
JS注入
Mongoshell拼接注入
重言式(永真式)
联合查询
Javascript注入
什么是重言式注入?
重言式又称为永真式。此类攻击是在条件语句中注入代码,使生成的表达式判定结果永远为真 ,从而绕过认证或访问机制使用 Mongo DB进行数据库查询的过程:
就PHP本身的性质而言,由于其松散的数组特性,导致如果我们输λ value=1那么。也就是输入了一个 value的值为1的数据。如果输 value[$ne]=2,也就意味着value=array($ne=>2),在MongoDb得角度来,很有可能从原来的个单个目标的查询变成了条件查询
从 xxx.find({'key':'A'}) ====> xxx.find({'key':{$ne:'A'}})
db->logins->find(array("username"=>(string)$_POST["username"],"password"=>(string)$_POST["password"]));
必须要结合PHP语言才能导致重言式注入(依据PHP语言的特性),ASP没有永真式注入
如果是POST方法传参,可以结合 Burp Suite抓包、改包进行绕过。
使用正则表达式也可以构造永真式如:
username[$regex]=.*?&password[$regex]=.*? # .*?为匹配所有字符串
什么是 JavaScript注入?
这是一种新的漏洞由允许执行数据内容中 JavaScript 的 NOSQL数据库引入的。 JavaScript使在数据引擎进行复杂事务和查询成为可能。传递不干净的用广输入到这些查询中可以注入任意 JavaScript代码这会导致非法的数据获取或篡改
注入产生的原因
MongoDB中$where操作符是可以执行 JavaScript语句的。
在PHP语言中是不能直接写入 JavaScript语句的,需要写在字符串中。使用字符串就会引用到单引号和双引号,因此容易出现闭合的问题
在 MongoDB2.4之前,通过$ where操作符使用 map-reduce、 group命令可以访问到 mongo shell中的全局函数和属性也就是说可以操作数据库中的数据。
在$query中使用了$where操作符执行 JavaScript语言,其中$username和 $password使用了字符串拼接的方式
所以可以尝试构造闭合语句 进行注入攻击。
根据代码,可以控制 admin和 password进行闭合,构造出 payload
如:通过闭合单引号,插入代码:n';return true;var a='
提交执行的 Javascript代码为
在输入用户名后就返回了true,所以只要输入任意密码就可以成功登陆了。
注意:
闭合的方法有很多,只要 return的值为真即可。、
该注入方法较难,主要是因为 payload不易构造,在有源码的情况下容易构造闭合语句,没有源码只能猜测。
$where执行的 JavaScript语句只能进行简单的逻辑操作。
mongoshell是什么?
MongoShell是一个互动的 JavaScript接口的 Mongo DB,可以使用M。 ngo Shell来查询和更新数据以及执行管理操作。可以连接到在运行的 MongoDB实例
产生的原因
PHP中,通过** executeCommand** 可以执行she命令,可以直接执行语句。同样是存在字符串拼接的问题,因此通过使用单引号、双引号构造闭合语句 ,就可以执行任意的语句。
危害
可以通过构造的语句对数据库进行任意操作,包括增删改查。
因为 mongo shell的语句比较好猜测,所以构造 payload的难度不高,且危害较大。