首页 >科技周边 >IT业界 >如何保护您的网站免受SQL注入攻击

如何保护您的网站免受SQL注入攻击

Lisa Kudrow
Lisa Kudrow原创
2025-02-18 09:09:09907浏览

How to Protect Your Website Against SQL Injection Attacks

SQL注入攻击:关键要点

SQL注入攻击是一种严重的网站安全威胁,攻击者利用网站输入通道中的漏洞来攻击其数据库,可能窃取或更改数据、破坏功能或获得管理访问权限。

为了防止SQL注入攻击,切勿信任用户输入,始终验证其是否存在潜在的攻击模式。这不仅包括文本输入,还包括隐藏输入、查询字符串参数、Cookie和文件上传。

应在服务器端验证用户输入,以确保其类型正确,并消除任何潜在的恶意命令。这可以通过多种方法实现,例如:为可能更改SQL命令的输入添加转义字符,或使用命令参数替换SQL命令中的用户输入。

定期检查网站代码是否存在潜在漏洞至关重要,做好SQL注入攻击的应急准备同样重要。限制潜在损害的措施包括:避免使用管理员权限、加密敏感数据以及除非绝对必要,否则不要存储敏感数据。

其他保护措施包括:对读写数据库操作使用单独的连接、将用户帐户访问权限限制在特定IP地址范围内、在MS SQL Server中使用Windows身份验证模型以及使用SHA-2等强算法进行密码哈希。

How to Protect Your Website Against SQL Injection Attacks

感谢Chris Lienert和Guido Tonnaer的帮助审阅本文。

在针对网站的所有攻击中,SQL注入是最危险和最普遍的一种,在过去一年中已被用于对企业和组织造成实际损害。该方案已被用于攻击知名组织和公司,包括TalkTalk、VTech、《华尔街日报》和美国政府。

简而言之,SQL注入(也称为SQLi)利用网站输入通道中的漏洞来攻击Web应用程序后端的数据库,其中存储着最敏感和最有价值的信息。攻击者可以使用此方案来窃取或篡改数据、妨碍应用程序功能,并在最坏的情况下获得对数据库服务器的管理访问权限。

以下是您需要了解的关于SQL注入以及如何保护您的网站免受其攻击的信息。

SQL注入攻击的工作原理

SQL注入攻击是通过Web请求向数据库服务器发送恶意SQL命令来进行的。任何输入通道都可以用来发送恶意命令,包括表单元素、查询字符串、Cookie和文件。

要了解其工作原理,假设您有一个接受用户名和密码的登录表单:

How to Protect Your Website Against SQL Injection Attacks

当用户输入其凭据并按下“登录”按钮时,信息将被发布回您的Web服务器,并与SQL命令组合在一起。例如,在PHP中,代码如下所示:

<code class="language-php">$sql_command = "select * from users where username = '" . $_POST['username']; 
$sql_command .= "' AND password = '" . $_POST['password'] . "'"; </code>

然后,该命令将被发送到数据库服务器,生成的dataset将确定用户名和密码是否与有效的用户帐户相对应。平均用户输入“john”作为用户名和“123456”作为密码(顺便说一句,切勿使用该密码)将转换为以下命令:

<code class="language-sql">SELECT * FROM users WHERE username='john' AND password='123456' </code>

但如果用户决定尝试其他内容,例如以下内容:

How to Protect Your Website Against SQL Injection Attacks

生成的命令将如下所示,它将始终返回非空dataset:

<code class="language-sql">SELECT * FROM users WHERE username='john' OR 1=1; -- ' AND password='123456' </code>

此代码片段可能会允许用户绕过登录屏幕而无需拥有正确的凭据。

这是最简单的SQL注入形式之一。只需付出更多努力,同一个用户就可以插入新的用户帐户,以及删除或修改现有用户帐户。在显示结果的页面中,可以使用相同的方案来显示本来仅限于普通访问者查看的记录和信息,或更改记录的内容。

在更严重的情况下,如果通过管理员帐户(例如MySQL中的“root”或MS SQL Server中的“sa”)连接到数据库服务器,攻击者甚至可以完全破坏服务器的操作系统。在Windows服务器上,这可能表现为攻击者执行扩展存储过程,例如xp_cmdshell。在一个案例中,攻击者利用SQL注入漏洞在受感染的服务器上创建用户帐户、启用远程桌面功能、设置SMB共享文件夹并上传恶意软件——除了实际上弄乱数据库中存储的所有内容之外。

如何保护自己免受SQL注入攻击

由于用户输入通道是SQL注入攻击的主要媒介,因此大多数防御方法都涉及控制和审查用户输入是否存在攻击模式。

以下是一些可以确保用户输入安全的措施。

切勿信任用户输入

关于用户输入的首要规则是“不信任并验证”,这意味着所有形式的用户输入都应被视为恶意,除非证明并非如此。这不仅适用于简单的输入框,例如文本区域和文本框,还适用于所有其他内容——例如隐藏输入、查询字符串参数、Cookie和文件上传。

仅仅因为浏览器的用户界面不允许用户操作输入,并不意味着无法篡改它。诸如Burp Suite之类的简单工具使用户能够捕获HTTP请求并在将其提交到服务器之前修改任何内容,包括隐藏的表单值。如果您认为自己通过Base64编码数据很聪明,恶意用户可以轻松地对其进行解码、修改和重新编码。

在服务器端验证输入字符串

验证是确保用户提供正确类型的输入并消除可能嵌入在输入字符串中的任何潜在恶意命令的过程。例如,在PHP中,您可以使用mysql_real_escape_string()来转义可能改变SQL命令性质的字符。

前面提到的登录代码的修改版本如下所示:

<code class="language-php">$sql_command = "select * from users where username = '" . $_POST['username']; 
$sql_command .= "' AND password = '" . $_POST['password'] . "'"; </code>

此简单的修改将通过在恶意用户故意添加的单引号前面添加转义字符()来保护您的代码免受攻击。

关于验证的一点说明:如果您添加了客户端验证函数,做得很好。但是不要将其依赖为针对SQL注入攻击的防御措施。虽然客户端函数可能会使向您的服务器发送恶意输入变得更难,但它很容易通过一些浏览器调整和诸如前面提到的工具来规避。因此,您需要用服务器端验证来补充它。

一些编程平台(例如ASP.NET)包含内置功能,这些功能会在页面回发时自动评估用户输入是否存在恶意内容。但是黑客可以通过足够的技巧和细致来规避它们,因此您仍然应该通过您自己的安全检查程序来运行用户输入。您永远不会过于谨慎。

使用命令参数

比转义更好的替代方法是使用命令参数。命令参数是通过在SQL命令中添加占位符名称来定义的,这些占位符名称稍后将被用户输入替换。ASP.NET为此目的提供了一组非常直观且易于使用的API。

以下是用C#编写的代码显示了如何使用命令参数来保护您的网站免受SQL注入攻击:

<code class="language-sql">SELECT * FROM users WHERE username='john' AND password='123456' </code>

您首先创建一个SqlCommand对象,并在命令字符串中使用@parameter_name范例,用户输入应插入到该范例中。

然后,您创建SqlParameter对象的实例,在其中插入用户输入,而不是直接将其与命令字符串连接起来。

最后,您将SqlParameter对象添加到SqlCommand对象的Parameters集合中,该集合将使用提供的输入替换参数。ADO.net负责其余工作。

在PHP中,等效项是预处理语句,它比其ASP.net对应项更复杂一些。您可以在这里探索它。

显式转换您的输入

此技巧适用于PHP等弱类型语言,这意味着您通常不会为变量定义数据类型,并且语言会自动处理彼此之间不同数据类型的转换。

显式转换可以作为在涉及非字符串类型时转义输入的快捷方式。因此,如果您希望用户为age参数输入一个int,您可以使用PHP中的以下代码来确保输入的安全:

<code class="language-sql">SELECT * FROM users WHERE username='john' OR 1=1; -- ' AND password='123456' </code>

请注意,此代码片段仅验证输入的类型,而不是其范围。因此,您必须运行其他代码以确保用户不会输入负年龄——或不切实际的年龄,例如1300。

此外,另一个最佳实践是避免在涉及非字符串输入的SQL命令中使用单引号。因此,不要使用以下代码……

<code class="language-php">$sql_command = "select * from users where username = '" . $_POST['username']; 
$sql_command .= "' AND password = '" . $_POST['password'] . "'"; </code>

……使用以下代码会更安全一些:

<code class="language-sql">SELECT * FROM users WHERE username='john' AND password='123456' </code>

如何根除SQL注入漏洞

作为一般做法,您应该检查每个页面的代码,查看您将页面内容、命令、字符串等与可能来自用户的来源组合在一起的地方。检查您的源代码是否存在漏洞和安全漏洞应该是软件开发过程中的一个固有部分。

您还可以使用sqlmap等扫描工具来抓取网站的页面,查找潜在的SQL注入漏洞。事实上,黑客经常使用此工具来查找和利用目标网站上的SQL注入攻击媒介,那么为什么不使用它来提高其安全性呢?

您的最后一道防线

无论您如何加强网站的安全,您都必须为SQL注入确实发生的那一天做好准备。毕竟,正如网络安全行业中众所周知的那样,防御者必须赢得每一场战斗,但黑客只需要赢一次。

以下是一些提示,可以帮助您在成为SQL注入受害者时最大限度地减少损害。

避免管理员权限

使用“root”或“sa”帐户将您的Web应用程序连接到数据库服务器是您可以犯下的最严重的错误之一。正如我已经提到的那样,被破坏的管理员帐户可能会让黑客访问整个系统。即使是非管理员帐户也可能造成损害,这些帐户可以访问服务器中的所有数据库,尤其是在数据库服务器在不同的应用程序和数据库之间共享时。

因此,最好使用一个帐户,该帐户仅对位于网站后端的特定数据库具有简单的读写权限,因此,如果您的网站通过SQL注入被黑客入侵,损害范围将仅限于该单个数据库的范围内。

一种更高级的方法是为从数据库读取或写入数据库的代码段使用单独的连接,并进一步减少每个段的权限和角色。例如,列表页面(不修改数据库,但广泛使用搜索参数)可以使用只读连接到数据库进行编码,以便进一步增强代码的抗故障能力。

在MySQL中,通过将对用户帐户的访问限制在特定的IP地址范围内(而不是“%”模型)来提高安全性,以防止从远程位置访问受损帐户。

在MS SQL Server中,我强烈建议您使用Windows身份验证模型,这将限制黑客对数据库的访问,并确保他们无法使用其他通道进入您的数据库。

此外,除非您计划使用SQL Server的一些高级功能,否则最好将Windows服务设置为使用受限帐户,而不是高权限的“本地系统”帐户。如果“sa”帐户被破坏,这将最大限度地减少损害。

加密敏感数据

加密数据库中的敏感数据。这包括密码、安全问题和答案、财务数据、健康信息以及其他可能对恶意行为者有用的信息。这将确保即使黑客掌握了您的数据,他们也无法立即利用它,这为您提供了时间来发现漏洞、堵塞漏洞并采取其他反应措施,例如强制重置密码,这将确保被盗数据在攻击者破译之前失去其价值。

如果您正在对密码进行哈希处理,请使用SHA-2等强算法,这很快将成为密码保护的行业标准。MD5和SHA-1已过时,可以被反转。

对于其他形式的加密,请注意您存储密钥的位置,切勿孤注一掷。如果密钥就在加密数据旁边,并且黑客一旦破坏服务器就会轻松访问它们,那么使用加密就没有意义了。

如果不需要,请不要存储敏感数据

每当您在数据库中存储信息时,请考虑如果信息落入坏人之手会造成多大的损害,并决定您是否真的需要存储它。Ashley Madison黑客事件将约3700万人的黑暗秘密和最私密信息泄露到互联网上,并造成了一些严重的损害,其成功部分归因于提供商没有从其数据库中删除敏感信息。

因此,底线是,除非您确实必须这样做,否则不要在数据库中存储敏感信息。即使那样,也要在信息不再有用时将其删除。

最终想法

SQL注入已经存在了几十年,并且可能会在未来几年继续占据漏洞排行榜的榜首。它只需要几个简单的——但经过精心计算的——步骤来保护您和您的用户免受其侵害,并且在审核源代码是否存在安全漏洞时,它应该是您的首要任务之一。

避免成为下一个大型SQL注入数据泄露事件受害者的关键是:首先,控制和验证用户输入;其次,为“何时”做好准备,而不是“是否”。

关于保护您的网站免受SQL注入攻击的常见问题解答(FAQ)

保护我的网站免受SQL注入攻击的第一步是什么?

保护您的网站免受SQL注入攻击的第一步是了解什么是SQL注入。SQL注入是一种代码注入技术,攻击者使用它将恶意SQL语句插入输入字段以进行执行。这可能导致未经授权访问敏感数据、数据丢失甚至数据损坏。一旦您了解了这一点,您就可以实施诸如输入验证、参数化查询和使用存储过程等措施来保护您的网站。

输入验证如何帮助防止SQL注入攻击?

输入验证是一种定义用户输入的语法、内容和逻辑值的方法。通过这样做,您可以防止攻击者将恶意SQL代码插入到网站的输入字段中。这是因为输入验证过程将拒绝任何不符合已定义条件的输入。

参数化查询是什么?它们如何防止SQL注入攻击?

参数化查询是一种SQL查询,其中使用占位符表示值,而值本身是在执行时提供的。这意味着即使攻击者试图插入恶意SQL代码,它也会被视为文字字符串,而不是SQL命令的一部分。这有效地防止了SQL注入攻击。

存储过程如何帮助防止SQL注入攻击?

存储过程是存储在数据库中并可以由应用程序调用的SQL语句。它们可以帮助防止SQL注入攻击,因为它们不允许直接访问数据库。相反,它们使用不被执行为SQL命令的参数,从而防止任何注入的SQL代码被执行。

错误处理在防止SQL注入攻击中起什么作用?

正确的错误处理可以通过不透露有关数据库结构或SQL语法的任何信息来帮助防止SQL注入攻击。这是因为当发生错误时,错误消息可以为攻击者提供有关数据库结构或SQL语法的线索,然后他们可以使用这些线索来改进其攻击。

我如何使用最小权限原则来保护我的网站免受SQL注入攻击?

最小权限原则意味着只为用户帐户或进程提供执行其预期功能所必需的权限。例如,如果用户帐户只需要从数据库读取数据,则无需授予其写入访问权限。这可以通过限制攻击者在设法利用漏洞时可以执行的操作来帮助防止SQL注入攻击。

定期更新在防止SQL注入攻击中起什么作用?

定期更新对于防止SQL注入攻击非常重要,因为它们通常包含针对已知漏洞的补丁。通过使您的软件保持最新,您可以确保您免受可能被SQL注入攻击利用的已知漏洞的侵害。

我如何使用Web应用程序防火墙来保护我的网站免受SQL注入攻击?

Web应用程序防火墙(WAF)可以通过过滤和监控Web应用程序和Internet之间的HTTP流量来帮助保护您的网站免受SQL注入攻击。它可以通过检测HTTP请求中的恶意SQL代码来识别和阻止SQL注入攻击。

入侵检测系统在防止SQL注入攻击中起什么作用?

入侵检测系统(IDS)可以通过监控网络流量并检测可疑活动来帮助防止SQL注入攻击。如果IDS检测到潜在的SQL注入攻击,它可以提醒管理员甚至采取措施阻止攻击。

我如何使用加密来保护我的网站免受SQL注入攻击?

加密可以通过使攻击者更难以读取敏感数据来帮助保护您的网站免受SQL注入攻击。即使攻击者设法利用SQL注入漏洞,他们仍然需要解密数据才能使用它。

以上是如何保护您的网站免受SQL注入攻击的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn