3.2.3 SQL注入漏洞案例及分析

3.2.3 SQL注入漏洞案例及分析

1.定义

几乎每一个Web应用程序都使用数据库来保存操作所需的各种信息。例如,网上零售商所用的Web应用程序使用数据库保存以下信息:

用户账户、证书和个人信息;

所销售商品的介绍与价格;

订单、账单和支付细节;

每名应用程序用户的权限。

数据库中的信息通过结构化查询语言(Structured Query Language,SQL)访问。SQL可用于读取、更新、增加或删除数据库中保存的信息。

SQL是一种解释型语言,Web应用程序经常建立合并用户提交的数据的SQL语句。因此,如果建立语句的方法不安全,那么应用程序可能易于受到SQL注入攻击。这种缺陷是困扰Web应用程序的最臭名昭著的漏洞之一,在最严重的情形中,匿名攻击者可利用SQL注入读取并修改数据库中保存的所有数据,甚至完全控制运行数据库的服务器。随着Web应用程序安全意识的日渐增强,SQL注入漏洞越来越少,同时也变得更加难以检测与利用。许多主流应用程序采用API来避免SQL注入,如果使用得当,这些API能够有效阻止SQL注入攻击。在这些情况下,通常只有在无法应用这些防御机制时,SQL注入才会发生。有时,查找SQL注入漏洞是一项艰难的任务,需要测试员坚持不懈地在应用程序中探查一两个无法应用常规控制的实例。

随着这种趋势的变化,查找并利用SQL注入漏洞的方法也在不断改进,通常使用更加微妙的漏洞指标以及更加完善与强大的利用技巧。我们首先分析最基本的情况,然后进一步描述最新的盲目检测与利用技巧。

有大量广泛的数据库可为Web应用程序提供支持。虽然对绝大多数数据库而言,SQL注入的基本原理大体相似,但它们之间也存在着许多差异,包括语法上的细微变化以及可能影响攻击者所使用的攻击类型的巨大行为与功能差异。

2.案例分析

下面以一个书籍零售商使用的Web应用程序为例,该应用程序允许用户根据作者、书名、出版商等信息搜索产品。完整的书籍目录保存在数据库中,应用程序使用SQL查询,根据用户提交的搜索项获取各种书籍的信息。当一名用户搜索由Wiley出版的所有书籍时,应用程序执行以下查询:

该查询要求数据库检查书籍表的第一行,提取每条publisher列为Wiley值的记录,并返回所有这些记录,然后应用程序处理这组记录,并通过一个HTML页面将结果显示给用户。在这个查询中,等号左边的词由SQL关键字、表和数据库列名称构成。这个部分的全部内容由程序员在创建应用程序时建立。当然,表达式Wiley由用户提交,它是一个数据项。SQL查询中的字符串数据必须包含在单引号内,与查询的其他内容分隔开来。现在思考一下,如果用户搜索所有由O Reilly出版的书籍,会出现什么情况。应用程序将执行以下查询:

在这个示例中,查询解释器以和前面一个示例相同的方式到达字符串数据位置。它解析这个包含在单引号中的数据,得到值0。然后遇到表达式Reilly,这并不是有效的SQL语法,因此应用程序生成一条错误消息:

如果应用程序以这种方式运行,那么它非常容易遭到SQL注入。攻击者可提交包含引号的输入终止他控制的字符串,然后编写任意的SQL修改开发者想要应用程序执行的查询。例如,在这个示例中,攻击者可以对查询进行修改,通过输入以下搜索项,返回零售商目录中的每一本书。

应用程序将执行以下查询:

这个查询对开发者查询中的WHERE子句进行修改,增加了另外一个条件。数据库将检查书籍表的每一行,提取publisher列值为Wiley或其中1等于1的每条记录。因为1总是等于1,所以数据库将返回书籍表中的所有记录。

攻击者的输入中的“--”在SQL中是一个有意义的表达式,它告诉查询解释器该行的其他部分属于注释,应被忽略。在一些SQL注入攻击中,这种技巧极其重要,因为它允许忽略由应用程序开发者建立的查询的剩余部分。在上面的示例中,应用程序将用户提交的字符串包含在单引号中。因为攻击者已经终止他控制的字符串并注入一些其他SQL,他需要处理字符串末尾部分的引号,避免出现和O Reilly示例中相同的语法错误。攻击者通过添加一个“--”达到这一目的,将查询的剩余部分以注释处理。在MySQL中,需要在双连字符后加入一个空格,或者使用“#”符号指定注释。

原始查询还将访问仅限于已出版的书籍,因为它指定“and published=1”。通过注入注释序列,攻击者获得未授权访问权限,可以返回所有书籍(包括已出版及其他书籍)的详细信息。很明显,前面的示例不会造成严重的安全威胁,因为用户使用完全合法的方法就可以访问全部书籍信息。但是,稍后我们将描述如何利用这种SQL注入漏洞从各种数据库表中提取任何数据,并提升在数据库和数据库服务器中的权限。为此,不管出现在哪个应用程序功能中,任何SQL注入漏洞都应被视为极其严重的威胁。