SQL注入(SQLi)是一种注入攻击,它使执行恶意SQL语句成为可能。这些语句控制Web应用程序后面的数据库服务器。攻击者可以使用SQL Injection漏洞绕过应用程序安全措施。他们可以遍历网页或Web应用程序的身份验证和授权,并检索整个SQL数据库的内容。他们还可以使用SQL Injection添加,修改和删除数据库中的记录。
SQL注入漏洞可能会影响使用SQL数据库的任何网站或Web应用程序,例如MySQL,Oracle,SQL Server或其他。犯罪分子可能会使用它来未经授权地访问您的敏感数据:客户信息,个人数据,商业秘密,知识产权等。SQL注入攻击是最古老,最普遍和最危险的Web应用程序漏洞之一。OWASP组织(开放式Web应用程序安全性项目)在其OWASP Top 102017文档中列出了注入,这是对Web应用程序安全性的头号威胁。
如何以及为什么执行SQL注入攻击
要进行SQL注入攻击,攻击者必须首先在网页或Web应用程序中找到易受攻击的用户输入。具有SQL注入漏洞的网页或Web应用程序直接在SQL查询中使用此类用户输入。攻击者可以创建输入内容。此类内容通常称为恶意有效负载,是攻击的关键部分。攻击者发送此内容后,将在数据库中执行恶意SQL命令。
SQL是一种查询语言,旨在管理关系数据库中存储的数据。您可以使用它来访问,修改和删除数据。许多Web应用程序和网站都将所有数据存储在SQL数据库中。在某些情况下,您还可以使用SQL命令来运行操作系统命令。因此,成功的SQL Injection攻击可能会带来非常严重的后果。
- 攻击者可以使用SQL注入来查找数据库中其他用户的凭据。然后,他们可以模拟这些用户。模拟用户可以是具有所有数据库特权的数据库管理员。
- SQL使您可以从数据库中选择和输出数据。SQL注入漏洞可能使攻击者能够完全访问数据库服务器中的所有数据。
- SQL还允许您更改数据库中的数据并添加新数据。例如,在金融应用程序中,攻击者可以使用SQL注入来更改余额,使交易无效或将资金转入其帐户。
- 您可以使用SQL从数据库中删除记录,甚至删除表。即使管理员进行数据库备份,删除数据也可能影响应用程序的可用性,直到还原数据库为止。此外,备份可能不会覆盖最新数据。
- 在某些数据库服务器中,您可以使用数据库服务器访问操作系统。这可能是有意或无意的。在这种情况下,攻击者可以使用SQL注入作为初始媒介,然后攻击防火墙后面的内部网络。
SQL注入攻击有几种类型:带内SQLi(使用数据库错误或UNION命令),盲SQLi和带外SQLi。您可以在以下文章中了解有关它们的更多信息:SQL注入(SQLi)的类型,盲目SQL注入:这是什么。
要逐步了解如何执行SQL Injection攻击以及可能造成的严重后果,请参阅:利用SQL Injection:动手示例。
简单的SQL注入示例
第一个例子很简单。它显示了攻击者如何利用SQL Injection漏洞来绕过应用程序安全性并以管理员身份进行身份验证。
以下脚本是在Web服务器上执行的伪代码。这是使用用户名和密码进行身份验证的简单示例。示例数据库有一个表users
,该表包含以下列:username
和password
。
# Define POST variables
uname = request.POST['username']
passwd = request.POST['password']
# SQL query vulnerable to SQLi
sql = “SELECT id FROM users WHERE username=’” + uname + “’ AND password=’” + passwd + “’”
# Execute the SQL statement
database.execute(sql)
这些输入字段容易受到SQL注入的攻击。攻击者可能以改变数据库服务器执行的SQL语句的方式在输入中使用SQL命令。例如,他们可以使用涉及单引号的技巧,并将passwd
字段设置为:
password' OR 1=1
结果,数据库服务器运行以下SQL查询:
SELECT id FROM users WHERE username='username' AND password='password' OR 1=1'
由于该OR 1=1
语句,无论and 是什么,该WHERE
子句都id
从users
表中返回第一个。数据库中的第一个用户通常是管理员。这样,攻击者不仅绕过身份验证,而且还获得了管理员特权。他们还可以注释掉其余的SQL语句,以进一步控制SQL查询的执行:username
password
id
-- MySQL, MSSQL, Oracle, PostgreSQL, SQLite
' OR '1'='1' --
' OR '1'='1' /*
-- MySQL
' OR '1'='1' #
-- Access (using null characters)
' OR '1'='1' %00
' OR '1'='1' %16
基于联合的SQL注入示例
SQL注入的最常见类型之一是使用UNION运算符。它允许攻击者将两个或多个SELECT语句的结果组合为一个结果。该技术称为基于联合的SQL注入。
以下是此技术的示例。它使用网页testphp.vulnweb.com,这是由Acunetix托管的故意易受攻击的网站。
以下HTTP请求是合法用户将发送的普通请求:
GET http://testphp.vulnweb.com/artists.php?artist=1 HTTP/1.1
Host: testphp.vulnweb.com
该artist
参数容易受到SQL注入的攻击。以下有效负载修改了查询以查找不存在的记录。它将URL查询字符串中的值设置为-1
。当然,它可以是数据库中不存在的任何其他值。但是,负值是一个很好的猜测,因为数据库中的标识符很少是负数。
在SQL注入中,UNION
运算符通常用于将恶意SQL查询附加到打算由Web应用程序运行的原始查询。注入查询的结果将与原始查询的结果结合在一起。这使攻击者可以从其他表中获取列值。
GET http://testphp.vulnweb.com/artists.php?artist=-1 UNION SELECT 1, 2, 3 HTTP/1.1
Host: testphp.vulnweb.com
下面的示例显示如何使用SQL Injection有效负载从这个故意易受攻击的站点获取更多有意义的数据:
GET http://testphp.vulnweb.com/artists.php?artist=-1 UNION SELECT 1,pass,cc FROM users WHERE uname='test' HTTP/1.1
Host: testphp.vulnweb.com

如何防止SQL注入
防止SQL注入攻击的唯一确定的方法是输入验证和参数化查询(包括准备好的语句)。应用程序代码永远不要直接使用输入。开发人员必须清除所有输入,而不仅仅是登录表单之类的Web表单输入。他们必须删除潜在的恶意代码元素,例如单引号。关闭生产站点上数据库错误的可见性也是一个好主意。数据库错误可与SQL Injection一起使用,以获取有关数据库的信息。
如果发现SQL注入漏洞(例如使用Acunetix扫描),则可能无法立即修复。例如,该漏洞可能位于开放源代码中。在这种情况下,您可以使用Web应用程序防火墙临时清理您的输入。
要了解如何预防PHP语言中的SQL Injection攻击,请参阅:防止PHP应用程序中的SQL Injection漏洞并修复它们。要了解如何使用许多其他不同的编程语言来执行此操作,请参阅Bobby Tables指南以防止SQL注入。