6SQL注入攻击与防御 行命令的组件(如数据库服务器、应用服务器或Wb服务器)拥有相同的权限,这种权限通常级 别很高。 为展示该过程,我们回到之前的那个简单的在线零售商店的例子。如果读者有印象的话, 当时使用了下面的URL来尝试查看商店中所有价格低于$100的商品: .http://www.victim.com/products.php?val=100 注意: 为了便于展示,本章中的URL示例使用的是GET参数而非POST参数。POST参数操作 起来与GET一样容易,但通常要用到其他程序,比如流量管理工具、Wb浏览器插件或内联 代理程序。 这里我们尝试向输入参数val插入自己的SQL命令。可通过向URL添加字符串ORI'=I 来实现该目的: .http://www.victim.com/products.php?val=100'OR '1'='1 这次,PHP脚本构造并执行的SQL语句将忽略价格而返回数据库中的所有商品,这是因 为我们修改了查询逻辑。添加的语句导致查询中的OR操作符永远返回真(即1永远等于I), 从而出现这样的结果。下面是构造并执行的查询语句: SELECT FROM ProductsTbl WHERE Pr.1ce<'100.00'OR'1'='1' ORDER BY ProductDescription; 注意: 可通过多种方法来利用SQL注入漏洞以便实现各种目的。攻击成功与否通常高度依赖于 基础数据库和所攻击的互联系统。有时,完全挖掘一个漏洞需要有大量的技巧和坚强的毂力。 前面的例子展示了攻击者操纵动态创建的SQL语句的过程,该语句产生于未经验证或编 码的输入,并能够执行应用开发人员未预见或未曾打算执行的操作。不过,上述示例并未说明 这种漏洞的有效性,我们只是利用它查看了数据库中的所有商品。我们本可以使用应用最初提 供的功能来合法地实现该目的。但如果该应用可以使用CMS(Content Management System,内 容管理系统)进行远程管理,会出现什么情形呢?CMS是一种Web应用,用于为Wb站点创建、 编辑、管理及发布内容。它并不要求使用者对HTML有深入的了解或者能够进行编码。可使用 下面的URL访问CMS应用: .http://www.victim.com/cms/login.php?username=foo&password=bar 在访问该CMS应用的功能之前,需要提供有效的用户名和口令。访问上述URL时会产生 如下错误:“ncorrect username or password,please try again”。下面是login.php脚本的代码: /connect to the database Sconn mysql_connect ("localhost","username","password"); /dynamically build the sql statement with the input
第1章什么是SQL注入7 Squery "SELECT userid FROM CMSUsers WHERE user -'S_GET["user"]'". "AND password ='GET["password"]'"; /execute the query against the database Sresult mysql_query(Squery); /check to see how many rows were returned from the database Srowcount■mysql num rows(Sresult); /if a row is returned then the credentials must be valid,so /forward the user to the admin pages if (Srowcount !=0)(header("Location:admin.php");) /if a row is not returned then the credentials must be invalid else die('Incorrect username or password,please try again.')) login.php脚本动态地创建了一条SQL语句。如果输入匹配的用户名和口令,它将返回一 个记录集。下列代码更加清楚地说明了PHP脚本构造并执行的SQL语句。如果输入的usr和 password的值与CMSUsers表中存储的值相匹配,那么该查询将返回与该用户对应的userid。. SELECT userid FROM CMSUsers WHERE user 'foo'AND password ='bar' 这段代码的问题在于应用开发人员相信执行脚本时返回的记录数始终是0或1。在前面的 SQL注入示例中,我们使用了可利用的漏洞来修改SQL查询的含义以使其始终返回真。如果 对CMS应用使用相同的技术,那么将导致程序逻辑失败,向下面的URL添加字符串OR‘1'='1, 这次,由PHP脚本构造并执行的SQL语句将返回CMSUsers表中所有用户的userid。新的URL 如下所示: .http://www.victim.com/cms/login.php?username=foo&password=bar 'OR '1'='1 我们通过修改查询逻辑,返回了所有的userid。添加的语句导致查询中的OR操作符永远 返回真(即1永远等于1),从而出现了这样的结果。下面是构造并执行的查询语句: SELECT userid FROM CMSUsers WHERE user 'foo'AND password 'password'OR '1'='1'; 应用逻辑是指要想返回数据库记录,就必须输入正确的验证证书,并在返回记录后转而访 问受保护的admin.php脚本。我们通常是作为CMSUsers表中的第一个用户登录的。SQL注入 漏洞可以操纵并破坏应用逻辑。 警告: 不要在任何Wb应用或系统中使用上述示例,除非已得到应用或系统所有者的许可(最好 是书面形式).在美国,该行为会因违反l986年《计算机欺诈与溢用法》(Computer Fraud and Abuse Act of 1986)(www.cio.energy.gov/documents/ComputerFraud-AbuseAct.pdf)2001 国爱国者法案》(USA PATRIOT ACT of2001)而遭到起诉。在英国,则会因违反1990年的《计
8SQL注入攻击与防御 算机滥用法》(Computer Misuse Act of1990)(www.opsi.gov.uk/acts/acts1990/Ukpga19900018_cn_1) 和修订过的2006年的《警察与司法法裘》(Police and Justice Act of2006)(www.opsi.gov.uk/Acts/ acts2006/ukpga20060048cn1)而遭到起诉。如果控告并起诉成功,那么你将会面临罚款或漫 长的监禁。 著名事例 很多国家的法律并没有要求公司在经历严重的安全破坏时对外透露该信息(这一点与美国 不同),所以很难正确且精准地收集到有多少组织曾因SQL注入漏洞而遭受攻击或已受到危害。 不过,由恶意攻击者发动的安全破坏和成功攻击是当今新闻媒体中一个喜闻乐见的话题。即便 是最小的破坏(可能之前一直被公众所忽视),现在通常也会被大力宣传。 有些公共可用的资源可以帮助理解SQL注入问题的严重性。例如,通用漏洞披露组织 CVE(Common Vulnerabilities and Exposures)的Web站点上提供了一系列安全漏洞和公布信息, 目的在于为众所周知的问题提供统一命名。CVE的目标是使不同漏洞容器(工具、知识库和服 务)间的数据共享变得更容易。该网站整理众所周知的漏洞信息并提供安全趋势的统计分析。 在2007年的报告中(http:/lcwe.mitre.org/documents/vuln-trends/index.html),CVE共列举了其数 据库中的1754个SQL注入漏洞,其中944个是2006年新增的。SQL注入漏洞在CVE2006 年报告的所有漏洞中占l3.6%(http:/cwe.mitre.org/documents/.uln--trends/index.html),仅次于跨 站脚本(XSS)漏洞,但排在缓冲区溢出漏洞的前面。 此外,开放应用安全计划组织OWASP(Open Web Application Security Project)在其列举的 2007年10大最流行的影响Wb应用的安全漏洞中将注入缺陷(包括SQL注入)作为第二大漏 洞。OWASP列举出10个漏洞的主要目的是让开发人员、设计人员、设计师和组织了解最常见 的Wb应用安全漏洞所产生的影响。OWASP2007年公布的10大安全漏洞是对CVE数据进 行精简后汇编而成的。使用CVE数据来表示有多少网站受到过SQL注入攻击的问题是该数据 无法包括自定义站点中的漏洞。CVE需求代表的是商业和开源应用中己发现的漏洞数量,它们 无法反映现实中这些漏洞的存在情况。现实中的情况非常糟糕。 我们还可以参考其他专门整理受损Wb站点信息的站点所提供的资源。例如,Zone-H是 一个流行的专门记录Web站点毁损的Wb站点。该站点展示了近几年来因为出现可利用的 SQL注入漏洞而被黑客攻击的大量著名的Web站点和Web应用。自2001年以来,Microsoft 域中的Web站点已被破坏过46次(甚至更多).可以在Zone-H上在线查看受到攻击的Microsoft 站点的完整列表(www.zone-h.org/content/view/14980/1)。 传统媒体同样喜欢大力宣传因数据安全所带来的破坏,尤其是那些影响到著名的重量级公 司的攻击。下面是已报道的一些新闻的列表: ·2002年2月,Jeremiah Jacks发现Guess.com(www.securityfocus.com/hews/346)存在SQL 注入漏洞。他因此而至少获取了200000个用户信用卡信息的访问权。 ·2003年6月,Jeremiah Jacks再次发动攻击,这次攻击了PetCo.com(www.securityfocus. com/news/6194),他通过SQL注入缺陷获取了500000个用户信用卡信息的访问权。 ● 2005年6月17日,MasterCard为保证信用卡系统方案的安全,变更了部分受到破坏的 顾客信息。这是当时已知的此种破坏中最严重的一次。黑客利用SQL注入缺陷获取了4 千万张信用卡信息的访问权(www.ftc.gov/os/caselist/0523148/0523148 complaint..pdf
第1章什么是SQL注入9 ·2005年12月,Guidance Software(EnCase的开发者)发现一名黑客通过SQL注入缺陷 破坏了其数据库服务器(www.ftc.gov/os/caselist/0623057/0623057 complaint..pdf,导致 3800位用户的经济记录被泄露。 ·大约2006年12月,美国折扣零售商TX被黑客攻击,黑客从TX数据库中盗取了上 百万条支付卡信息。 以前黑客破坏Wb站点或Web应用是为了与其他黑客组织进行竞赛(以此来传播特定的政 治观点和信息),炫耀他们疯狂的技术或者只是报复受到的侮辱或不公。但现在黑客攻击Wb 应用更大程度上是为了从经济上获利。当今internet上潜伏的大量黑客组织均带有不同的动机。 其中包括只是出于对技术的狂热和“黑客”心理而破坏系统的个人,专注于寻找潜在目标以实 现经济增值的犯罪组织,受个人或组织信仰驱动的政治活动积极分子以及心怀不满、滥用职权 和机会以实现各种不同目的的员工和系统管理员。Wb站点或Wcb应用中的一个SQL注入漏 洞通常就足以使黑客实现其目标。 您的网站被攻击了么? 这种事不会发生在我身上,是吧? 多年来我评估过很多Wb应用,在所测试的应用中我发现有三分之一易遭受SQL注入 攻击。该漏洞所带来的影响因应用而异,但现在很多面向Internet的应用中均存在该漏 洞。很多应用暴露在不友善的环境中,比如未经过漏洞评估的Internet.毁坏Web站点 是一种非常嘈杂、显眼的行为,“脚本小子”'通常为赢得其他黑客组织的比分和尊重而 从事该活动,而那些非常严肃且目的明确的黑客则不希望自己的行为引起注意。对于老 练的攻击者来说,使用SQL注入漏洞获取内联系统的访问权并进行破坏是个完美可行 的方案。我曾不止一次告诉过客户他们的系统已遭受攻击,目前黑客正利用它们来从事 各种非法活动。有些组织和Wb站,点的所有者可能从未了解他们的系统之前是否被利 用过或者当前系统中是否已被黑客植入了后门程序。 2008年年初至今,数十万Wb站点遭到一种自动SQL注入攻击的破坏。该攻击使用一种 工具在internet上搜索存在潜在漏洞的应用。如果发现了存在漏洞的站点,该工具使自动利用 该漏洞。传递完可利用的净荷(payload)之后,它执行一个交互的SQL循环来定位远程数据库中 用户创建的每一张表,然后将恶意的客户端脚本添加到表的每个文本列中。由于大多数数据库 驱动的Wb应用使用数据库中的数据来动态构造Wb内容,因而该脚本最终会展现给受危害 的Web站点或应用的用户。标签(tag)会指示浏览器加载受感染的Web页面,从而执行远程服 务器上的恶意脚本。这种行为的目的是让该恶意程序感染更多主机。这是一种非常高效的攻击 方式。重要的站点(比如由政府部门维护的站点、联合国和较大公司的站点)均遭受过大量这种 攻击的破坏和感染。很难准确地弄清在连接到这些站点的客户端电脑和访问者中有多少受到了 感染或破坏(尤其是当发动攻击的个人自己定义传递的可利用净荷时)。 1.真正的黑客对那些只会模仿且水平低下的年青人的速称
10SQL注入攻击与防街 1.4理解SQL注入的产生过程 SQL是访问Microsoft SQL Server、Oracle、MySQL、Sybase和Informix(以及其他)数据库 服务器的标准语言。大多数Wb应用都需要与数据库进行交互,并且大多数Web应用编程语 言(如ASP、C#、NET、Jva和PHP)均提供了可编程的方法来与数据库相连并进行交互。如果 web应用开发人员无法确保在将从Web表单、cookie及输入参数等收到的值传递给SQL查询(该 查询在数据库服务器上执行)之前已经对其进行过验证,那么通常会出现SQL注入漏洞。如果 攻击者能够控制发送给SQL查询的输入,并且能够操纵该输入将其解析为代码而非数据,那 么攻击者就很可能有能力在后台数据库执行该代码。 每种编程语言均提供了很多不同的方法来构造和执行SQL语句,开发人员通常综合应用 这些方法来实现不同的目标。很多Wb站点提供了教程和代码示例来帮助应用开发人员解决 常见的编码问题,但这些讲述的内容通常都是些不安全的编码实践,而且示例代码也容易受到 攻击。如果应用开发人员未彻底理解交互的基础数据库或者未完全理解并意识到所开发代码的 潜在的安全问题,那么他们编写的应用通常是不安全的,易受到SQL注入攻击。 1.4.1构造动态字符串 构造动态字符串是一种编程技术,它允许开发人员在运行过程中动态构造$QL语句。开 发人员可以使用动态SQL来创建通用、灵活的应用。动态SQL语句是在执行过程中构造的, 它根据不同的条件产生不同的SQL语句。当开发人员在运行过程中需要根据不同的查询标准 来决定提取什么字段(如SELECT语句),或者根据不同的条件来选择不同的查询表时,动态构 造SQL语句会非常有用。 不过,如果使用参数化查询的话,开发人员可以以更安全的方式得到相同的结果。参数化 查询是指SQL语句中包含一个或多个嵌入参数的查询。可以在运行过程中将参数传递给这些 查询。包含的嵌入到用户输入中的参数不会被解析成命令而执行,而且代码不存在被注入的机 会。这种将参数嵌入到SQL语句中的方法比起使用字符串构造技术来动态构造并执行SQL语 句来说拥有更高的效率且更加安全。 下列PHP代码展示了某些开发人员如何根据用户输入来动态构造SQL字符串语句。该语句 从数据库的表中选择数据。它根据至少在数据库的一条记录中出现的用户输入值来返回记录。 /a dynamically built sql string statement in PHP Squery "SELECT FROM table WHERE field -'S GET["input"]'"; /a dynamically built sql string statement in .NET query "SELECT FROM table WHERE field -' request.getParameter("input")+""; 像上面那样构造动态SQL语句的问题是:如果在将输入传递给动态创建的语句之前,未 对代码进行验证或编码,那么攻击者会将SQL语句作为输入提供给应用并将SQL语句传递给 数据库加以执行。下面是使用上述代码构造的SQL语句: SELECT FROM TABLE WHERE FIELD input