关于 Blind SQL Injection 的利用方法总结,关于 Blind SQL Injection (SQL盲注) 的利用方法总结。

文/LengF

Date/2011-10-28

首发:www.bhst.org

说明:支持一下t00ls的论坛,同时也欢迎大家到BHSTl来讨论交流。

0x00 概 述

    从2006年开始,SQL注入已经成为Web安全的重点了,随着管理员的安全意识加强,注入已经不再是那么简单了。从注入过滤和绕过注入等等,安全爱好者和管理员一直持续着猫和老鼠的游戏。本文描述在Blind SQL Injection中的利用技巧,并非绕过过滤的总结。

0x01 何为盲注

    盲注和普通的SQL注入原理是一样的(老生常谈的话题),不同在哪里?普通注入是会显示一些错误信息在页面上给攻击者判断,也就是说它会有多种情况,从而方便攻击者。而盲注则是只有两种情况,即TRUE和FALSE,这样说并不是很准确,因为SQL查询无非就这两种情况,应该说是盲注的时候你只能得到一个正常的页面或者是什么页面的不存在,甚至你在查询表的记录过程也不会有显示。还是不大理解,那么就继续往下看,我会试图尽力让大家明白这个问题。另外一点,盲注用工具很难进行注入(其实,有国外牛人写的一些程序,我测试了一下,效果不大理想),所以这里要重视手工注入技巧。

0x02 检测盲注点

    和普通的SQL注入类似,老样子两条语句判断。

And 0=0 和 And 0=1

    根据返回结果判断是否存在注入点,盲注存在,则第一条语句是正常的原始页面,第二条语句则会出错但是没有任何的错误信息和提示信息。
假设,我们有这样一个注入点:http://127.0.0.1/gbook/gshow.php?bid=1。

0x03 盲注利用方法

    本文的重点在于如何解决盲注的难点继续进行注入,总结了前辈的三种方法:通用方法、时间延迟、正则表达式等,主要测试平台是Mysql和Mssql。

    1.通用的方法

        通用的方法,严格上来说不算是盲注的一种,因为他还是有SQL查询返回结果,就是True 或者False,我不说这种方法,相信有SQL注入基础的朋友都会。

    2.时间延迟

        什么时候需要用到时间延迟攻击呢?当你输入SQL语句后没有看到任何的返回结果的时候。不同的数据库系统使用不同的函数或者方法。

    <1> MySQL

    在PHP+Mysql中,有安全意识的网站管理员会经常将display_errors设置成Off,如果存在注入,我们就可以利用Mysql数据库BENCHMARK函数进行盲注。我们从MySQL5.1参考手册看下函数说明:

BENCHMARK(count,expr)

    BENCHMARK() 函数重复count 次执行表达式 expr 。 它可以被用于计算  MySQL 处理表达式的速度。结果值通常为 0。另一种用处来自 mysql客户端内部,能够报告问询执行的次数。此处报告的时间是客户端上的共用时间,而不是服务器端上的CPU时间。

    我们测试程序有gbook.admin表的权限,其他类似,我们把php的display_errors设置成Off,程序明显存在注入漏洞,但是当我们提交单引号或者and 1=2都返回了和原来一样的错误了。那我们怎么进行注入呢?当然了,有些人说这种比较难判断,为什么呢?因为这个也跟网速有关系,所以可以选择两个时间相差较大的值来测试就很明显了。

具体利用方法是:

    # 执行经过了10S后才反应过来,说明第一位是a,否则继续

http://127.0.0.1/gbook/gshow.php?bid=1 union select if(substring(pwd,1,1)=char(97),benchmark(10000,md5(1)),0),2,3,4,5 from admin where uid=1

    # 原理同上面一句一样

http://127.0.0.1/gbook/gshow.php?bid=1 union select if(substring(pwd,1,1)=char(98),benchmark(10000,md5(1)),0),2,3,4,5 from admin where uid=1

    由于开启了GPC,所以我们将字符a用ASCII了。另外一点说明,在使用函数的benchmark时,第一参数不宜过大,过大容易导致卡机。SQL语句中那个if语句意思是,当查询字段pwd的第一个字符是a就调用延迟函数来计算数字1的md5,否则就为0.说到这里大家应该明白如何下面的盲注了吧。另外说下,如果这个延迟值够大相当于对目标数据库服务造成DDOS攻击。顺便附上MYSQL测试图:

关于 Blind SQL Injection (SQL盲注) 的利用方法总结

    <2> MSSQL

    Mysql知道怎么利用时间延迟进行盲注了,那么MSSQL呢?有点茫然,没事继续看看。

    在Mssql中就要稍微变通一下了,怎么延迟时间呢,通过多个count函数的统计,来延迟时间,比如我想获取sysuser表中的用户名,我们可以这样注入:

http://127.0.0.1/news.aspx?id=1 and (SELECT count(*) FROM sysusers AS sys1, sysusers assys2, sysusers as sys3, sysusers AS sys4, sysusers AS sys5, sysusers AS sys6,sysusers AS sys7, sysusers AS sys8)>1 and 300>(select top 1ascii(substring(name,1,1)) from sysusers)

    我们知道用户名的第一个字母的ASCII肯定小于300,所以该语句返回真,执行需要大概延迟14秒,继续执行:

http://127.0.0.1/news.aspx?id=1 and (SELECT count(*) FROM sysusers AS sys1, sysusers assys2, sysusers as sys3, sysusers AS sys4, sysusers AS sys5, sysusers AS sys6,sysusers AS sys7, sysusers AS sys8)>1 and 0 >(select top 1 ascii(substring(name,1,1))from sysusers)

    这一句就是判断用户名的第一个字母的ASCII是否小于0,肯定不可能,所以返回假,执行只要1秒,这就是时间延迟的方法,猜解其他的字段和内容也是同理,很有意思吧。

    总结一下时间延迟的总体思路就是如何构造时间延迟的问题,也就是构造能够判断TRUE和FALSE的语句即可。

    <3> 正则表达式

    第二种方法,让人感觉有点不靠谱,因为他依赖于网速,有时候比较尴尬,那么我们还有方法,就是本节要讲的正则表达式盲注。这种方法有更快的速度,可以节省更多的时间。主要的思想是:我们通过制定数字、字符串和特殊字符来利用mysql中的REGEXP函数或者是MSSQL中的like函数进行匹配。

    在Mysql中我们可以使用regexp函数进行正则表达式匹配,在注入语句中可以这样写:

http://127.0.0.1/gbook/gshow.php?bid=1 and 1=(select 1 from admin where admin regexp '^[a-z]' limit 0,1)

    简单解释一下,后面的sql如果存在那么返回是1,也就是and 1=1 结果成立,返回和原来一样页面。如图:

关于 Blind SQL Injection (SQL盲注) 的利用方法总结

    既然正常,继续调整正则的范围,如图:

关于 Blind SQL Injection (SQL盲注) 的利用方法总结

    看到了一个空内容的页面,说明第一个用户名的首字母不在a-h之间,调整h-z,通过不断缩小范围。最后改成^n以后我们发现返回正常,说明首字母是n(首个用户是nohack),就这样又可以通过页面返回页面来判断了,那么如何猜解第二个字符呢?同理,将正则表达式写成^n[a-z],不断循环判断就完成了整个字符串的猜解了。是不是感觉太有意思了?这个方法会更快,但是需要您有一定的正则表达式基础。

    以上是mysql的盲注方法,那么MSSQL如何实现?我们还记得mssql中有模糊匹配的关键字like。

    有了上面的基础,我想mssql也是很简单的,我直接给出利用语句例子:

http://127.0.0.1/news.aspx?id=1 and AND 1=(SELECT TOP 1 1 FROM information_schema.tables WHERETABLE_SCHEMA=”dbname” and table_name LIKE ‘[a-z]%’

    其他的就不说了。大家自己变通吧~~

0x04 总结

    盲注,已经不再像普通的注入了,需要我们进行适当的变通就可以继续注入了。同时也会发现这是一个很有意思的领域,也许你有更多的思路,期待您的分享。有不对的地方和不解的地方可以跟我交流,我的ID是:LengF。