16SQL注入攻击与防御 /pass the string to an external validator sbool validate(input string GET["param"]); if(sboo1=true)【 /continue processing /process form 2 if (GET["form"]"form2")( /no need to validate param as forml would have validated it for us SSQL "SELECT FROM TABLE WHERE ID =GET["param"]"; /execute sql statement Sresult mysql_query(SSQL); //check to see how many rows were returned from the database Srowcount mysql_num_rows(Sresult); Srow 1; /iterate through the record set returned while (Sdb field mysql_fetch_assoc(Sresult))( if (Srow <Srowcount)( print $db_field[srow】·"<BR>"; Srow++; 该应用的开发人员没有想到第二个表单也需要验证输入,因为第一个表单已进行过输入验 证了。攻击者将不使用第一个表单而是直接调用第二个表单,或是简单地向第一个表单提交有 效数据,然后操纵要向第二个表单提交的数据。下面的第一个URL会失败,因为需要验证输 入。第二个URL则会引发成功的SQL注入攻击,因为输入未作验证: [1]http://www.victim.com/form.php?form=forml¶m='SOL Failed - [2]http://www.victim.com/form.php?form=form2sparam=' SQL Success - 1.4.2不安全的数据库配置 可以使用很多方法来减少可修改的访问、可被窃取或操纵的数据量、内联系统的访问级别 以及SQL注入攻击所导致的破坏。保证应用代码的安全是首要任务,但也不能忽视数据库本 身的安全。数据库带有很多默认的用户预安装内容。SQL Server使用声名狼藉的“sa”作为数 据库系统管理员账户,MySQL使用“root”和“anonymous”用户账户,Oracle则在创建数据 库时通常默认会创建SYS、SYSTEM、DBSNMP和OUTLN账户。这些并非全部的账户,只 是比较出名的账户中的一部分,还有很多其他账户。其他账户同样按默认方式进行预设置,口 令众所周知。 有些系统和数据库管理员在安装数据库服务器时允许以root、SYSTEM或Administrator 特权系统用户账户身份执行操作。应该始终以普通用户身份(尽可能位于更改根目录的环境中) 运行服务器(尤其是数据库服务器)的服务,以便在数据库遭到成功攻击后可以减少对操作系统
第1章什么是SQL注入17 和其他进程的潜在破坏。不过,这对于Windows下的Oracle却是不可行的,因为它必须以 SYSTEM权限运行。 不同类型的数据库服务器还施加了自己的访问控制模型,它们为用户账户分配多种权限来 禁止、拒绝、授权、支持数据访问和(或)内置存储过程、功能或特性的执行。不同类型的数据 库服务器默认还支持通常超出需求但能够被攻击者修改的功能(xp cmdshell、OPENROWSET、 LOAD FILE、ActiveX以及Java支持等)。第4章到第7章将详细介绍修改这些功能和特性的 攻击。 应用开发人员在编写程序代码时,通常使用某个内置的权限账户来连接数据库,而不是根 据程序需要来创建特定的用户账户。这些功能强大的内置账户可以在数据库上执行很多与程序 需求无关的操作。当攻击者利用应用中的SQL注入漏洞并使用授权账户连接数据库时,他可 以在数据库上使用该账户的权限执行代码。W®b应用开发人员应与数据库管理员协同工作,以 保证程序的数据库访问在最低权限模型下运行,同时应针对程序的功能性需求适当地分离授权 角色。 理想情况下,应用还应使用不同的数据库用户来执行SELECT、UPDATE、NSERT及类 似的命令。这样一来,即使攻击者成功将代码注入到易受攻击的语句,为其分配的权限也是最 低的。由于多数应用并未进行权限分离,所以攻击者通常能访问数据库中的所有数据,并且拥 有SELECT、NSERT、UPDATE、DELETE、EXECUTE及类似的权限。这些过高的权限通常 允许攻击者在数据库间跳转,访问超出程序数据存储区的数据。 不过,要实现上述目标,攻击者需要了解可以获取哪些附加内容、目标机器安装了哪些其 他数据库、存在哪些其他的表以及哪些有吸引力的字段!攻击者在利用SQL注入漏洞时,通 常会尝试访问数据库的元数据。元数据是指数据库内部包含的数据,比如数据库或表的名称、 列的数据类型或访问权限。有时也使用数据字典和系统目录等其他项来表示这些信息。MySQL 服务器(5.0及之后的版本)的元数据位于NFORMATION SCHEMA虚拟数据库中,可通过 SHOW DATABASES和SHOW TABLES命令访问.所有MySQL用户均有权访问该数据库中的 表,但只能查看表中那些与该用户访问权限相对应的对象的行。SQL Server的原理与MySQL 类似,可通过NFORMATION SCHEMA或系统表(sysobjects、sysindexkeys、sysindexes、 syscolumns、.systypes等)及(或)系统存储过程来访问元数据。SQL Server2005引入了一些名为 “sys.*”的目录视图,并限制用户只能访问拥有相应访问权限的对象。所有的SQL Server用户 均有权访问数据库中的表并可以查看表中的所有行,而不管用户是否对表或所查阅的数据拥有 相应的访问权限。 Oracle提供了很多全局内置视图来访问Oracle的元数据(ALL TABLES、 ALL TAB COLUMNS等)。这些视图列出了当前用户可访问的属性和对象。此外,以USER 开头的视图只显示当前用户拥有的对象(例如,更加受限的元数据视图):以DBA开头的视图 显示数据库中的所有对象(例如,用于数据库示例且不受约束的全局元数据视图)。DBA元数 据函数需要有数据库管理员(DBA)权限。下面是这些语句的示例: -Oracle statement to enumerate all accessible tables for the current user SELECT OWNER,TABLE NAME FROM ALL TABLES ORDER BY TABLE NAME; --MySQL statement to enumerate all accessible tables and databases for the --current user SELECT table schema,table name FROM information schema.tables; --MS SQL statement to enumerate all accessible tables using the system
18SQL注入攻击与防御 -tables SELECT name FROM sysobjects WHERE xtype ='U'; --MS SQL statement to enumerate all accessible tables using the catalog --views SELECT name FROM sys.tables; 注意: 要隐藏或取消对MySQL数据库中INFORMATION SCHEMA虚拟数据库的访问是不可能 的,也不可能隐藏或取消对Oracle数据库中数据字典的访问(因为它是一个视图)。可以通过修 改视图来对访问加以约束,但Oracle不提倡这么做。可以取消对SQL Server数据库中的 NFORMATION_SCHEMA、system和sys.*表的访问,但这样会破坏某些功能并导致部分与数 据库交互的应用出现问题。更好的解决办法是为应用的数据库访问运行一个最低权限模型,并 针对程序的功能性需求适当地分离授权角色· 1.5 本章小结 通过本章,您学到了一些引发SQL注入的因素,从应用的设计和架构到开发人员行为以 及在构建应用的过程中使用的编码风格。我们讨论了当前流行的多层(n层)Wb应用架构中通 常包含的带数据库的存储层,是如何与其他层产生的数据库查询(通常包含某些用户提供的信 息)进行交互的。我们还讨论了动态字符串构造(也称动态SQL)以及将$QL查询组合成一个字 符串并与用户提供的输入相连的操作。该操作会引发SQL注入,因为攻击者可以修改SQL查 询的逻辑和结构,进而执行完全违背开发人员初衷的数据库命令。 我们将在后面的章节中进一步讨论SQL注入,不仅学习SQL注入的发现和区分(第2章和 第3章)、$QL注入攻击和SQL注入的危害(第4~7章),还将学习如何对SQL注入进行防御(第 8章和第9章)。最后在第10章,我们会给出很多方便的参考资源、建议和备忘单以帮助读者 快速找到需要的信息。 您应该反复阅读并实践本章的例子,这样才能巩固对SQL注入概念及其产生过程的理解。 掌握这些知识后,才算踏上了在现实中寻找、利用并修复SQL注入的漫漫征程。 1.6 快速解决方案 1.理解Web应用的工作原理 Web应用是一种使用Wcb浏览器并通过nternet或内部网访问的程序。它同时还是一 种使用浏览器所支持语言(如HTML、JavaScript、Java等)编写的计算机软件程序,借 助普通的Web浏览器来呈现应用程序的可执行文件。 ·基本的数据库驱动的动态Wb应用通常包含一个后台数据库和很多包含服务器端脚本 的Wb页面,这些脚本则是由可从数据库(数据库的选择依不同的交互而定)中提取特 定信息的编程语言编写而成的。 ·基本的数据库驱动的动态Wcb应用通常包含三层:表示层(Wb浏览器或渲染引擎)、 逻辑层(如C#、ASP、NET、PHP、JSP等编程语言)和存储层(如SQL Server、MySQL
第1章什么是SQL注入19 Oracle等数据库)。Web浏览器(表示层,Internet Explorer、Safari、Firefox等)向中间层 (逻辑层)发送请求,中间层通过查询、更新数据库(存储层)来响应该请求。 2.理解SQL注入 ·$QL注入是一种将SQL代码插入或添加到应用(用户)的输入参数中,之后再将这些参 数传递给后台的SQL服务器加以解析并执行的攻击。 ·SQL注入的主要方式是直接将代码插入到参数中,这些参数会被置入SQL命令中加以 执行。 ·攻击者能够修改SQL语句时,该进程将与执行命令的组件(如数据库服务器、应用服 务器或Web服务器)拥有相同的权限,该权限通常级别很高。 3.理解SQL注入的产生过程 ·如果Web应用开发人员无法确保在将从Web表单、cookie、输入参数等收到的值传递 给SQL查询(该查询在数据库服务器上执行)之前已经对其进行过验证,那么通常就会 出现SQL注入漏洞。 ·如果攻击者能够控制发送给SQL查询的输入,并且能操纵该输入将其解析为代码而非 数据,那么攻击者就可能有能力在后台数据库上执行该代码。 ·如果应用开发人员无法彻底理解与他们交互的基础数据库或者无法完全理解并意识到 所开发代码潜在的安全问题,那么他们编写的应用通常是不安全的,并且容易受到$QL 注入攻击。 1.7常见问题解答 问题:什么是SQL注入? 解答:SQL注入是一种通过操纵输入来修改后台SQL语句以达到利用代码进行攻击目的 的技术。 问题:是否所有数据库都易受到SQL注入攻击? 解答:根据情况的不同,大多数数据库都易受到攻击。 问题:SQL注入漏洞有哪些影响? 解答:这取决于很多因素。例如,攻击者可潜在地操纵数据库中的数据,提取更多应用允 许范围之外的数据,并可能在数据库服务器上执行操作系统命令。 问题:SQL注入是一种新漏洞吗? 解答:不是。自SQL数据库首次连接至Wb应用起,SQL注入就可能已经存在。但它首 次引起公众注意是在1998年的圣诞节。 问题:如果我向一个Wb站点插入单引号(),真的会遭到起诉么? 解答:是的,除非您这样做有合法的理由(例如,您的名字中包含一个单引号,如ONi)
20SQL注入攻击与防御 问题:如果某人故意在输入中添加了一个单引号字符,代码会怎样执行? 解答:SQL数据库将单引号字符解析成代码与数据间的分界线:假定单引号外面的内容均 为需要运行的代码,而用单引号括起来的内容均为数据。 问题:如果Wb站点禁止输入单引号字符,是否能避免SQL注入? 解答:不能。可使用很多方法对单引号字符进行编码,这样就能将它作为输入来接收。有 些SQL注入漏洞不需要使用该字符。此外,单引号字符并不是唯一可用于SQL注 入的字符,攻击者还可以使用很多其他字符,比如双竖线()和双引号字符(“)等。 问题:如果Web站点不使用GET方法,是否能避免SQL注入? 解答:不能。POST参数同样容易被操纵。 问题:我的应用是用PHP/ASP/Perl/,NET/Java等语言编写的。我选择的语言是否能避免 SQL注入? 解答:不能。任何编程语言,只要在将输入传递给动态创建的SQL语句之前未经过验证, 就容易潜在地受到攻击,除非使用参数化查询和绑定变量