SQL注入式攻击

SQL注入攻击的危害性很大。在讲解其防止办法以前,数据库管理员有必要先了解一下其攻击的原理。这有利于管理员采起有针对性的防治措施。web

 1、 SQL注入攻击的简单示例。sql

  statement := "SELECT * FROM Users WHERE Value= " + a_variable + "数据库

  上面这条语句是很普通的一条SQL语句,他主要实现的功能就是让用户输入一个员工编号而后查询处这个员工的信息。可是若这条语句被不法攻击者改装事后,就可能成为破坏数据的黑手。如攻击者在输入变量的时候,输入如下内容SA001’;drop table c_order--。那么以上这条SQL语句在执行的时候就变为了SELECT * FROM Users WHERE Value= ‘SA001’;drop table c_order--。编程

  这条语句是什么意思呢?‘SA001’后面的分号表示一个查询的结束和另外一条语句的开始。c_order后面的双连字符 指示当前行余下的部分只是一个注释,应该忽略。若是修改后的代码语法正确,则服务器将执行该代码。系统在处理这条语句时,将首先执行查询语句,查到用户编号为SA001 的用户信息。而后,数据将删除表C_ORDER(若是没有其余主键等相关约束,则删除操做就会成功)。只要注入的SQL代码语法正确,便没法采用编程方式来检测篡改。所以,必须验证全部用户输入,并仔细检查在您所用的服务器中执行构造 SQL命令的代码。安全

  2、 SQL注入攻击原理。服务器

  可见SQL注入攻击的危害性很大。在讲解其防止办法以前,数据库管理员有必要先了解一下其攻击的原理。这有利于管理员采起有针对性的防治措施。网络

  SQL注入是目前比较常见的针对数据库的一种攻击方式。在这种攻击方式中,攻击者会将一些恶意代码插入到字符串中。而后会经过各类手段将该字符串传递到SQLServer数据库的实例中进行分析和执行。只要这个恶意代码符合SQL语句的规则,则在代码编译与执行的时候,就不会被系统所发现。数据库设计

  SQL注入式攻击的主要形式有两种。一是直接将代码插入到与SQL命令串联在一块儿并使得其以执行的用户输入变量。上面笔者举的例子就是采用了这种方法。因为其直接与SQL语句捆绑,故也被称为直接注入式攻击法。二是一种间接的攻击方法,它将恶意代码注入要在表中存储或者做为原书据存储的字符串。在存储的字符串中会链接到一个动态的SQL命令中,以执行一些恶意的SQL代码。工具

  注入过程的工做方式是提早终止文本字符串,而后追加一个新的命令。如以直接注入式攻击为例。就是在用户输入变量的时候,先用一个分号结束当前的语句。而后再插入一个恶意SQL语句便可。因为插入的命令可能在执行前追加其余字符串,所以攻击者经常用注释标记“—”来终止注入的字符串。执行时,系统会认为此后语句位注释,故后续的文本将被忽略,不背编译与执行。测试

  3、 SQL注入式攻击的防治。

  既然SQL注入式攻击的危害这么大,那么该如何来防治呢?下面这些建议或许对数据库管理员防治SQL注入式攻击有必定的帮助。

  一、 普通用户与系统管理员用户的权限要有严格的区分。

  若是一个普通用户在使用查询语句中嵌入另外一个Drop Table语句,那么是否容许执行呢?因为Drop语句关系到数据库的基本对象,故要操做这个语句用户必须有相关的权限。在权限设计中,对于终端用户,即应用软件的使用者,没有必要给他们数据库对象的创建、删除等权限。那么即便在他们使用SQL语句中带有嵌入式的恶意代码,因为其用户权限的限制,这些代码也将没法被执行。故应用程序在设计的时候,最好把系统管理员的用户与普通用户区分开来。如此能够最大限度的减小注入式攻击对数据库带来的危害。

  二、 强迫使用参数化语句。

  若是在编写SQL语句的时候,用户输入的变量不是直接嵌入到SQL语句。而是经过参数来传递这个变量的话,那么就能够有效的防治SQL注入式攻击。也就是说,用户的输入绝对不可以直接被嵌入到SQL语句中。与此相反,用户的输入的内容必须进行过滤,或者使用参数化的语句来传递用户输入的变量。参数化的语句使用参数而不是将用户输入变量嵌入到SQL语句中。采用这种措施,能够杜绝大部分的SQL注入式攻击。不过惋惜的是,如今支持参数化语句的数据库引擎并很少。不过数据库工程师在开发产品的时候要尽可能采用参数化语句。

 三、 增强对用户输入的验证。

  整体来讲,防治SQL注入式攻击能够采用两种方法,一是增强对用户输入内容的检查与验证;二是强迫使用参数化语句来传递用户输入的内容。在SQLServer数据库中,有比较多的用户输入内容验证工具,能够帮助管理员来对付SQL注入式攻击。测试字符串变量的内容,只接受所需的值。拒绝包含二进制数据、转义序列和注释字符的输入内容。这有助于防止脚本注入,防止某些缓冲区溢出攻击。测试用户输入内容的大小和数据类型,强制执行适当的限制与转换。这即有助于防止有意形成的缓冲区溢出,对于防治注入式攻击有比较明显的效果。

  如可使用存储过程来验证用户的输入。利用存储过程能够实现对用户输入变量的过滤,如拒绝一些特殊的符号。如以上那个恶意代码中,只要存储过程把那个分号过滤掉,那么这个恶意代码也就没有用武之地了。在执行SQL语句以前,能够经过数据库的存储过程,来拒绝接纳一些特殊的符号。在不影响数据库应用的前提下,应该让数据库拒绝包含如下字符的输入。如分号分隔符,它是SQL注入式攻击的主要帮凶。如注释分隔符。注释只有在数据设计的时候用的到。通常用户的查询语句中没有必要注释的内容,故能够直接把他拒绝掉,一般状况下这么作不会发生意外损失。把以上这些特殊符号拒绝掉,那么即便在SQL语句中嵌入了恶意代码,他们也将毫无做为。

  故始终经过测试类型、长度、格式和范围来验证用户输入,过滤用户输入的内容。这是防止SQL注入式攻击的常见而且行之有效的措施。

  四、 多多使用SQL Server数据库自带的安全参数。

  为了减小注入式攻击对于SQL Server数据库的不良影响,在SQLServer数据库专门设计了相对安全的SQL参数。在数据库设计过程当中,工程师要尽可能采用这些参数来杜绝恶意的SQL注入式攻击。

  如在SQL Server数据库中提供了Parameters集合。这个集合提供了类型检查和长度验证的功能。若是管理员采用了Parameters这个集合的话,则用户输入的内容将被视为字符值而不是可执行代码。即便用户输入的内容中含有可执行代码,则数据库也会过滤掉。由于此时数据库只把它看成普通的字符来处理。使用Parameters集合的另一个优势是能够强制执行类型和长度检查,范围之外的值将触发异常。若是用户输入的值不符合指定的类型与长度约束,就会发生异常,并报告给管理员。如上面这个案例中,若是员工编号定义的数据类型为字符串型,长度为10个字符。而用户输入的内容虽然也是字符类型的数据,可是其长度达到了20个字符。则此时就会引起异常,由于用户输入的内容长度超过了数据库字段长度的限制。

  五、 多层环境如何防治SQL注入式攻击?

  在多层应用环境中,用户输入的全部数据都应该在验证以后才能被容许进入到可信区域。未经过验证过程的数据应被数据库拒绝,并向上一层返回一个错误信息。实现多层验证。对无目的的恶意用户采起的预防措施,对坚决的攻击者可能无效。更好的作法是在用户界面和全部跨信任边界的后续点上验证输入。如在客户端应用程序中验证数据能够防止简单的脚本注入。可是,若是下一层认为其输入已经过验证,则任何能够绕过客户端的恶意用户就能够不受限制地访问系统。故对于多层应用环境,在防止注入式攻击的时候,须要各层一块儿努力,在客户端与数据库端都要采用相应的措施来防治SQL语句的注入式攻击。

  六、 必要的状况下使用专业的漏洞扫描工具来寻找可能被攻击的点。

  使用专业的漏洞扫描工具,能够帮助管理员来寻找可能被SQL注入式攻击的点。不过漏洞扫描工具只能发现攻击点,而不可以主动起到防护SQL注入攻击的做用。固然这个工具也常常被攻击者拿来使用。如攻击者能够利用这个工具自动搜索攻击目标并实施攻击。为此在必要的状况下,企业应当投资于一些专业的漏洞扫描工具。一个完善的漏洞扫描程序不一样于网络扫描程序,它专门查找数据库中的SQL注入式漏洞。最新的漏洞扫描程序能够查找最新发现的漏洞。因此凭借专业的工具,能够帮助管理员发现SQL注入式漏洞,并提醒管理员采起积极的措施来预防SQL注入式攻击。若是攻击者可以发现的SQL注入式漏洞数据库管理员都发现了并采起了积极的措施堵住漏洞,那么攻击者也就无从下手了。

 

防止注入式攻击方法:

1.不要或尽可能少拼接sql,禁止用户输入敏感字符
2.注意对用户输入的数据进行检查 
3.sql参数使用参数化形式(parameter)

一、对string参数进行Replace("'","''") or Replace("'","")
示例sql语句:string sql = "select * from [users] where [name]='"+ name.Replace("'","") +"'";
注意sql语句中[name]=''两个单引号不可缺
二、对int参数进行int.Parse()
示例sql语句:string sql = "select * from [users] where [id]="+ int.Parse(id).ToString();

 

 1、什么是SQL注入式攻击?      所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令。在某些表单中,用户输入的内容直接用来构造(或者影响)动态SQL命令,或做为存储过程的输入参数,这类表单特别容易受到SQL注入式攻击。常见的SQL注入式攻击过程类如:      ⑴ 某个ASP.NET Web应用有一个登陆页面,这个登陆页面控制着用户是否有权访问应用,它要求用户输入一个名称和密码。      ⑵ 登陆页面中输入的内容将直接用来构造动态的SQL命令,或者直接用做存储过程的参数。下面是ASP.NET应用构造查询的一个例子:      System.Text.StringBuilder query = new System.Text.StringBuilder(   "SELECT * from Users WHERE login = '")   .Append(txtLogin.Text).Append("' AND password='")   .Append(txtPassword.Text).Append("'");      ⑶ 攻击者在用户名字和密码输入框中输入"'或'1'='1"之类的内容。      ⑷ 用户输入的内容提交给服务器以后,服务器运行上面的ASP.NET代码构造出查询用户的SQL命令,但因为攻击者输入的内容很是特殊,因此最后获得的SQL命令变成:SELECT * from Users WHERE login = '' or '1'='1' AND password = '' or '1'='1'。      ⑸ 服务器执行查询或存储过程,将用户输入的身份信息和服务器中保存的身份信息进行对比。      ⑹ 因为SQL命令实际上已被注入式攻击修改,已经不能真正验证用户身份,因此系统会错误地受权给攻击者。      若是攻击者知道应用会将表单中输入的内容直接用于验证身份的查询,他就会尝试输入某些特殊的SQL字符串篡改查询改变其原来的功能,欺骗系统授予访问权限。      系统环境不一样,攻击者可能形成的损害也不一样,这主要由应用访问数据库的安全权限决定。若是用户的账户具备管理员或其余比较高级的权限,攻击者就可能对数据库的表执行各类他想要作的操做,包括添加、删除或更新数据,甚至可能直接删除表。      2、如何防范?      好在要防止ASP.NET应用被SQL注入式攻击闯入并非一件特别困难的事情,只要在利用表单输入的内容构造SQL命令以前,把全部输入内容过滤一番就能够了。过滤输入内容能够按多种方式进行。      ⑴ 对于动态构造SQL查询的场合,可使用下面的技术:      第一:替换单引号,即把全部单独出现的单引号改为两个单引号,防止攻击者修改SQL命令的含义。再来看前面的例子,“SELECT * from Users WHERE login = ''' or ''1''=''1' AND password = ''' or ''1''=''1'”显然会获得与“SELECT * from Users WHERE login = '' or '1'='1' AND password = '' or '1'='1'”不一样的结果。      第二:删除用户输入内容中的全部连字符,防止攻击者构造出类如“SELECT * from Users WHERE login = 'mas' -- AND password =''”之类的查询,由于这类查询的后半部分已经被注释掉,再也不有效,攻击者只要知道一个合法的用户登陆名称,根本不须要知道用户的密码就能够顺利得到访问权限。      第三:对于用来执行查询的数据库账户,限制其权限。用不一样的用户账户执行查询、插入、更新、删除操做。因为隔离了不一样账户可执行的操做,于是也就防止了本来用于执行SELECT命令的地方却被用于执行INSERT、UPDATE或DELETE命令。      ⑵ 用存储过程来执行全部的查询。SQL参数的传递方式将防止攻击者利用单引号和连字符实施攻击。此外,它还使得数据库权限能够限制到只容许特定的存储过程执行,全部的用户输入必须听从被调用的存储过程的安全上下文,这样就很难再发生注入式攻击了。      ⑶ 限制表单或查询字符串输入的长度。若是用户的登陆名字最多只有10个字符,那么不要承认表单中输入的10个以上的字符,这将大大增长攻击者在SQL命令中插入有害代码的难度。      ⑷ 检查用户输入的合法性,确信输入的内容只包含合法的数据。数据检查应当在客户端和服务器端都执行——之因此要执行服务器端验证,是为了弥补客户端验证机制脆弱的安全性。      在客户端,攻击者彻底有可能得到网页的源代码,修改验证合法性的脚本(或者直接删除脚本),而后将非法内容经过修改后的表单提交给服务器。所以,要保证验证操做确实已经执行,惟一的办法就是在服务器端也执行验证。你可使用许多内建的验证对象,例如RegularExpressionValidator,它们可以自动生成验证用的客户端脚本,固然你也能够插入服务器端的方法调用。若是找不到现成的验证对象,你能够经过CustomValidator本身建立一个。      ⑸ 将用户登陆名称、密码等数据加密保存。加密用户输入的数据,而后再将它与数据库中保存的数据比较,这至关于对用户输入的数据进行了“消毒”处理,用户输入的数据再也不对数据库有任何特殊的意义,从而也就防止了攻击者注入SQL命令。System.Web.Security.FormsAuthentication类有一个HashPasswordForStoringInConfigFile,很是适合于对输入数据进行消毒处理。      ⑹ 检查提取数据的查询所返回的记录数量。若是程序只要求返回一个记录,但实际返回的记录却超过一行,那就看成出错处理。 

相关文章
相关标签/搜索