NoSQL SQL注入

0x00 NoSQL 基础

什么是 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 SQL注入

NoSQL 的代表数据库

  • MongDB、Redis、Memcache

NoSQL 的应用

  • 目前许多大型互联网项目都会选用 MySQL(或任何关系型数据库) + NoSQL 的组合方案

  • 举例:

  • 关系型数据库适合存储结构化数据 ,如用户的帐号、地址:

    • 这些数据通常需要做结构化查询

    • 这些数据的规模、增长的速度通常是可以预期的

    • 事务性、一致性

  • NoSQL 适合存储非结构化数据 ,如文章、评论:

    • 这些数据通常用于模糊处理 ,如全文搜索、机器学习

    • 这些数据是海量的 ,而且增长的速度是难以预期的

    • 根据数据的特点,NoSQL 数据库通常具有无限(至少接近)伸缩性

    • 按 key 获取数据效率很高,但是对 join 或其他结构化査询的支持就比铰差

0x01 MongoDB 基础

MongoDB 介绍

  • MongoDB 是流行的 NoSQL 数据库,它是个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。默认端口号为 27017

  • MongoDB 的特点

    • MongoDB 和其他的数据库一样,都支持常见存储操作,但是它可以存储任何的数据,包括文件。

    • MongoDB 允许在服务端执行脚本,可以用 javascript 编写某个函数,直接在服务端执行,也可以把函数的定义存储在服务端,下次直接调用即可。

    • MongoDB 数据操作使用 JSON 形式的标记。

    • MongoDB 支持各种编程语言:RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言。

    • MongoDB 使用 db 关键字代表当前数据库。

MongoDB 语句

NoSQL SQL注入

MongoDB 数据类型

NoSQL SQL注入

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岁, 或者性别为男

0x02 NoSQL注入分类

  • Web应用和服务通常使用 NoSQL数据库去保存客户数据。图为典型web应用架构。该程序自身可能不易受到攻击,但有时它们提供了不安全的API ,当应用开发人员错误地使用它们时就会给该应用引入漏洞,这些漏洞会被人利用对数据库进行
    任意操作。

NoSQL SQL注入

  • NoSQL注入分为4种
  1. 重言式/永真式(重要)

  2. JavaScript注λ(难度较大)

  3. 联合查询注入(被淘汰)

  4. mongoshell拼接注入(难度中等,危害大)、

  • 语言、代码逻辑角度分类(3种):
  1. PHP数组注入

  2. JS注入

  3. Mongoshell拼接注入

  • 攻击手段角度分类(3种)
  1. 重言式(永真式)

  2. 联合查询

  3. Javascript注入

重言式注入

  • 什么是重言式注入?

  • 重言式又称为永真式。此类攻击是在条件语句中注入代码,使生成的表达式判定结果永远为真 ,从而绕过认证或访问机制使用 Mongo DB进行数据库查询的过程:

NoSQL SQL注入

  • MongoDB将查询语句存放在数组中,再将数组带入数据库进行查询。此过程安全性较高,不存在单引号闭合的问题。但是由于PHP的特性导致注入仍然存在。

NoSQL SQL注入

  • 解释:

就PHP本身的性质而言,由于其松散的数组特性,导致如果我们输λ value=1那么。也就是输入了一个 value的值为1的数据。如果输 value[$ne]=2,也就意味着value=array($ne=>2),在MongoDb得角度来,很有可能从原来的个单个目标的查询变成了条件查询
从 xxx.find({'key':'A'}) ====> xxx.find({'key':{$ne:'A'}})

  • 防御:可以通过函数 is_array将输入参数转变字符串类型来解决

db->logins->find(array("username"=>(string)$_POST["username"],"password"=>(string)$_POST["password"]));

  • 注意:
  1. 必须要结合PHP语言才能导致重言式注入(依据PHP语言的特性),ASP没有永真式注入

  2. 如果是POST方法传参,可以结合 Burp Suite抓包、改包进行绕过。

  3. 使用正则表达式也可以构造永真式如:

username[$regex]=.*?&password[$regex]=.*?         # .*?为匹配所有字符串

JavaScript注入

  • 什么是 JavaScript注入?

  • 这是一种新的漏洞由允许执行数据内容中 JavaScript 的 NOSQL数据库引入的。 JavaScript使在数据引擎进行复杂事务和查询成为可能。传递不干净的用广输入到这些查询中可以注入任意 JavaScript代码这会导致非法的数据获取或篡改

  • 注入产生的原因

  1. MongoDB中$where操作符是可以执行 JavaScript语句的。

  2. 在PHP语言中是不能直接写入 JavaScript语句的,需要写在字符串中。使用字符串就会引用到单引号和双引号,因此容易出现闭合的问题

  3. 在 MongoDB2.4之前,通过$ where操作符使用 map-reduce、 group命令可以访问到 mongo shell中的全局函数和属性也就是说可以操作数据库中的数据。

NoSQL SQL注入

  • 在$query中使用了$where操作符执行 JavaScript语言,其中$username和 $password使用了字符串拼接的方式
    所以可以尝试构造闭合语句 进行注入攻击。

  • 根据代码,可以控制 admin和 password进行闭合,构造出 payload

  • 如:通过闭合单引号,插入代码:n';return true;var a='

  • 提交执行的 Javascript代码为

NoSQL SQL注入

  • 在输入用户名后就返回了true,所以只要输入任意密码就可以成功登陆了。

  • 注意:

  • 闭合的方法有很多,只要 return的值为真即可。、

  • 该注入方法较难,主要是因为 payload不易构造,在有源码的情况下容易构造闭合语句,没有源码只能猜测。

  • $where执行的 JavaScript语句只能进行简单的逻辑操作。

mongo shell拼接注入

  • mongoshell是什么?

  • MongoShell是一个互动的 JavaScript接口的 Mongo DB,可以使用M。 ngo Shell来查询和更新数据以及执行管理操作。可以连接到在运行的 MongoDB实例

  • 产生的原因

  • PHP中,通过** executeCommand** 可以执行she命令,可以直接执行语句。同样是存在字符串拼接的问题,因此通过使用单引号、双引号构造闭合语句 ,就可以执行任意的语句。

  • 危害

  • 可以通过构造的语句对数据库进行任意操作,包括增删改查。

  • 因为 mongo shell的语句比较好猜测,所以构造 payload的难度不高,且危害较大。

NoSQL SQL注入

  • 以上图代码为例,$cmd是根据时间排倒序,其中$username采用字符串拼接的方式,因此可以构造双引
    号闭合攻击,之后通过 executeCommand 可以直接执行语句,造成攻击
上一篇:分布式数据库NoSQL简介


下一篇:MySQL学习笔记:一、数据库概述