首页 > 数据库 >DVWA之SQL注入—Impossible level代码审计

DVWA之SQL注入—Impossible level代码审计

时间:2023-05-02 22:11:41浏览次数:41  
标签:last name level DVWA SQL row id first

Impossible level源代码

<?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();

?>

代码审计

审计checkToken

首先,该代码片段使用了 checkToken() 函数来验证 Anti-CSRF 令牌,即检查用户的访问令牌是否有效,以防止CSRF。

CSRF原理

CSRF(Cross-Site Request Forgery,跨站点请求伪造)是一种利用 Web 应用程序身份验证漏洞的攻击方式,攻击者通过伪造请求来冒充受信任用户的身份,以执行某些未经授权的操作。这种攻击方式通常发生在 Web 应用程序中存在漏洞的情况下,而攻击者则可以利用这些漏洞来伪造请求、窃取用户会话信息和执行非授权的操作。

例如,假设某个在线银行应用程序使用 GET 请求来执行转账操作,然后攻击者在一个恶意网站上嵌入一个包含一个类似于以下代码的图像:

<img src="http://bank.com/transfer?to=attacker&amp;amount=100" />

如果受害者浏览器中已经登录到银行的账户,并且在同一浏览器中访问了上面的恶意网站,那么这个 GET 请求就会被发送到银行应用程序中,并转移 100 美元给攻击者。由于该请求与受害者浏览器中的 cookie 相关联,并且被认为是合法的请求,因此银行应用程序将无法区分攻击者和受害者之间的差异。

为了防止 CSRF 攻击,Web 应用程序通常会生成一个随机的 CSRF 令牌,并将其包含在每个表单请求、链接和 AJAX 请求中。这个令牌可以告诉应用程序这个请求是否是受信任的,因为令牌只有在用户通过 Web 应用程序正常交互提交请求时才会出现。


审计is_numeric

从 GET 请求参数中获取 id 值,并使用 is_numeric() 函数检查该值是否为数字。如果是数字,则使用 intval() 函数将其转换为整数类型,然后根据配置文件中的 SQLI_DB 常量所指定的数据库类型(MySQL 或 SQLite),进行相应的查询操作

浮点数精度原理

在数据库中,整数类型和小数类型的自增方式不同。整数类型的自增方式是在原有的基础上加1,而小数类型则是在原有的基础上加上指定的增量。
假设在一个 static 表中,使用 FLOAT 类型的 id 字段作为主键,并且其初始值为 1.0,递增步骤为 0.1。当插入记录时,系统自动生成的 ID 值如下所示:

id name price
1.0 A 1
1.1 B 2
1.2 C 3
1.3 D 4
1.4 E 5

由于浮点数采用的是二进制表示法,而非十进制,因此可能存在像 0.1 这样的十进制小数无法精确转化为二进制的情况。所以实际的 ID 值可能是 1.0999999999 或者 1.1000000001 等类似的近似值。在这种情况下,可能会出现重复数据。
比如,在向 statict 表中插入一条记录时,新记录的 ID 值计算结果为 1.2000000001,这个值与已经存在的 ID 值 1.2 可能会相同,导致数据库插入失败。
另外,若出现数据查找或更新等操作时,可能会因为 ID 不准确而无法正确操作记录,例如查询 ID 为 1.2999999999 的记录,实际上这条记录不存在,但是由于精度问题,可能会得到一条随机的记录。
这种精度问题可能会导致小数值被截断或近似值导致的数据不一致。攻击者可以通过构造恶意的请求,将输入的小数值进行微调,进而获取到本来不应该被暴露的数据。


审计占位符:id

在MYSQL中,使用 PDO 对象的 prepare() 方法准备 SQL 查询语句,在其中使用占位符 :id 代替 id 参数,以避免 SQL 注入攻击。

占位符防sql原理

举例如下:
假设某注入语句为SELECT * FROM users WHERE id=1 OR 1=1,这将返回所有用户记录。
如果使用占位符 :id代替id参数,则该查询语句将变为 SELECT * FROM users WHERE id=:id,查询语句将不会受到任何注入攻击。


审计bindParam()

使用 bindParam() 方法将 id 参数绑定到占位符上,指定参数类型为整数类型。

bindParam()原理

当使用 bindParam() 方法时,参数并没有直接拼接到 SQL 语句中,而是将参数绑定到占位符上,然后统一交给数据库执行器去处理。这样可以避免通过字符串拼接方式构造 SQL 语句,从而防止 SQL 注入攻击。

假设有一个查询用户信息的 SQL 语句:

SELECT * FROM users WHERE id = :id

此时可以使用 bindParam() 方法将 id 参数绑定到占位符 :id 上,例如:

      $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();

审计

使用 execute() 方法执行查询,使用 fetch() 方法获取查询结果中第一行的数据,并将其存储到 $row 数组中。然后判断 $data->rowCount() 的值是否为 1,确保只有一个结果被返回.

在 SQLite 中,使用全局变量 $sqlite_db_connection 获取 SQLite 数据库连接对象,并使用 prepare() 方法准备 SQL 查询语句,在其中使用占位符 :id 代替 id 参数。

使用 bindValue() 方法将 id 参数绑定到占位符上,指定参数类型为整数类型。

使用 execute() 方法执行查询,并使用$result->numColumns()方法获取查询结果集的列数,如果列数为 2,则调用 $result->fetchArray() 方法获取查询结果集的第一行数据,将第一列的值赋值给 $row[0],第二列的值赋值给 $row[1],从而得到指定 user_id 的用户的 first_name 和 last_name 两个字段的值。

最后,使用 generateSessionToken() 函数在服务器端生成 Anti-CSRF 令牌,并将其存储到 $_SESSION['session_token'] 变量中。


总结

以上为DVWA之SQL注入—Impossible level代码审计。
往期参考:
[网络安全]DVWA之SQL注入—low level解题详析

[网络安全]DVWA之SQL注入—medium level解题详析

[网络安全]DVWA之SQL注入—High level解题简析

后续将分享SQL-Labs攻击姿势及解题详析。
我是秋说,我们下次见。

标签:last,name,level,DVWA,SQL,row,id,first
From: https://www.cnblogs.com/qiushuo/p/17368397.html

相关文章

  • PHP: mysql 5.7 and php 5.6 导入记事本编号查询不了和中文乱码问题
    --https://dev.mysql.com/doc/refman/8.0/en/charset-database.htmlshowvariableslike"character_set_%";CREATEDATABASE`geovindu`CHARACTERSETutf8COLLATEutf8_general_ci;--mysql官方说明文档才知道原来MySQL8.0已经已经把默认字符集升级成ut8mb4了,和5.0有区......
  • MySQL数据库设计规范
    一、背景规范及目的MySQL数据库与oracle、sqlserver等数据库相比,有其内核上的优势与劣势。我们在使用MySQL数据库的时候需要遵循一定规范,扬长避短。本规范旨在帮助或指导RD、QA、OP等技术人员做出适合线上业务的数据库设计。在数据库变更和处理流程、数据库表设计、SQL......
  • 【必知必会的MySQL知识】③DML语言
    目录前言准备插入数据语法格式插入完整行数据插入多行数据将检索出来的数据插入表更新数据准备两张表语法实践操作删除数据语法实践操作小结前言前面的两篇文章中,我们已经对MySQL有了基本了解。并且知道了怎么用工具连接数据库?怎么创建数据库?怎么创建表?这一篇呢我们就来看看怎......
  • SQL后半部和JDBC
    SQL后半部 排序orderbyasc升序desc降序select*from表名orderby列名asc;select*from表名orderby列名asc,列名desc; 聚合count selectcount(*)from表名where列名>200;sum selectsum(列名)from表名;maxminavg平均值 分组gr......
  • linux 下 mysql 安装目录在哪里。linux mysql 安装介绍:
    linux下mysql安装目录在哪里。linuxmysql安装介绍:linux服务器RedHat5.0.server.MySQL版本:下载地址链接:http://dev.mysql.com/downloads/mysql/5.1.htmlMySQL服务端:MySQL-server-community-5.1.38-0.rhel5.i386.rpmMySQL客户端:MySQL-client-community-5.1.38-......
  • mysql -- 保存查询结果和加载数据
    可以使用selectintooutfile语句将输出保存到文件中。可以指定列和行分割符,然后可以将数据导入其他数据平台。保存查询结果可以将输出目标另存为文件或表。1.另存为文件​ 要将输出结果保存到文件中,需要拥有file权限。FILE是一个全局特权,这意味着你不能将其限制为针对特定......
  • SQLite3数据库的介绍和使用(面向业务编程-数据库)
    SQLite3数据库的介绍和使用(面向业务编程-数据库)SQLite3介绍SQLite是一种用C语言实现的的SQL数据库它的特点有:轻量级、快速、独立、高可靠性、跨平台它广泛应用在全世界范围内的手机电脑应用的内建数据库官网地址:https://www.sqlite.org/index.htmlSQLite因为其采用文件存储......
  • 腾讯音乐SQL题
    1.计算歌曲完播率请根据user_listen_record、song_library计算出QQ音乐20230306歌曲完播率(播放时长>=听歌时长)输出表结构如下,其中完播率保留小数点后2位小数并按照完播率重小到大排序:song_playback_history已知QQ音乐部分用户听歌流水表格式和样例数据如下:user_listen_rec......
  • C#开发 B/S架构的实验室管理系统 云LIS系统(MVC + SQLserver + Redis)
    一、云LIS系统是将各种样本、免疫、临检、放免、及实验用的分析仪器,通过网络管理和传输实验分析过程中全部数据。对每一专业,实现检验申请、样本采集、样本核收、联机检验、质量控制、报告审核到报告发布的全环节的信息化管理平台。二、基于B/S架构的云LIS系统,整个系统的运行基于WE......
  • MySQL(十七)查询优化(二)与数据库主键设计
    查询优化(二)1覆盖索引什么是覆盖索引​ 看下面的例子,对于联合索引age_sno_name,当查询字段较少时能够使用索引,而字段较多的时候只能进行文件排序,这是由优化器判断通过索引加回表或者直接文件排序的成本来决定的。这种一个索引包含了满足查询结果的数据(select+where+join字......