浅谈盲注中的基于时间型和布尔型的注入方法

SQL显错注入已经被用烂了像这种漏洞,漏洞批量发现工具找一找,sqlmap跑一跑。

今天讲的是在我们的命令被带入数据库查询语句但是却什么都没有返回的情况我们该怎么办。例如应用程序就会返回一个“通用的”的页面,或者重定向一个通用页面(可能为网站首页)。这时,我们之前学习的SQL注入办法就无法使用了。

盲注,即在SQL注入过程中,SQL语句执行选择后,选择的数据不能回显到前端,我们需要使用一些特殊的方法进行判断或尝试,这个过程称为盲注

SQL盲注分为三大类:

1.基于布尔型SQL盲注

2.基于时间型SQL盲注

3.基于报错型SQL盲注


有三个函数在整个过程中一直被使用

1.mid()函数

mid(striing,start,length)

string(必需)规定要返回其中一部分的字符串。

start(必需)规定开始位置(起始值是 1)。

length(可选)要返回的字符数。如果省略,则 mid() 函数返回剩余文本。


2.substr()函数

substr(string,start,length)

string(必需)规定要返回其中一部分的字符串。

start(必需)规定在字符串的何处开始。

length(可选)规定被返回字符串的长度。


3.left()函数

left(string,length)

再怎么解释也不如直接开弄

string(必需)规定要返回其中一部分的字符串

length(可选)规定被返回字符串的前length长度的字符

先讲讲怎么来做基于布尔型的盲注吧

基于布尔型SQL盲注即在SQL注入过程中,应用程序仅仅返回True(页面)和False(页面)。
这时,我们无法根据应用程序的返回页面得到我们需要的数据库信息。但是可以通过构造逻辑判断(比较大小)来得到我们需要的信息。


此时返回正常,并没有返回404页面,证明库的长度为8字节

这个使用left()判断库的名字第一位是什么;这是页面如果返回正常,说明首字母应该是小于t

这是页面如果返回正常,说明首字母应该是大于r,那么首字符就是s了,依次以这样的方法去判断。


那么我们来判断库的第二位是什么(在这里使用了ascii判断)

最后发现了当前的库名字为“security”

下面来猜表的名字第一个库的第一表的首字符ascii大于113

ascii<115,这两页返回正常说明,表的首字符为'r'

经过查找后该表名为referer。

猜测第三个字段的的首字母

所以,当前数据表的第三个字段的第一个字符为’i’;一次类推,当前数据表的第四个字段为’id’

猜测第三个字段第一个数据项的第一个字符:

所以,当前字段的第一个数据项的第一个字符为’D’

猜第二个


所以,当前字段的第一个数据项的第一个字符为’u‘

以此类推,当前字段的第一个数据项为’Dumb

同样的方法可以推出‘password’字段的第一个数据项为’Dumb’’


在布尔的盲注的基础上在下基于时间型的注入

在我们注入了SQL代码之后,存在以下两种情况:

  • 如果注入的SQL代码不影响后台[数据库]的正常功能执行,那么Web应用的页面显示正确(原始页面)。
  • 如果注入的SQL代码影响后台数据库的正常功能(产生了SQL注入),但是此时Web应用的页面依旧显示正常(原因是Web应用程序采取了“重定向”或“屏蔽”措施)。

这时候,我们就会产生一个疑问:我们注入的的SQL代码到底被后台数据库执行了没有?即Web应用程序是否存在SQL注入?

面对这种情况,之前讲的基于布尔的SQL盲注就很难发挥作用了(因为基于布尔的SQL盲注的前提是Web程序返回的页面存在true和false两种不同的页面)。这时,我们一般采用基于web应用响应时间上的差异来判断是否存在SQL注入,即基于时间型SQL盲注。

if语句/if()函数

在基于时间型SQL盲注中,我们经常使用条件语句来判断我们的操作是否正确:

<code class="hljs bash has-numbering"><span class="hljs-keyword">if</span> condition <span class="hljs-keyword">then</span> <span class="hljs-keyword">do</span>_something <span class="hljs-keyword">else</span> <span class="hljs-keyword">do</span>_something_<span class="hljs-keyword">else</span>11</code>
即如果某条件发生,那么执行语句一;否则,执行语句二

MySQL中,if()函数语法如下:

<code class="hljs ruleslanguage has-numbering"><span class="hljs-keyword">IF</span>(expr1,expr2,expr3)</code>

如果 expr1 为真,则 IF()函数执行expr2语句; 否则 IF()函数执行expr3语句。

sleep()函数

在mysql中,sleep()函数语法如下:

<code class="hljs erlang has-numbering"><span class="hljs-function"><span class="hljs-title">sleep</span><span class="hljs-params">(seconds)</span></span></code>

即sleep() 函数代码执行延迟若干秒。

BENCHMARK()函数

在mysql中,BENCHMARK()函数语法如下:

<code class="hljs axapta has-numbering">BENCHMARK(<span class="hljs-keyword">count</span>,expr)
</code>
即BENCHMARK()函数重复执行表达式expr count次。

一般情况下,我们不建议使用BENCHMARK()函数,因为其消耗大量的CPU资源。


接下来,学习基于时间型SQL盲注。

我们在这里使用IF(查询语句,1,sleep(5)),即如果我们的查询语句为真,那么直接返回结果;如果我们的查询语句为假,那么过5秒之后返回页面。所以我们就根据返回页面的时间长短来判断我们的查询语句是否执行正确,即我们的出发点就回到了之前的基于布尔的SQL盲注,也就是构造查询语句来判断结果是否为真。

步骤一 枚举出当前数据库名


database()即能显示当前数据库,然后通过比较当前当前数据库的ascii码来枚举当前数据库的具体字符(建议采用二分法来一一枚举)。

最后,我们得到当前数据库为“security”。

步骤二 枚举当前数据库的表名

这里我们仅仅展示枚举当前数据库第一个表的第一个字符的方法,如图所示:

可以看出,当我们将表的第一个字符与102比较时,过了5秒之后才浏览器才显示(忽略下面的内容),即表的第一个字符大于102为假。然后我们将表的第一个字符与100比较,浏览器直接显示,即表的第一个字符大于100。这样就能得到表的全部字符。

最后,我们得到当前数据库第一个表名为“emails”。

步骤三 枚举当前数据表的字段名

这里,我们完整的展示枚举当前数据表的第一个字段名。如图所示:

很多人会疑惑,我们究竟怎么判断我们得到的各个字符就是完整的字段名呢?因为我们并不知道字段的长度。

这个很简单,就是当我们在枚举字段名时,如果我们直接与1进行比较(即假设当前字符的ascii码大于1),如果这都显示错误,那一般情况下,我们可以认为我们已经得到了完整的字段名了。如图所示:

步骤四 枚举各个字段对应的数据项内容

在这一步的时候,遇到了一下问题,具体如下:


一步步判断,最后的结果为'admin'

最后感谢熊俊坤的博客。

猜你喜欢

转载自blog.csdn.net/weixin_45682070/article/details/107819901