现在很多人在入侵的过程中基本都是通过SQL注入来完成的,但是有多少人知道为什么会有这样的注入漏洞呢?有的会随口说着对于字符的过滤不严造成的。但是事实是这样吗?我们学这些,不仅要知其然,更要知其所以然!理论联系实际,才能对我们技术的提高有所帮助。
步骤/方法
1、SQL注入,由于程序在实际使用中,为了管理庞大的数据信息,就会使用到数据库。数据库可以方便程序对所有数据信息进行统一的存储和分类组织,便于查询更新。用户在使用程序时,程序可以自动通过对数据库的查询,将所获得的信息按照一定格式反馈给用户,同时用户也是通过交互式的对话框提交给程序数据,从而使程序按照用户想要的信息进行查询,反馈给用户想要的信息。对于程序这种数据库操作,先来看一段代码:
strKeyword = Request ["keyword"];
sqlQuery = "SELECT * FROM Aritcles WHERE Keywords LIKE '%" +strKeyword + "%'";
这段代码的主要目的是按照用户提交的关键字Keyword,对软件连接数据库中的文件进行搜索,找出所有包含用户关键字的文章来。假设此时,我们提交给软件“hack”这个数据,这时,“hack”这个关键字就会被传递给Keyword关键变量。接下来看看代码的执行情况,keyword获得数据“hack”后,被赋值给strKeyword变量,然后strKeyword变量被放入查询语句,此时的查询语句表现为:"SELECT * FROM Aritcles WHERE Keywords LIKE '%hack%'",这个查询语句的意思就是从数据库Aritcles表中查询出所有包含“hack”这个关键字的文章。注意“hack”这个单词是我们提交给程序的,因此可以对其随意修改的。于是,可以这样修改,把它变为“hack'; DROP TABLE Aritcles; --”。
现在看看程序会怎样处理这个外部关键字数据。首先,查询语句变成了:“SELECT * FROM Aritcles WHERE Keywords LIKE '%hack%'; DROP TABLE Aritcles; --”,我们知道DROP TABLE语句是在数据库操作中删除一个指定的表的意思,现在那个查询语句的意思就变了,以中间的分号为标志,分成两个部分,首先还是正常的查出所有包含hack关键字的文章。但是接下来……
由于程序使用的数据库是微软的SQL SERVER,该数据库支持多命令语句执行,这些数据库操作的命令语句都是由分号分隔开,然后依次执行的。这里的“DROP TABLE Aritcles; --”是一个完全合法的命令语句,“--”符号是SQL SERVER数据库特有注释标识,数据库不执行任何命令。这样,当这段查询语句执行时,就会去执行一个删除Aritcles表的数据库命令。
像这样,通过控制传递给程序数据库操作语句的关键变量来获得恶意控制程序数据库,从而获取有用信息或者制造恶意破坏的,甚至是控制用户计算机系统的漏洞,就称之为“SQL注入漏洞”。
SQL注入漏洞完全是利用了将包含了某种目的的SQL语句,通过关键变量插入到程序中正常的数据库操作语句里。程序一旦发生注入漏洞,就会引发一系列安全隐患。
SQL注入漏洞是不分语言的,无论用什么语言开发的程序,只要涉及对数据库的操作,都可能存在SQL注入漏洞。虽然有时会因为编写语言的要求,或者程序设置环境的不同,导致SQL注入漏洞很难被常用的方法利用,但是总可以找到突破的方法。
2、下面以网站程序为例,看一看SQL注入漏洞最经常被利用的地方,也是危害最大的地方。
都知道对于一个网站来说,可以说数据库存放着网站所有的信息,WEB应用程序完全是凭借数据库中的信息进行正常的运行的。一个网站程序中,最关键的一个部分就是对用户的合法性的判断,也就是看访问它的用户是不是一个注册的用户。这个时候,就会要求输入用户名和密码,然后根据输入的信息查询数据库,判断是否存在用户,并检查密码是不是一致,如果一致则承认合法用户,否则将给予非法提示。下面看一段常常出现在论坛程序中的用户认证程序代码:
(1)admin1 = trim(request("name"))
(2)password1 = trim(request("password"))
(3)Set rs = Server.CreateObject ("ADODB.Recordset")
(4)sql = "select * from userlogin where name='"&admin1&"' and password='"&password1&"'"
(5)rs.Open sql,conn,1,1
(6)if rs.eof and rs.bof then
(7)response.write"<SCRIPT language=JavaScript>alert('用户名或密码不正确!')"
(8)response.write"javascript:history.go(-1)</SCRIPT>"
(9)response.end
(10)else
(11)session("name")=rs("name")
(12)session("password")=rs("password")
(13)response.Redirect("default.asp")
(14)end if
这段程序的第1和第2行分别通过Request对象获得用户名和密码,第3行是建立一个数据库操作集对象,第4行就是将用户名以及密码同时作为查询条件放入到userlogin表中进行查询,第5到第14行就是根据查询结果进行判断,弹出警告窗口,或者重定向网页。
假设数据库中有个用户guest,密码123456,那么该用户登录时,认证代码中的第4行则变为:sql = "select * from userlogin where name='guest' and password='123456'",这是一个合法查询语句,所以用户能正常登录,反之则登录不了。
看起来这是一个比较严格的认证代码,但是事实呢?
现在,我们用户名提交“'or 1='1”,密码也是一样,同样也会成为合法用户,这是为什么?
当我们提交表单后,代码通过Request对象获得提交的用户名'or 1='1以及密码'or 1='1后,直接将这些数据放入了第4行的查询语句中,于是变成了这样:sql = "select * from userlogin where name=''or 1='1' and password=''or 1='1'"。我们先看1='1',这个绝对永远为真,如果你说假,那么你回小学学数学吧,学好再来看吧,呵呵~注意在大马前面还有一个or,这代表者1='1'是作为一个条件选择语句放入数据库查询的,这样无论查询语句中的用户名和密码是否正确,都会因为or后面的1='1'代码,导致查询语句返回值永远为真,这样就是绕过了看似严格的用户认证,获得了合法的权限。