SQL注入:SQL Injection在这种攻击方式中,恶意代码被插入到查询字符串中,然后将该字符串传递到数据库服务器进行执行,根据数据库返回的结果,获得某些数据并进一步攻击,甚至获取管理员账号,密码,窃取或者篡改系统数据。
eg:
首先,数据库中有一个表格:
有一个登陆页面,输入用户的账号、密码,查询数据库,进行登陆,为了将问题简化,我们仅仅将其SQL打印出来供大家分析。
详见代码login.jsp
在文本框中输入查询信息,提交,能够到打loginResult.jsp显示登陆结果。
运行login.jsp,输入正常数据(如guokehua,guokehua):
提交,显示的结果是:
熟悉SQL的读者可以看到,该结果没有任何问题,数据库将对该输入进行验证,看能否返回结果,如果有,表示登录成功,否则表示登录失败。
但是该程序有漏洞。比如,客户输入账号为:"aa 'OR 1=1= --",密码随便输入,如”aa":
查询显示的结果为:
该程序中,SQL语句为:
其中 --表示注释,因此真正运行的SQL语句是:
此处, “1=1” 永真,所以该语句将返回USERS表中的所以记录。网站受到了SQL注入的攻击。
2、另一种方式是使用通配符进行注入,比如,有一个页面,可以对学生的姓名(STUNAME)从STUDENTS表中进行模糊查询:同样,为了将问题简化,我们仅仅将其SQL打印出来供大家分析。
代码详见query.jsp。
运行,效果如下:
在文本框内输入查询信息,提交,能够到达queryResult.jsp显示登陆结果。运行query.jsp,输入正常数据(如guokehua),提交,效果为:
同 样,该结果没有任何 问题,数据库将进行模糊查询并且返回结果。如果什么都不输入,提交,效果为:
说明该程序允许无条件的模糊查询。
但是该程序也有漏洞。比如,客户输入:“% ‘--”:
查询显示的结果为:
该程序中, --表示注释,因此,真正运行的SQL语句是:
该语句中,也会将STUDENTS中所有的内容显示出来。相当于程序又允许了无条件的模糊查询。
更有甚者,可以在文本框内输入:“%’;DELETE FROM STUDENTS --":
查询显示的结果为:
这样,就可以删除表STUDENTS中所有的内容。
3、还有一种方法是直接通过DELETE语句进行注入,如有下面语句:
其中,bookName为输入的变量。
如果bookName以正常数据输入,如输入Java,语句为:
正常,但是如果给bookName的值为:Java ‘OR 1=1 --,语句变为:
实际执行的语句为:
可以将表中所有内容删除。
不仅仅SELECT语句会被注入,UPDATE语句也会被注入,如有下面表格:
有一条语句为:
其中,cname和account为输入的变量。
如果cname输入和account以正常数据输入,如输入”guokehua","0001",语句为:
正常,但是如果给cname的值为:“guokehua ',PASSWORD=' 111 '--", account随便输入,如”111“,语句变为:
就将所有记录的CNAME改为guokehua,密码改为111。
同样是上面那张表,如有INSERT语句:
如果account、password和cname以正常数据输入,如输入”0001“, ”akdj", "guokehua",语句为:
正常,但是如果给cname的值为: ”guokehua ',1000) --",其他值和前面一样,语句变为:
很明显,注册一个账号,默认的MONEY字段变成了1000.SQL注入危害:由于SQL注入攻击一般利用的是利用的是SQL语,这使得于所有基于SQL语言标准的数据库软件,SQLServer,Oracle,MySQL, DB2等都有可能受到攻击,并且攻击的发生和Web编程语言本身也无关,如ASP、JSP、PHP,在理论上都无法完全幸免。SQL注入攻击的危险是比较大的。很多其他的攻击,如DoS等,可能通过防火墙等手段进行阻拦,但是而对于SQL注入攻击,由于注入访问是通过正常用户端进行的,所以普通防火墙对此不会发出警示,一般只能通过程序来控制,而SQL攻击一般可以直接访问数据库进而甚至能够获得数据库所在的服务器的访问权,因此,危害相当严重。
二、防范方法:
1:将输入中的单引号变成双引号。这种方法经常用于解决数据库输入问题,同时也是一种对于数据库安全问题的补救措施。
列如代码:
当用户输入“Guokehua 'OR 1=1 --'时,首先利用程序将里面的’ (单引号)换成”(双引号),于是,输入就变成了:“Guokehua" OR 1=1 --", SQL代码变成了:
很显然,该代码不符合SQL语法。
如果是正常输入呢?正常情况下,用户输入”Guohua",程序将其中的‘换成“,当然,这里面没有单引号,结果仍是Guokehua,SQL为:
这是一句正常的SQL,不过,有时候,攻击者可以将单引号隐藏掉。比如,用”char(0x27)"表示单引号。所以,该方法并不是解决所以问题的方法。
2:使用存储过程。
比如上面的列子,可以将查询功能写在存储过程prcGetCustomer内,调用存储过程的方法为:
当攻击者输入“Guokehua 'or 1=1 --"时SQL命令为:
显然无法通过存储过程的编译。
注意,千万不要将存储过程定义为用户输入的SQL语句。如:
从安全角度讲,这是一个最危险的错误。