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

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

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攻击姿势及解题详析。

我是秋说,我们下次见。


目录
相关文章
|
2月前
|
SQL 安全 前端开发
Web学习_SQL注入_联合查询注入
联合查询注入是一种强大的SQL注入攻击方式,攻击者可以通过 `UNION`语句合并多个查询的结果,从而获取敏感信息。防御SQL注入需要多层次的措施,包括使用预处理语句和参数化查询、输入验证和过滤、最小权限原则、隐藏错误信息以及使用Web应用防火墙。通过这些措施,可以有效地提高Web应用程序的安全性,防止SQL注入攻击。
67 2
|
4月前
|
SQL 安全 数据库
惊!Python Web安全黑洞大曝光:SQL注入、XSS、CSRF,你中招了吗?
在数字化时代,Web应用的安全性至关重要。许多Python开发者在追求功能时,常忽视SQL注入、XSS和CSRF等安全威胁。本文将深入剖析这些风险并提供最佳实践:使用参数化查询预防SQL注入;通过HTML转义阻止XSS攻击;在表单中加入CSRF令牌增强安全性。遵循这些方法,可有效提升Web应用的安全防护水平,保护用户数据与隐私。安全需持续关注与改进,每个细节都至关重要。
148 5
|
4月前
|
SQL 安全 数据库
深度揭秘:Python Web安全攻防战,SQL注入、XSS、CSRF一网打尽!
在Web开发领域,Python虽强大灵活,却也面临着SQL注入、XSS与CSRF等安全威胁。本文将剖析这些常见攻击手段,并提供示例代码,展示如何利用参数化查询、HTML转义及CSRF令牌等技术构建坚固防线,确保Python Web应用的安全性。安全之路永无止境,唯有不断改进方能应对挑战。
89 5
|
4月前
|
SQL 安全 数据安全/隐私保护
Python Web安全大挑战:面对SQL注入、XSS、CSRF,你准备好了吗?
在构建Python Web应用时,安全性至关重要。本文通过三个真实案例,探讨了如何防范SQL注入、XSS和CSRF攻击。首先,通过参数化查询替代字符串拼接,防止SQL注入;其次,利用HTML转义机制,避免XSS攻击;最后,采用CSRF令牌验证,保护用户免受CSRF攻击。这些策略能显著增强应用的安全性,帮助开发者应对复杂的网络威胁。安全是一个持续的过程,需不断学习新知识以抵御不断变化的威胁。
140 1
|
4月前
|
SQL 安全 数据库
Python Web开发者必看!SQL注入、XSS、CSRF全面解析,守护你的网站安全!
在Python Web开发中,构建安全应用至关重要。本文通过问答形式,详细解析了三种常见Web安全威胁——SQL注入、XSS和CSRF,并提供了实用的防御策略及示例代码。针对SQL注入,建议使用参数化查询;对于XSS,需对输出进行HTML编码;而防范CSRF,则应利用CSRF令牌。通过这些措施,帮助开发者有效提升应用安全性,确保网站稳定运行。
67 1
|
4月前
|
SQL 安全 数据库
深度揭秘:Python Web安全攻防战,SQL注入、XSS、CSRF一网打尽!
在Web开发领域,Python虽强大灵活,但安全挑战不容小觑。本文剖析Python Web应用中的三大安全威胁:SQL注入、XSS及CSRF,并提供防御策略。通过示例代码展示如何利用参数化查询、HTML转义与CSRF令牌构建安全防线,助您打造更安全的应用。安全是一场持久战,需不断改进优化。
62 3
|
4月前
|
SQL 安全 数据库
从入门到精通:Python Web安全守护指南,SQL注入、XSS、CSRF全防御!
【9月更文挑战第13天】在开发Python Web应用时,安全性至关重要。本文通过问答形式,详细介绍如何防范SQL注入、XSS及CSRF等常见威胁。通过使用参数化查询、HTML转义和CSRF令牌等技术,确保应用安全。附带示例代码,帮助读者从入门到精通Python Web安全。
106 6
|
4月前
|
SQL 安全 JavaScript
告别Web安全小白!Python实战指南:抵御SQL注入、XSS、CSRF的秘密武器!
【9月更文挑战第12天】在Web开发中,安全漏洞如同暗礁,尤其对初学者而言,SQL注入、跨站脚本(XSS)和跨站请求伪造(CSRF)是常见挑战。本文通过实战案例,展示如何利用Python应对这些威胁。首先,通过参数化查询防止SQL注入;其次,借助Jinja2模板引擎自动转义机制抵御XSS攻击;最后,使用Flask-WTF库生成和验证CSRF令牌,确保转账功能安全。掌握这些技巧,助你构建更安全的Web应用。
79 5
|
5月前
|
SQL 安全 API
PHP代码审计示例(一)——淡然点图标系统SQL注入漏洞审计
PHP代码审计示例(一)——淡然点图标系统SQL注入漏洞审计
118 4
|
6月前
|
SQL 安全 数据库
Python Web开发者必看!SQL注入、XSS、CSRF全面解析,守护你的网站安全!
【7月更文挑战第27天】在 Python Web 开发中, 安全至关重要。
84 0