1 什么是SQL注入?
所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击。当应用程序使用输入内容来构造动态SQL语句以访问数据库时,会发生SQL注入攻击。如果代码使用存储过程,而这些存储过程作为包含未筛选的用户输入的字符串来传递,也会发生SQL注入。 黑客通过SQL注入攻击可以拿到网站数据库的访问权限,之后他们就可以拿到网站数据库中所有的数据,恶意的黑客可以通过SQL注入功能篡改数据库中的数据甚至会把数据库中的数据毁坏掉。
2 SQL注入的产生原因
SQL注入攻击是利用是指利用设计上的漏洞,在目标服务器上运行SQL语句以及进行其他方式的攻击,动态生成SQL语句时没有对用户输入的数据进行验证是SQL注入攻击得逞的主要原因。对于Java数据库连接JDBC而言,SQL注入攻击只对Statement有效,对PreparedStatement是无效的,这是因为PreparedStatement不允许在不同的插入时间改变查询的逻辑结构。
例如验证用户是否存在的SQL语句为:用户名'and pswd='密码
如果在用户名字段中输入:'or 1=1 或是在密码字段中输入:'or 1=1 将绕过验证,但这种手段只对只对Statement有效,对PreparedStatement无效。
相对Statement有以下优点:
- 防注入攻击
- 多次运行速度快
- 防止数据库缓冲区溢出
- 代码的可读性可维护性好
这四点使得PreparedStatement成为访问数据库的语句对象的首选,缺点是灵活性不够好,有些场合还是必须使用Statement。
3 SQL注入原理
SQL注射能使攻击者绕过认证机制,完全控制远程服务器上的数据库。 SQL是结构化查询语言的简称,它是访问数据库的事实标准。目前,大多数Web应用都使用SQL数据库来存放应用程序的数据,几乎所有的Web应用在后台都使用某种SQL数据库。跟大多数语言一样,SQL语法允许数据库命令和用户数据混杂在一起的。如果开发人员不细心的话,用户数据就有可能被解释成命令,这样的话,远程用户就不仅能向Web应用输入数据,而且还可以在数据库上执行任意命令了。
SQL注入式攻击的主要形式有两种。
- 一是直接将代码插入到与SQL命令串联在一起并使得其以执行的用户输入变量。上面笔者举的例子就是采用了这种方法。由于其直接与SQL语句捆绑,故也被称为直接注入式攻击法。
- 二是一种间接的攻击方法,它将恶意代码注入要在表中存储或者作为原书据存储的字符串。在存储的字符串中会连接到一个动态的SQL命令中,以执行一些恶意的SQL代码。注入过程的工作方式是提前终止文本字符串,然后追加一个新的命令。如以直接注入式攻击为例。就是在用户输入变量的时候,先用一个分号结束当前的语句。然后再插入一个恶意SQL语句即可。由于插入的命令可能在执行前追加其他字符串,因此攻击者常常用注释标记“-”来终止注入的字符串。执行时,系统会认为此后语句位注释,故后续的文本将被忽略,不背编译与执行。
4 如何防范SQL注入?
(1) 参数化SQL:在设计与数据库连接并访问数据时,在需要填入数值或者数据的地方,使用参数(Parameter)来给值,用@来表示参数。在使用参数化查询的情况下,数据库服务器不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,因此就算参数中含有恶意的指令,由于已经编译完成,就不会被数据库所运行,因此,可从一定程度上避免SQL注入。
(2)字符串过滤
(3)使用正则表达式过滤传入的参数
(4)前端js防范SQL注入
(5)在数据库中限制用户权限,drop/create/truncate等权限谨慎grant
(6)多使用数据库自带的安全参数。如在SQLServer数据库中提供了Parameter这个集合,这个集合提供类型检查和长度验证的功能。如果管理员采用了 Parameter这个集合的话,则用户输入的内容将被视为字符值而不是可执行代码。即使用户输入的内容中含有可执行代码,则数据库也会过滤掉。因为此时数据库只把它当作普通的字符来处理。
(7)多层环境如何防治SQL注入式攻击?(实现多层验证,需要多层一起努力,在客户端与数据库端都要采用相应的措施来防治SQL语句的注入式攻击)
(8)必要情况下使用专业的漏洞扫描工具来寻找可能被攻击的点