Physical Address

304 North Cardinal St.
Dorchester Center, MA 02124

如何理解(和预防)SQL 注入攻击

SQL 注入基本上是一种基于 Web 的攻击。 该网站有一个表单,开发人员设计用于接受一些数据,处理它,并返回一些输出。 普通用户输入程序期望的内容。 但黑客利用 Web 表单(或格式错误的 URL)的机会执行恶意 SQL 代码,意图侵入、更改或破坏后端数据库,或试图从系统中检索机密信息。

黑客正在寻找您网站上接受用户输入的任何页面。 这可以是任何东西:登录页面、搜索页面、反馈页面。 用批判的眼光查看 HTML 页面中 <FORM> </FORM> 标记之间的内容。 这样做可以揭示有关可能被利用的领域的有用信息。

不要只看静态 HTML 页面。 SQL 注入可以在使用 ASP、JSP、CGI 或 PHP 的页面上使用,它们采用以下参数:

http://****.com/index.asp?id=1 

用特定的插图来展示它是如何工作的是最简单的。 (我的示例是从 Microsoft SQL Server 的角度来看的;在其他平台上并没有太大的不同)。

让我们举一个简单的网页示例,其中用户输入凭据进行登录。 可以通过许多不同的方式处理登录,例如:

string strQry = "SELECT Count(*) FROM Users WHERE UserName='" + 
txtUsrName.Text + "' AND Password='" + txtPasswd.Text + "'";

当这个动态生成的查询被创建和执行时,变量 txtUsrName.txt 和 txtPasswd.txt 被连接到查询中,然后传递给 SQL 数据库。 这里的重要词是 concatenated 。 如果 txtUsrName.Text 和 txtPasswd.Text 包含合法用户名和密码以外的任何值,则会盲目地将其传递给 SQL 数据库。 简而言之,这就是漏洞利用。 动态 SQL 指令是 SQL 注入最易受攻击的候选对象。

用户输入有效用户名和密码的晴天场景会产生如下语句:

[php]string strQry = "SELECT Count(*) FROM Users WHERE UserName='Sammy' AND Password='myPass';[/php] 

另一个可以打破查询的晴天场景是像 O’Hara 这样的名字。 查询字符串如下所示:

string strQry = "SELECT Count(*) FROM Users WHERE UserName='O'Hara' AND Password='myPass'; 

因为 O’Hara 有一个单引号,所以会导致语法错误。 例如,以下是此命令生成的 SQL Server 错误消息:

用于 ODBC 驱动程序的 Microsoft OLE DB 提供程序错误“80040e14”[Microsoft][ODBC SQL Server Driver][SQL Server]第 1 行:“H”附近的语法不正确。  /test/example.asp,第 45 行 

必须处理这样的问题,即使程序员认为她的代码是 SQL 注入安全的,仅仅是因为世界上有姓 O’Hara 的人。

但我们的重点是如何滥用它。 让我们看看黑客可以用那个登录页面做什么。 黑客首先尝试使用相同的单引号通过插入恶意代码来破坏系统。 普遍的第一步是黑客输入用户名字段:

' or 1=1 -- 

现在生成的查询字符串如下所示:

string strQry = " SELECT Count(*) FROM Users WHERE UserName = '' OR 1=1 -- AND Password = 'myPass'; 

1=1 将始终计算为 True,双连字符 (–) 是 SQL 中注释的标准形式。 结果,“1=1”之后的所有内容都被有效地注释掉了。 查询字符串如下所示,这是一个合法的 SQL 命令:

string strQry = " SELECT Count(*) FROM Users WHERE UserName='' OR 1=1 -- 

请注意,黑客没有有效的用户名和密码。 尽管如此,假设用户登录表中至少有一行,黑客已经成功获取了记录计数。 现在恶意黄鼠狼知道您的公司有多少用户或客户; 这本身就很烦人。

此外,如果黑客输入这样的字符串:

' OR 1=1; DROP TABLE USERS –-

……如果他有必要的权限,他就可以成功地放下桌子。 不幸的是,这并不难实现。 Web 应用程序经常以管理员级别的权限运行。 使用数据库的管理员帐户运行连接到数据库的应用程序有可能使攻击者对数据库执行几乎无限的命令。 管理员可以做的任何事情,攻击者也可以。

另一种利用可能是字符串的形式,如下所示:

' UNION SELECT id, name, '', 0 FROM sysobjects WHERE xtype ='U' – 

在这里,UNION 语句用于将一个查询的结果连接到另一个查询上。 同样,如果对 sysobjects 和 sycolumns 等重要系统表的访问不限于 Web 应用程序常规登录,则此查询可能会成功。 这种查询的输出提供了对内部数据库结构的访问权限,可以利用这些结构来操作整个表。 防范这种情况似乎是常识,但这些类型的攻击非常普遍。

上面的示例是可以在网站上执行的最简单的攻击形式。 但即使是最复杂的攻击也可以通过以下一些非常简单的措施来规避:

1. 使用参数化查询 。 这是防止 SQL 注入的最佳方法之一。 这样做时,变量不会连接到查询字符串,而是作为参数发送。 在表中搜索参数值以查找匹配项。 因此,如果我们在前面示例中使用的查询应该重写为:

string strQry = 
"SELECT Count(*) FROM Users WHERE UserName=@username" + 
"AND PassWord=@password"; 

@username 和@password 的值与表中字段的值进行比较,而不是连接。 如果黑客输入“a’ or 1=1 –”,则将 SQL 语句的结果与 表中的值进行比较。 这将返回 False 值,因为没有名称为“a’ or 1=1 –”的用户。

2. 不相信通过系统传来的数据 。 不对应用程序接收的数据大小、类型或内容做任何假设。 验证所有输入。 这涉及检查数据的长度以避免缓冲区溢出的实例。 如果字段需要字符串,请确保接收到的数据是字符串,而不是二进制数据或特殊字符。 这可以通过维护和比较白名单来完成,而不是试图找出什么是坏数据。 白名单中不存在的任何内容都将被拒绝。

3. 限制 Web 用户登录权限,仅访问相关表 。 如果该站点被利用,此措施会将损坏限制在一张桌子上。 简而言之,使用最低权限的数据库帐户。

4. 对所有用户提供的输入使用转义例程 。 参数化 SQL 有时是要走的路。 但是,如果由于某种原因,唯一可用的选项是动态 SQL,则应处理对 SQL Server 具有特殊含义的输入字符以保护输入。 转义例程向对 SQL Server 具有特殊含义的字符添加转义字符,从而使它们无害。

5. 构建强大的异常处理例程: 异常处理例程不应提供任何可能有助于黑客努力的信息。 在一个网站上,当我提供输入“a’ or 1=1 –”时收到此错误消息。

经验丰富的黑客会发现利用此类消息的漏洞。 永远不应披露错误消息。 为所有异常提供通用错误消息。

简单的预防措施可以 保护 Web 应用程序免受 SQL 注入 。 在设计时将应用程序安全作为优先事项,并将安全测试作为非功能性需求的一部分是良好编程实践的开始。 测试上面列出的每一点应该可以保护您的软件免受 SQL 注入的影响。

声明:文章来源与网络。仅用于学习,请勿使用非法用途