基于时间的 SQL注入研究

SQL注入攻击是业界一种很是流行的攻击方式,是由rfp在1998年《Phrack》杂志第54期上的“NT Web Technology Vulnerabilities”文章中首次提出的。时过境迁,相关SQL注入的技术和工具都进行了不断的发展和演化。目前 SQL注入漏洞已是信息安全的一大领域,不管是小到我的网站,仍是大到电子商务网站,都或多或少的存在SQL注入漏洞。为何SQL注入漏洞会屡禁不止,缘由就在于要想防护SQL注入漏洞,须要对SQL语句、业务流程行为、各类主流数据库相关机制都有较为深刻的认识和理解,才能真正作好SQL注入的攻击和防范。数据库

SQL注入和盲注浏览器

对于SQL注入的定义和通常的判断方法,无非就是著名的三段式。普通SQL注入是经过构造SQL语句,将敏感信息直接暴露在网页上,有两种方式,一种是经过报错方式,一种是经过union select联合查询方式。普通的SQL注入并非完美的,一旦开发人员将错误页面进行处理,将unionselect关键字进行过滤,注入将再也不有效。其实这种修复方式存在较大的问题。若是是在不采起其余措施的状况下,仅仅更换成统一的错误页面是不能避免SQL注入的,这将会产生一种更高级的SQL注入方式盲注。盲注是经过构造SQL判断语句,经过返回页面的不一样将信息判断出来。返回页面有三种:有结果页面、0结果页面和错误过滤页面。只要有其中的两个页面,不管哪两个页面均可以,就能够判断存在注入漏洞。固然,这中间还有一个前提,就是这些不一样的页面是由输入到URL中的SQL语句执行的不一样形成的。可是普通的盲注也不是绝对有效的,一旦没有两个以上的差别页面,或者不能经过页面的不一样来来判断 URL中SQL语句的有效性,此时就要使用基于时间的SQL盲注。基于时间的SQL盲注的特色和使用假设有这么一个文件,不管怎么注入,页面内容都同样,但此文件确实存在注入点。最关键的是经过普通盲注不能获得差别页面,没有差别也就无法进行盲注。为何没有差别,有这么几种状况:安全

第一种状况:不管输入什么都只显示无信息页面,例如登录页面。这种状况下可能只有登陆失败页面,错误页面被屏蔽了,而且在没有密码的状况下,登陆成功的页面通常状况下也不知道。在这种状况下,有可能基于时间的SQL注入会有效。session

第二种状况:不管输入什么都只显示正常信息页面。例如,采集登陆用户信息的模块页面。采集用户的 IP、浏览器类型、refer字段、session字段,不管用户输入什么,都显示正常页面。函数

第三种状况:差别页面不是由输入URL中的SQL语句来决定的。这种状况下,也只能使用基于时间的盲注。工具

总之,状况有不少种,只要没法经过差别页面来进行通常SQL盲注,基于时间的SQL盲注就都有存在的可能。优化

Oracle数据库盲注网站

Oracle中基于时间的盲注主要是使用了DBMS_PIPE.RECEIVE_MESSAGE()函数和CASEWHEN„THEN„语句。下面是一个示例:中间件

 

5593=(CASE
WHEN
(ASCII(SUBSTRC((SELECT
NVL(CAST([ColumnName]
AS
VARCHAR(4000)),CHR(32))  FROM  (SELECT   [ColumnName],ROWNUM  AS  LIMIT  FROM  (SELECT
DISTINCT([ColumnName])  FROM   [TableName]))  WHERE  LIMIT=[StringIndex]),[CharIndex],1))   
[GuessChar])
THENDBMS_PIPE.RECEIVE_MESSAGE(CHR(90)||CHR(80)||CHR(71)||CHR(74),5)
ELSE 5593 END)

 

将[TableName]中的[ColumnName]字段下的全部数据选出,逐一选择每条数据,而且逐一选择每条数据中的每一个字符,判断该字符的 ASCII码值是否是大于[GuessChar],若是大于,将等待 5秒,若是不大于将返回 5593,当为 5593时,整个判断条件为真。上面的语句是用来获取指定表指定列中的数据。咱们还能够经过使用 user_tab_columns、all_tab_columns、md5

all_tables和user_tables等表或视图来获取想要的表名和列名。若是是过滤了“”、“”,可使用 like来进行等价变化.MSSQL数据库盲注

1)普通注入方法

MSSQL中基于时间的盲注主要使用了waitfor delay和if语句。下面是一个示例:

;if(ascii(substring((SELECT top 1 name FROM [DatabaseName]..sysobjects where xtype=Uand name not in(SELECTtop [StringIndex] name FROM [DatabaseName]..sysobjects wherextype=U)),[CharIndex],1))%3E[GuessChar]) waitfor delay 0:0:4--选出[DatabaseName]数据库 sysobjects表中 name字段下的全部数据,而且逐一选择条目,每一个条目中的字符逐一进行 ASCII码值的判断,若是大于[GuessChar]中指定的码值,将延迟 4秒钟响应。

2)高级注入方法

除了直接使用延迟函数的方法,MSSQL中还有另一种方法,简单说就是MSSQL数据库中where子句的执行顺序问题。由于MSSQL数据库使用了CBR技术进行优化,所以where后的子句不必定按照子句的书写顺序来执行,是按照各个子句的复杂度来进行,数据库将先执行复杂度较小的子句,若是各个子句使用and来进行链接,那么较小子句的返回结果为false,致使总体的返回结果为 false,其它高复杂度的语句的结果将可有可无,致使其它高复杂度的语句免于执行,又由于高复杂的子句消耗时间和系统资源较大,从而缩短系统执行时间。若是 where后面的各个子句不是并列关系,而是依赖关系或递进关系的话,则必须进行特殊处理,如 case when或子查询。

总之,复杂度较小的子句的返回结果的真假,将决定复杂度较大的子句是否执行,也就决定了整个 SQL语句执行下来的返回时间的长短。经过这样一个时间差,便可判断以前复杂度较小的子句是否执行成功。

3)使用示例

若是判断网站是否存在基于时间的盲注,那么可使用下面的语句:

http://xxx/index.asp?id=1 and (SELECTcount(*) FROM syscolumns AS sys1,syscolumns assys2,syscolumns AS sys3,syscolumns AS sys4,syscolumns AS sys5,syscolumns AS sys6)0 and 1=1

其中(SELECT count(*) FROM syscolumns AS sys1, syscolumns as sys2,syscolumns AS

sys3,syscolumns AS sys4,syscolumns AS sys5,syscolumns AS sys6)0是复杂度较大的子句,1=1

是复杂度较小的语句。1=1返回为真,那么前面复杂度较大的子句将免于执行。整个查询结果将当即返回。若是为 1=2,那数据库将执行复杂度较大的子句,整个查询结果将会有很大的延迟。例以下面的语句能够用来判断当前用户权限是否够用。

http://xxx/index.asp?id=1 and (SELECT count(*) FROM syscolumns AS sys1, syscolumns assys2,syscolumns AS sys3,syscolumns AS sys4,syscolumns AS sys5,syscolumns AS sys6)0 and1=(SELECT IS_MEMBER(sysadmin))

MySQL数据库盲注

MySQL数据库基于时间的盲注在使用延迟函数上能够有两个选择,一个是BENCHMARK(count,expr)函数,一个是 sleep(time)函数。前者经过将 expr语句执行 count次来达到延迟的目的,后者是直接延迟 time时间。例如 benchmark函数的使用,能够写成:

 

id=1  union  select 1,benchmark(1000000,md5(test)),1 from use where  userid=1 and
ord(substring(username,1,1))=97 /*

 

也能够写成:

 

id=1
union
select
if(substring(password,1,1)=A,benchmark(10000000,sha(1)),0)
username,password from cms_users where username = admin/*

 

使用 sleep函数的示例以下:

 

8468=IF((ORD(MID((SELECT%20IFNULL(CAST([ColumnName]%20AS%20CHAR),0x20)%20FRO
M%20[DatabaseName].[TableName]%20LIMIT%20[StringIndex],1),[CharIndex],1))%20%3E%20[G
uessChar]),SLEEP([DelayTime]),8468)

 

其中,为了对付部分 waf防火墙,能够去掉 if关键字,也能够去掉“”、“”等符号,使用 like或 in来进行代替。

防护方法

对付基于时间的 SQL盲注和对付其它类型盲注的方法是同样的,无非是作好三个方面的工做:输入数据的过滤、输出数据的处理、SQL语句访问权限的设置。

返回信息是否进行过滤:仅仅控制返回信息不能彻底避免注入漏洞的存在,仅仅是让利用难度大增,可能会相继存在明注、盲注、基于时间的盲注。即便将错误页面重定向,也不必定不能明注,好比说利用 union select走正规输入页面来输出。作好返回信息的过滤只是必要条件而不是充分条件。

链接权限是否为 sa:若是链接权限设置很是严密,那么利用系统表的注入就很难成功,只能经过暴力猜表名猜数据的方式,运气成分很大,可是若是有更新当前数据表的权限,就能够向普通业务表中插入或删除数据。输入数据是否进行过滤:输入数据过滤这部分提及来比较复杂,须要结合 waf、中间件、应用程序三者配合进行过滤,若是过滤严密,SQL注入将很是困难。但在某些特殊业务和某些特殊环境下,不可能将全部的关键字和符号都过滤掉,若是过滤掉,可能会致使业务不可用。

总结

不管对于普通SQL盲注,仍是基于时间的SQL盲注,最重要的特色是不一样点,只要有不一样就能注入。这就是所谓的行不行。数据库的链接用户最好是管理员帐号,不然就只能使用暴力破解。这就是所谓的难不难的问题。固然,这些都是在关键字和符号过滤不严的状况下进行的。上面提到的注入方法,也只能几个简单的例子。若是对数据库有足够的了解,能够任意发挥想象去构造 SQL语句来完成特定的功能。

相关文章
相关标签/搜索