打印本文 关闭窗口 | ||||||
运用LINQ轻松清除SQL注入式攻击 | ||||||
作者:陈鹏 文章来源:eNet 点击数 更新时间:2009/9/11 23:24:41 文章录入:陈鹏 责任编辑:陈鹏 | ||||||
|
||||||
微软的LINQ to SQL技术为.net开发人员提供了一种机会,使其可以清除所开发的Web应用程序中SQL注入式安全漏洞的可能性。 随着对Web安全破坏的与日俱增,开发人员越来越深刻地认识到需要为其开发的应用程序的安全性承担更大的责任,而且应用程序框架的厂商们也将更坚实的安全特性构建到其应用软件中去。许多开发人员已经认识到构建安全应用程序和防止破坏性攻击的最有效的方法就是从一开始就要安全地设计和实施应用程序。不幸的是,开发团队往往缺乏训练和资源来做出关于应用程序安全的科学设计决策。 在开发人员承受越来越多的安全责任之时,许多开发人员了解到的第一个Web应用安全漏洞,是一个被称为“SQL注入”的极危险的命令注入形式。命令注入的原始的形式本是指这样一种漏洞:攻击者通过提供一个正常使用者意料之外的输入,改变你的Web应用程序的运行方式,从而允许攻击者运行服务器上的非授权的命令。无疑,SQL注入式攻击是很常见的、被广泛使用的攻击形式。幸运的是,一旦我们理解了这个问题,就可以很容易地防止SQL注入式攻击。更妙的是,现在微软的数据访问技术向.net开发人员提供了彻底地清除SQL注入漏洞的机会,当然前提是能够正确使用。这种技术称为“语言级集成查询”(Language Integrated Query (LINQ)),并随Visual Studio "Orcas" 和 .NET Framework 3.5一起发布。本文将讨论如何通过LINQ强化Web应用程序的数据访问代码,从而解决通过SQL注入进行攻击的问题。 概述 SQL注入是一种Web应用程序的安全漏洞,通过它攻击者可以将恶意数据提交给应用程序,欺骗应用程序在服务器上执行恶意的SQL命令。理论上讲,这种攻击是容易预防的,不过由于其允许攻击者直接运行针对用户关键数据的数据库命令,从而成为一种常见的、危害性大的攻击形式。在非常极端的情况下,攻击者不但能够自由地控制用户的数据,还可以删除数据表和数据库,甚至控制整个数据库服务器。 如果这种攻击容易预防,那么为什么还如此危险呢?首先,由于众所周知的经济上的原因,你的应用数据库是非常诱人的,可以引起攻击者的极大注意。如果SQL注入漏洞在Web应用程序中可能存在着,那么对于一个攻击者来说是很容易检测到的,然后就可以利用它。很显然,即使SQL注入错误并不是开发人员最经常犯的错误,它们也很容易被发现和利用。 检测SQL注入漏洞的一个简单方法是在一次输入中插入一个元字符(meta-character),一个应用程序会用这个字符生成一个数据库访问语句。例如,在任何包含一个搜索输入栏的Web站点上,一个攻击者可以输入一个数据库元字符,例如一个核对符号(),然后单击“搜索”按钮提交输入。如果应用程序返回一个数据库错误消息,攻击者不但会知道他已经发现了一个应用程序的数据库驱动部分,而且他还能注入更加有意义的命令,让你的服务器执行它们。应用程序安全研究员Michael Sutton近来强调,发现那些易于受到SQL攻击的站点是很容易的。他说,使用Google搜索API这种方法只需几分钟就可以确定大量的潜在的易受攻击的站点。 对SQL注入的剖析 这里我们给出一个SQL注入的例子来说明两个问题,一是SQL注入这种错误是很容易犯的,二是只要进行严格的程序设计,这种错误是很容易预防的。 这个示例用的Web应用程序包含一个名为SQLInjection.aspx简单的客户搜索页面,这个页面易于受到SQL注入攻击。此页面包含一个CompanyName的输入服务器控件,还有一个数据表格控件,用于显示从微软的示例数据库Northwind的搜索结果(这个数据库可从SQL Server 2005中找到)。在搜索期间执行的这个查询包含一个应用程序设计中很普通的错误:它动态地从用户提供的输入中生成查询。这是Web应用程序数据访问中的一个主要的错误,因为这样实际上潜在地相信了用户输入,并直接将其发送给你的服务器。在从“搜索”的单击事件启动时,这个查询看起来是这个样子:
在这种情况下,如果一个用户输入“Ernst Handel”作为公司名,并单击“搜索”按钮,作为响应屏幕会向用户显示那个公司的记录,这正是我们所期望的理想情况。不过一个攻击者可以轻易地操纵这个动态查询。例如,攻击者通过插入一个UNION子句,并用一个注释符号终止这个语句的剩余部分。换句话说,攻击者不是输入“Ernst Handel”,而是输入如下的内容:
其结果是这个SQL语句在服务器端执行,由于添加了这个恶意的请求。它会将这个动态的SQL查询转换为下面的样子:
这是一个相当合法的SQL语句,它可以在应用程序数据库上执行,返回order表中所有的客户,这些客户通过应用程序已经处理了定单。
保障LINQ数据库存取的安全 LINQ to SQL在专用于数据存取时,清除了SQL注入存在于你的应用程序中的可能性,原因很简单:LINQ代表你执行的每次查询都加上了具体的参数。在LINQ从你植入的查询语句中构建SQL查询时,无论源自何处,提交给查询的任何输入都被当作字面值。而且,通过IntelliSense和编译时的语法检查,LINQ与Visual Studio Orcas的集成可以帮助开发人员构建合法的查询。编译器可以捕捉大量的对查询的错误使用,这些错误使用可以将功能上的缺陷或其它类型的漏洞带入到你的应用程序中。与此不同的是,在你获知它正确与否之前,你编写的SQL语句只在运行时刻在数据库系统上解析。针对LINQ to SQL的唯一攻击途径是攻击者欺骗LINQ形成非法的或无意识的SQL。幸运的是,语言和编译器就是设计来保护这个方面的。 在清楚了上述的基本思想后,下面我们就展示应该如何运用LINQ to SQL防护SQL注入式攻击,并具体讨论一个客户搜索的例子。第一步是创建数据库中有关数据的对象模型。Visual Studio Orcas包含一个新的对象关系设计器(Object Relational Designer),这个设计器使你能够生成一个完全的对象模型。为了为我们的Northwind Customers表构建一个对象模型,你通过选择“增加新项目…”并选择“LINQ to SQL File”模板(这个模板是在对象关系设计器中打开的),在应用程序中创建一个LINQ to SQL的数据库。为了给 Customers表自动构建完全的对象模型,在服务器资源管理器 (Server Explorer)中选择这个表,并将它拖到对象关系设计器的设计层面上。在这个例子中,对象关系设计器增加了一个名为Customers.designer.cs的文件,这个文件以代码的形式定义了你将要使用的类,而不是编写代码直接与数据库进行交互。 在为Customers表中的数据定义了对象模型的类之后中,你可以为客户的数据搜索页面直接以代码的形式查询数据。LINQ-powered 页面(LINQtoSQL.aspx.cs)的Page_Load方法,具体展现了由对象关系设计器创建的CustomersDataContext类,重新使用了前面在SQLInjection.aspx页面中使用的连接字符串。下面的LINQ查询重新使用了与where子句匹配的Customer对象的集合。
在使用了LINQ to SQL之后,如果我们将“Ernst Handel”作为搜索值,由LINQ在运行时生成并在服务器上执行的SQL语句看起来将会是如下这个样子:
可以看出,WHERE子句自动被加上了参数,因此,用传统的SQL注入式攻击是无法造成破坏的。不管用户将什么值作为输入提交给搜索页面,这个查询是安全的,它不允许用户的输入执行服务器上的命令。如果你输入了前面例子中用来实施SQL注入攻击的字符串,查询并不会返回任何信息。事实上,一个用户用这个查询可以进行的最大的破坏是执行一次强力攻击(或称蛮力攻击(Brute force attack)),主要通过使用搜索功能穷举Customers表中所有公司的记录,其使用的方法是猜测每一个可能的值。不过,即使这样也只提供了那个页面上所暴露的Customers表中的值,并不会给攻击者注入命令的机会,这里的命令指的是访问数据库中额外的数据表的命令。 LINQ与安全 正如前面的例子所显示的那样,在Web应用程序中引入SQL注入漏洞是很容易的,不过采用适当的方法也容易修正这些漏洞。但是,没有什么方法天生就能防止开发人员犯这些简单的但却是危险的错误。然而,微软的LINQ to SQL技术通过让开发人员直接与对象模型交互而不是直接与数据库交互,消除了来自数据库应用程序的SQL注入攻击的可能性。内建于c#和Visual Basic的 LINQ基础结构关注正确地表述合法而安全的SQL语句,可以防止SQL注入攻击,并使开发人员专注于对他们来说最自然的程序设计语言。不管你是将LINQ to SQL用作新的.NET应用程序开发的一部分,还是对它进行花样翻新,用于现有的实际应用程序的数据访问,你都是作了一个构建更安全的应用程序的选择。 【责任编辑 彭凡】 |
||||||
打印本文 关闭窗口 |