收藏 分享(赏)

SQL知识讲解.doc

上传人:hwpkd79526 文档编号:9295949 上传时间:2019-08-01 格式:DOC 页数:18 大小:51KB
下载 相关 举报
SQL知识讲解.doc_第1页
第1页 / 共18页
SQL知识讲解.doc_第2页
第2页 / 共18页
SQL知识讲解.doc_第3页
第3页 / 共18页
SQL知识讲解.doc_第4页
第4页 / 共18页
SQL知识讲解.doc_第5页
第5页 / 共18页
点击查看更多>>
资源描述

1、SQL 知识讲解1.1 概述1.2 背景1.3 字符编码2.1 综合测试2.2 测试过程2.3 分析结果3.1 绕过验证3.2 SELECT3.2.1 直接利用 号3.2.2 基于 UNION3.2.3 利用结构错误查询表单3.2.4 插入语句(圆扩号)3.2.5 利用 LIKE 语句查询3.2.6 “死胡同“3.2.7 列的数目不匹配问题3.2.8 附加的 WHERE 引号表和域的枚举3.2.10 单括号3.3 插入3.4SQL 服务器存储过程利用4.1 数据处理4.2 安全的 SQL 网页应用程序编写5.1MS SQL Server5.2MS Access Server5.3 Oracle

2、关于 SPI Dynamics,INc.一 概述和介绍1.网络应用和 SQL 注射1.1 概述有些网络数据库没有过滤客户提供的数据中可能有害的字符,SQL注射就是利用插入有害字符进行攻击的技术。尽管非常容易防范,但因特网上仍然有惊人数量的存储系统容易受到这种攻击。这篇文章的目的是指导专业安全组织了解这种技术,并告诉他们正确的,用来防范 SQL 注射的办法,以及处理各种常见的,由于非法输入引起的问题.1.2 背景在读这篇文章之前,你应该对数据库如何工作,以及 SQL 如何被用来访问数据库有一些基础的了解。我建议您阅读 eX 的文章“Introduction to Databases for We

3、bDevelopers”。(网址:http:/ 字符编码在大多数的网络浏览器中,标点符号和许多其它符号在用于一个网络请求前需要把 URL 编码,以便被适当地编译(interpret) 。在本文中的例子和截图中我使用了固定的 ASCII 字符以保证最大的可读性。然而,在实际应用中,你需要在 HTTP 请求中用%25 来代替百分号(%),用%2B 来代替加号(+)等等。 。 。2.易损性的测试(Testing for vulnerability)2.1 综合测试彻底地检测一个网络请求是否容易被 SQL 注射比一个可能的猜测(might guess)需要耗费更多的精力。当你把一个单引号放进一个脚本的

4、第一个参数值时,服务器返回一个空白的网页,上面除了ODBC 错误以外什么都没有.显然这种情况直接反映出 web 程序存在漏洞,但通常都不是这样的,如果你没有注意细节的话,很容易忽略掉一个看上去完美,其实很脆弱的脚本。服务器上每一个脚本中的每一个参数都应该被检测。开发者和开发组织之间可能很不一致。设计脚本 A 的程序员也许和脚本 B 的开发毫无关系,所以,其中一个也许对 SQL 注射免疫,而另外一个可能不会。事实上,设计脚本 A 里的函数 A 的程序员也许和脚本 A 里的函数 B 的开发毫无关系,所以脚本 A 里的一个参数也许对 SQL 注射是脆弱的,而另外一个参数却不一定,即使整个网络请求是由

5、一个程序员来构想,设计,编写及测试的,在成千上万的脚本中的参数中,由于某种原因,设计者忘了检验某个地方的数据,所以仍有可能存在一个脆弱的参数,而且那个地方是唯一的,你永远都不能确定是哪里,所以必须测试所有的东西。2.2 测试过程用一个单引号和一个 SQL 关键字(比如“WHERE” )替代每一个参数的值(argument) ,每个参数都应该被单独地测试,不止那样,当你测试一个参数的时候,应该保持其它的参数不变,并用有效的数据填充它们的值(argument) ,It can be tempting to just delete all of the stuff that youre not wo

6、rking with in order to make things look simpler, particularly with applications that have parameter lines that go into many thousands of characters.当你测试一个参数是否能被 SQL 注射的时候,如果忽略了其它参数或者给他们一个错误的值(argument) ,网络请求就有可能由于其它原因而出错,这阻碍了你判断 SQL 注射是否可行。比如,让我们假设以下是一个有效的,纯粹的(unaltered)参数行:ContactName=Maria%20Ander

7、s-“后面的任何东西,但是只有 MS 的SQL SERVER 会这样做.我们最好学习如何处理这个问题,这样我们在面对 Oracle,DB/2,MySQL 和他种类的数据库服务器的时候就知道怎么做了.SELECT 查询被用于从数据库中获取信息.大多数的 web 应用程序通过 SELECT 向数据库获取信息候再动态地在页面上显示出来.通常,数据库查询这部分你可以自己伪造,他将成为 WHERE 子句的一部分.我们可以通过插入 UNION SELECT 来绕过 web 程序允许我们查询的数据,从而得到其它的数据.联合查询(指 UNION SELECT)允许在一条语句中使用多个 SELECT 查询,看上

8、去就像这样:SELECT CompanyName FROM Shippers WHERE 1 = 1 UNION ALL SELECT CompanyName FROM Customers WHERE 1 = 1它返回的结果中包含了第一个查询和第二个查询的结果,“ALL SELECT“这里的 ALL 是必须的,这样可以逃过 SELECT DISTINCT 语句的限制并且不会妨碍别的(?),所以最好是使用它.你必须确认第一个查询,即 web 应用程序编写者希望执行的那个被执行,不返回任何记录.这并不难.举个例子,有这么一个表达式:SQLString = “SELECT FirstName, La

9、stName, Title FROM Employees WHERE City = “ 9,9,9通常这些字符串中的一些会返回相同的信息,或者根本不返回信息.但是有例子告诉我们,可能有的信息只有用他们中的一个才能得到,所以你最好提交字符串的时候,把他们都试一遍.(2 张图)3.2.4 圆扩弧如果有缺陷的查询语句中包含圆扩弧( (就像下面将会举的例子那样),或者返回的错误信息里显式地提醒你缺了(号(Oracle 这么做),那么你应该在你提交的 SQL 注射字符串中加入(号.通常在 WHERE子句后面加一个括号,但是在一些情况下,你需要加 2 个或者更多的括号.下面是 parenthesis.as

10、p 的源码:mySQL=“SELECT LastName, FirstName, Title, Notes, Extension FROM Employees WHERE (City = “ -”都没有用,所以自己要小心和避免在这种地方停留。3.2.7 列的数目不匹配问题如图所示,我们可以从几次错误中得到很多有用的信息,并且加以调整自己的请求语句,这种信息多了,那就意味着我们离成功不远了。在猜列名时,如图所示,我们提交语句后会碰到以下错误“在UNION 语句中的所有查询都必须在目标列表中具有相同数目的表达式” ,这就是说你需要找出或者说是探测出在合法的请求中有多少个列。这里我解释一下,UNIO

11、N 语句是用来将两个不同的查询结果集相加得到一个结果集,UNION 使用的唯一要求是两个查询的信息(你的查询语句)必须有相同的列数和相同的数据类型我举个例子,web 程序中有如下语句:SQLstring= “SELECT FirstName,LastName,EmployeeID FROM Employees WHERE City =“-”注释符号将其注释掉(如果我们是 SQL Server) 。或者干脆继续猜其他的列名,然后构造合法请求就如我们上一节讲到的一样。表名的枚举我们已经开始掌握如何来使用注入进行攻击,但是我们还要确定要从哪个表得到信息,换句话说就是我们要的到关键的表名才能获得我们想

12、要的有用信息。如何获得表名呢?在 SQL Server 中,你可以很容易得从数据库中得到全部的表名和列名。但是在 Oracle 和Access 中,你就不一定能如此轻易的得到了,这要看 WEB 程序对数据库的访问权限了。关键在于是否能得到系统建立时自动生成的表中包含的表名和列名。如在 SQL Server 中,它们分别为sysobjects和syscolumns,(在本文最后我们将给出其他数据库系统自建表和相应的列名)我们用以下的句子可以在这些表中列出数据库的所有列名和表名, (根据情况自行修改):SELECT name FROM sysobjects WHERE xtype = U这句话会返

13、回数据库中用户定义的所有表(如图所示) ,如果我们看到我们感兴趣的或者是想要看的表,那么我们就把他打开,这里以Orders 为例构造语句:SELECT name FROM syscolumns WHERE id = (SELECT id FROM sysobjects WHERE name = Orders)得到结果如图。3.2.10.单一纪录上面我们构造的语句返回了大量的信息,如果你只想显示一条数据纪录也是可以的。你完全可以构造你的注入语句来得到你想要的唯一的信息。我们只要在 WHERE 子句中添加关键字来避免某些行的关键字被选中就可以了。我来举个列子: UNION ALL SELECT n

14、ame, FieldTwo, FieldThree FROM TableOne WHERE =我们这样就可以得到 FieldOne,FieldTwo 和 FieldThree 的第一个值,假设我们的到的分别是“Alpha“, “Beta“和“Delta“。注意,更有意思的来了,我们要得到第 2 行的值,怎么构造下面的语句呢?这样来: UNION ALL SELECT FieldOne, FieldTwo, FieldThree FROM TableOne WHERE FieldOne NOT IN (Alpha) AND FieldTwo NOT IN (Beta) AND FieldThre

15、e NOT IN (Delta) AND =这里有一个子句“NOT IN VALUES” ,它的作用是不再返回我们已经得到的信息,即不是 alpha,不是 beta,不是 delta.既然都不是,数据库就会傻乎乎的告诉我们第二行的值。我们再假设我们得到第二行的值为“AlphaAlpha“, “BetaBeta“和“DeltaDelta“。我们来获得第三行的值,构造语句如下: UNION ALL SELECT FieldOne, FieldTwo, FieldThree FROM TableOne WHERE FieldOne NOT IN (Alpha, AlphaAlpha) AND Fie

16、ldTwo NOT IN (Beta, BetaBeta) AND FieldThree NOT IN (Delta, DeltaDelta) AND =这样就避免了得到第一次和第二次我们已经得到的值,我们就这样试下去会得到数据库中所有的值。这看起来好像确实比较麻烦,但在这里却是最有效的,不是么?3.3 插入3.3.1 插入基础关键字 INSERT 被用于向数据库添加信息,通常使用 INSERT 主要在包括用户注册,论坛,添加商品到购物车,等等。检查 INSERT 使用的弱点和检查 WHERE 一样。你可能不想使用 INSERT,如何避免被利用弱点是一个重要的考虑问题。INSERT 注入尝试常

17、常会让数据库以行形式返回结果导致泛滥的单独的引用和 SQL 关健字的意义可能改变.取决于管理员的注意和信息对数据库的操作,这个是要引起注意的,刚刚说过的那些,INSERT 注入和 SELECT 注入的不同。我们在一个允许用户进行各种注册,这就提供了一个你输入你的名字,地址,电话等等的表单。在你提交了这个表单之后,为了得到进一步的 INSERT 的弱点,你必须能够看到你提交的信息。它在那里不要紧。可能当你登陆根据在数据库里存储的名字的给予你权利的时候,可能在发送你的 spam 邮件的。 。 ,谁知道,寻找一个途径至少可以看到你输入的信息。3.3.2一个插入的请求看起来象这样:INSERT INT

18、O TableName VALUES (Vaule One,Value Two,Value Three) 你想可能利用一个在参数 VALUES 中的子句来看到其他的数据。我们可以使用这种办法,sql 的代码象这样:SQLString =“INSERT INTO TableName VALUES (“ EXEC master.dbo.xp_cmdshell cmd.exe dir c:注意,Notice how a valid argument is supplied at the beginning and followed by a quote and the final argument

19、to the stored procedure has no closing quote. This will satisfy the syntax requirements inherent in most quoted vulnerabilities. You may also have to deal with parentheses, additional WHERE statements, etc.但是在这以后将不需要担心列和数据的类型的匹配。这个可能弱点的输出象程序无法返回错误信息一样。我最喜欢存储过程。5. 3.4.2. xp_cmdshellxp_cmdshell comman

20、d_string , no_outputmaster.dbo.xp_cmdshell 是存储过程的圣杯,它带来了一个问题,能够调用命令行的数据库用户的和他的运行权限,这个并不可用除非这个网页程序使用的数据库用户是 SA. 运行级别为 6sp_makewebtask outputfile = outputfile, query = query 6. 另外一个好的调用对象是 master.dbo.sp_makewebtask,象你所看的,它是一个本地的输出文件和一个 SQL statement。sp_makewebtask 可以查询并建立一个包含输出的网页。注意你可以象使用一个 UNC 路径名一样

21、使用一个本地输出。这个意思就是这个输出文件可以放有在任何一台连在 Internet 并且有个可写的 SMB 共享(SMB 请求不需要任何的身份验证)。如果有一个防火墙限制了服务器对 Internet,试着把输出文件放在网页目录下(你要知道或者猜测网页的目录)。同样值得注意的是引用查询可能是 包括执行其他的存储过程。Making “EXEC xp_cmdshell dir c:“ 这个查询将在网页中给出“dir c:“的输出。当你进行嵌套引用的时候,记得单独的引用和双引号。4. 解决 4.1 数据处理所有的客户端数据可以被恶意的提交的字符或字符串清除。这些可能在所有的应用程序做到,不仅仅是使用

22、SQL 查询的。Stripping quotes or putting backslashes in front of them is nowhere near enough.最好的过滤数据的方式是不用规则的表达方式,使它只包括你所想要的字符类型。举个例子,下边的 regxp 将只能返回字母和数字,尽可能的过滤象 s/0-9a-zA-Z/g 这样的特殊字符。可能的时候尽量使用数字,在这以后只使用数字和字母。如果你需要包括各种各样的标志或标点。确信完全的把它们转换成 html 标记,像“e;“ or “” 。例如,一个用户提交了一个 email 地址只允许使用数字和字母还有“, “_“, “.“

23、 和“-“。仅仅只有这些字符可以转换成 html 标记。4.2. 编写安全的 web 程序这里同样有很少的特殊的 sql 注入规则。First, prepend and append a quote to all user input。尽管数据使数字。其次,限制网页应用程序的数据库用户在数据库里的权限。不要给这个用户访问所有的存储过程的权利如果这个用户只需要访问一些预定义的。这部分包括了所有在 sql 注入中有用的系统表,你可以在 google 上搜索到每一个的表的列的定义5.1. MS SQL ServerSysobjectssyscolumns5.2. MS Access Server MSysACEsMSysObjects MSysQueriesMSysRelationships5.3. Oracle SYS.USER_OBJECTSSYS.TAB SYS.USER_TABLESSYS.USER_VIEWS SYS.ALL_TABLES SYS.USER_TAB_COLUMNS SYS.USER_CONSTRAINTS SYS.USER_TRIGGERS SYS.USER_CATALOG

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报