SQL概述及在网络安全中的应用 |
1.网络 利用和SQL注射 1.1概述 有些网络数据库没有过滤客户提供的数据中可能有害的字符,SQL注射便是利用插入有害字符进行 突击的技术 。 只管十分方便 提防,但因特网上 依旧有惊人数量的存储系统方便受到这种 突击 。这篇文章的 目标是 指导专业安全组织了解这种技术,并告诉他们正确的,用来 提防SQL注射的 步骤,以及 解决各种常见的,由于非法输入引起的问题. 1.2背景 在读这篇文章之前,你应该对数据库如何工作,以及SQL如何被用来 拜访数据库有一些 根底的了解 。我 提议您阅读eXtropia.com的文章“Introduction to Databases for WebDevelopers” 。 1.3字符编码 在大多数的网络阅读器中,标点符号和许多其它符号在用于一个网络 申请前需求把URL编码,以便被适当地编译(interpret) 。在本文中的例子和截图中我 使用了固定的ASCII字符以 保障最大的可读性 。然而,在实际 利用中,你需求在HTTP 申请中用%25来 接替百分号(%),用%2B来 接替加号(+)等等 。 1.网络 利用和SQL注射 1.1概述 有些网络数据库没有过滤客户提供的数据中可能有害的字符,SQL注射便是利用插入有害字符进行 突击的技术 。 只管十分方便 提防,但因特网上 依旧有惊人数量的存储系统方便受到这种 突击 。这篇文章的 目标是 指导专业安全组织了解这种技术,并告诉他们正确的,用来 提防SQL注射的 步骤,以及 解决各种常见的,由于非法输入引起的问题. 1.2背景 在读这篇文章之前,你应该对数据库如何工作,以及SQL如何被用来 拜访数据库有一些 根底的了解 。我 提议您阅读eXtropia.com的文章“Introduction to Databases for WebDevelopers” 。 1.3字符编码 在大多数的网络阅读器中,标点符号和许多其它符号在用于一个网络 申请前需求把URL编码,以便被适当地编译(interpret) 。在本文中的例子和截图中我 使用了固定的ASCII字符以 保障最大的可读性 。然而,在实际 利用中,你需求在HTTP 申请中用%25来 接替百分号(%),用%2B来 接替加号(+)等等 。 。 。 1.网络 利用和SQL注射 1.1概述 有些网络数据库没有过滤客户提供的数据中可能有害的字符,SQL注射便是利用插入有害字符进行 突击的技术 。 只管十分方便 提防,但因特网上 依旧有惊人数量的存储系统方便受到这种 突击 。这篇文章的 目标是 指导专业安全组织了解这种技术,并告诉他们正确的,用来 提防SQL注射的 步骤,以及 解决各种常见的,由于非法输入引起的问题. 1.2背景 在读这篇文章之前,你应该对数据库如何工作,以及SQL如何被用来 拜访数据库有一些 根底的了解 。我 提议您阅读eXtropia.com的文章“Introduction to Databases for WebDevelopers” 。 1.3字符编码 在大多数的网络阅读器中,标点符号和许多其它符号在用于一个网络 申请前需求把URL编码,以便被适当地编译(interpret) 。在本文中的例子和截图中我 使用了固定的ASCII字符以 保障最大的可读性 。然而,在实际 利用中,你需求在HTTP 申请中用%25来 接替百分号(%),用%2B来 接替加号(+)等等 。 。 。 3.2.5 LIKE语句 查问 另一个大的 苦难是陷入一个LIKE子句的陷阱.(Seeing the LIKE keyword or percent signs cited in an error message are indications of this situation.)大多数的web查找程序 使用LIKE子句来 查问数据库, 比方下面这个: SQLString = "SELECT FirstName, LastName, Title FROM Employees WHERE LastName LIKE '%" & strLastNameSearch & "%'" 这里面的%是通配符,在这个例子里,WHERE子句会返回TRUE, 惟独LASTNAME里有字符串含有strLastNameSearch.为了阻挠SQL SERVER返回估计中的记录,你 构造的SQL语句里必须含有LASTNAME里没有的字符串.web查找程序查找的字符串来自于消费者的输入.通常有一个'和一个%在输入的字符串之前, 因此我们 构造字符串时,需求在WHERE子句中匹配它们.假如你提交了NULL作为查找字符串,那么LIKE的参数会变成"%%",这是一个全匹配,会返回所有的记录. 3.2.6 “死胡同” 大 部分的时候sql injection都要 伴随着大量失败的 实际,假如你发现你无论如何都不能插入 有关的语句,而且无论你怎么做都不对,这个时候你就要推断自己是不是掉进了一个死胡同,众多时候遇到这种状况你很可能是在一个多重嵌套的WHERE和SELECT子句的语句中,或者一些更加复杂的多重嵌套,连 使用“;--”都没有用,所以自己要小心和幸免在这种地方停留 。 3.2.7 列的数目不匹配问题 如图所示,我们 可以从几次 舛误中得到众多有用的信息,而且加以调整自己的 申请语句,这种信息多了,那就 象征着我们离 顺利不远了 。在猜列名时,如图所示,我们提交语句后会碰到以下 舛误“在UNION语句中的所有 查问都必须在 指标列表中 存在 雷同数 目标 抒发式”,这便是说你需求找出或者说是探测出在合法的 申请中有多少个列 。 这里我解释一下,UNION 语句是用来将两个不同的 查问 后果集相加得到一个 后果集,UNION 使用的唯一要求是两个 查问的信息(你的 查问语句)必须有 雷同的列数和 雷同的数据类型 我举个例子,web程序中有如下语句: SQLstring= "SELECT FirstName,LastName,EmployeeID FROM Employees WHERE City ='"&strCity"'" 合法的SELECT语句和我们注入的UNION SELECT语句在WHERE子句中都要有
雷同的列 。就上面的语句来说,假如我要加入UNION 语句的话,前后两者都要有3个列 。而且他们列的数据类型也要
彼此匹配才
可以 。假如FirstName这个值是字符串类型的,那么在你注入的语句中所对应的值也应该是字符串类型的 。一些数据库,如ORACLE,是对类型
审查十分严格的 。
其余的数据库
绝对要好一些,同意你输入任何数据类型而且它会自动的把你输入
舛误的数据类型转换成正确的 。
比方SQL数据库中,你在varchar类型的地方输入数值类型的数据(如int)是不会报错的,由于在这里数值类型会被自动转为字符串类型 。然而假如在smallint列处输入text类型则被认为是非法的,由于text类型不能被转换成int类型 。把数值类型的数据转换成字符串型是被同意的,而反之则不行,所以默许都是
使用数值类型的数据 。 假如 所有顺利,那么 恭喜你,你会得到一个和上面 格局 类似的而且是合法的页面;)无论动态页面在哪里浮现,你都 可以 构造自己的语句 应答 自如 。 3.2.8.WHERE 要害字 报错为“无效的列名'EmployeeID'”,这个问题可能是由我们注入的语句结尾的WHERE 要害字引起的,举例 注明: SQLString="SELECT FirstName,LastName,Title FROM Employees WHERE City='"&strcity&"'AND Country ='USA'" 假如我们注入的语句是UNION ALL SELECT OtherField FROM OtherTable WHERE 1=1 那么会得到如下的提交语句: SELECT FirstName, LastName, Title FROM Employees WHERE City = 'NoSuchCity' UNION ALL SELECT OtherField FROM OtherTable WHERE 1=1 AND Country = 'USA' 这样就会报错:[Microsoft][ODBC SQL Server Driver][SQL Server]无效的列名 'Country' 。 其实问题便是由于你注入的语句后,系统没有在从数据库的表中找到一个叫'Country'的列名 。我们这里 可以 方便的用“;--” 诠释符号将其 诠释掉(假如我们是SQL Server) 。或者 索性 接续猜 其余的列名, 而后 构造合法 申请就如我们上一节讲到的一样 。 表名的枚举 我们已经开始 主宰如何来 使用注入进行 突击,然而我们还要确定要从哪个表得到信息,换句话说便是我们要的到 要害的表名 威力 获得我们想要的有用信息 。如何 获得表名呢?在SQL Server中,你 可以很方便得从数据库中得到所有的表名和列名 。然而在Oracle和Access中,你就不 定然能如此轻易的得到了,这要看WEB程序对数据库的 拜访权限了 。 要害在于是不是能得到系统 构建时自动生成的表中包括的表名和列名 。如在SQL Server中,它们分别为'sysobjects'和'syscolumns',(在本文最终我们将给出 其余数据库系统自建表和相应的列名)我们用以下的句子 可以在这些表中列出数据库的所有列名和表名,(依据状况自行 批改): SELECT name FROM sysobjects WHERE xtype = 'U' 这句话会返回数据库中消费者定义的所有表,假如我们看到我们有兴趣的或者是想要看的表,那么我们就把他 打开,这里以Orders为例 构造语句:SELECT name FROM syscolumns WHERE id = (SELECT id FROM sysobjects WHERE name = 'Orders')得到 后果如图 。 3.2.10.单一纪录 上面我们 构造的语句返回了大量的信息,假如你只想显示一条数据纪录也是 可以的 。你 彻底 可以 构造你的注入语句来得到你想要的唯一的信息 。我们 惟独在WHERE子句中增加 要害字来幸免某些行的 要害字被选中就 可以了 。我来举个列子:' UNION ALL SELECT name, 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 FieldThree 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 FieldTwo NOT IN ('Beta', 'BetaBeta') AND FieldThree NOT IN ('Delta', 'DeltaDelta') AND ''=' 这样就幸免了得到第一次和第二次我们已经得到的值,我们就这样试下去会得到数据库中所有的值 。这看起来 如同 确切 比较麻烦,但在这里却是最有效的,不是么? 3.3 插入 3.3.1 插入 根底 要害字INSERT 被用于向数据库增加信息,通常 使用INSERT主要在包括消费者注册,论坛,增加商品到购物车,等等 。 审查INSERT 使用的弱点和 审查WHERE一样 。你可能不想 使用INSERT,如何幸免被利用弱点是一个主要的考量问题 。INSERT注入尝试 一般会让数据库以行 模式返回 后果招致泛滥的 径自的 引用和SQL关健字的 意思可能转变.取决于治理员的 留神和信息对数据库的操作,这个是要引起 留神的,方才说过的那些,INSERT注入和SELECT注入的不同 。我们在一个同意消费者进行各种注册,这就提供了一个你输入你的名字,地址,电话等等的表单 。在你提交了这个表单之后,为了得到进一步的INSERT的弱点,你必须 可以看到你提交的信息 。它在那里不要紧 。可能当你登陆依据在数据库里存储的名字的赋予你 权力的时候,可能在发送你的spam邮件的 。 。,谁晓得,寻觅一个 路径至少 可以看到你输入的信息 。 3.3.2 一个插入的 申请看起来象这样:INSERT INTO TableName VALUES ('Vaule One','Value Two','Value Three') 你想可能利用一个在参数VALUES中的子句来看到 其余的数据 。我们 可以 使用这种 步骤,sql的代码象这样:SQLString ="INSERT INTO TableName VALUES ('" & strValueOne & "', '" & strValueTwo & "', '" & strValueThree & "')"我们象这样填写表单:Name: ' + (SELECT TOP 1 FieldName FROM TableName) + ' Email: blah@blah.com Phone: 333-333-3333 使SQL的申明象这样 : INSERT INTO TableName VALUES ('' + (SELECT TOP 1 FieldName FROM TableName) + '', 'blah@blah.com', '333-333-3333')当你到了个人设置页面查看你的 使用信息,你将看到的第一个字段这个通常是消费者名r假如你使不在你的subselect中 使用TOP 1,你将得到一个 舛误信息说你的subselect返回了太多记录,你能查看表中所有的行, 使用NOT IN()同样的 步骤你 可以得到 径自的记录 。 3.4. SQL服务器存储过程利用 3.4.1 存储过程 根底 4. 一个 完全安装的MSSQL服务器有上千的存储过程 。假如你能在一个 后盾 使用mssql的网页 利用程序得到SQL注入,你能 使用这些存储过程 实现一些非凡的 成就 。我将 探讨很少的特别的过程 。取决于网页程序 使用数据库的消费者,惟独一些 可以工作,并不是所有的消费者都 可以利用 。第一件事你应该晓得存储过程注入不能通过存储过程的返回值来确定你的注入是不是 顺利.取决于你想 实现什么,你可能不需求得到数据 。你 可以找到返回给你的数据的 其余 意思 。存储过程注入比一般的 查问注入要方便些,存储过程的注入的弱点利用看起来象这样 。 simplequoted.asp?city=seattle';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 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_cmdshell xp_cmdshell {'command_string'} [, no_output] master.dbo.xp_cmdshell是存储过程的圣杯,它带来了一个问题, 可以调用命令行的数据库消费者的和他的运行权限,这个并不可用除非这个网页程序 使用的数据库消费者是SA. 运行级别为6 sp_makeweBTask [@outputfile =] 'outputfile', [@query =] 'query' 6. 另外一个好的调用对象是master.dbo.sp_makewebtask,象你所看的,它是一个当地的输出文件和一个SQL statement 。sp_makeweBTask 可以 查问并 构建一个包括输出的网页 。 留神你 可以象 使用一个UNC路径名一样 使用一个当地输出 。这个意思便是这个输出文件 可以放有在任何一台连在Internet而且有个可写的SMB共享(SMB 申请不需求任何的身份验证) 。假如有一个防火墙 制约了服务器对Internet,试着把输出文件放在网页目录下(你要晓得或者推测网页的目录) 。同样值得 留神的是 引用 查问可能是 包括执行 其余的存储过程 。Making "EXEC xp_cmdshell 'dir c:'" 这个 查问将在网页中给出"dir c:"的输出 。当你进行嵌套 引用的时候,记得 径自的 引用和双引号. 4.1数据 解决 所有的客户端数据 可以被 歹意的提交的字符或字符串 革除 。这些可能在所有的 利用程序做到,不只仅是 使用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地址只同意 使用数字和字母还有"@", "_", "." 和"-" 。仅仅惟独这些字符 可以转换成html标记 。 4.2. 编写安全的web程序 这里同样有很少的特别的sql注入 规定 。First, prepend and append a quote to all user input 。 只管数据使数字 。其次, 制约网页 利用程序的数据库消费者在数据库里的权限 。不要给这个消费者 拜访所有的存储过程的 权力假如这个消费者 惟独求 拜访一些 预约义的 。 这 部分包括了所有在sql注入中有用的系统表,你 可以在Google上查找到每一个的表的列的定义 5.1. MS SQL Server Sysobjects syscolumns 5.2. MS Access Server MSysACEs MSysObjects MSysQueries MSysRelationships 5.3. Oracle SYS.USER_OBJECTS SYS.TAB SYS.USER_TABLES SYS.USER_VIEWS SYS.ALL_TABLE S SYS.USER_TAB_COLUMNS SYS.USER_CONSTRAINTS SYS.USER_TRIGGERS SYS.USER_CATALOG |