BUUCTF-Web-Sql注入-[SUCTF 2019]EasySQL
题目链接:BUUCTF
类型:sql注入
知识点:堆叠注入、mysql异或、mysql服务器变量(sql_mode)、后端代码推测
解题方法:两种方法
这道题考的是一道堆叠注入,题目涉及到了后端代码推测和mysql的部分基础知识,代码推测意思就是构造前端输入根据后端回显信息去推测后端用到的是什么sql语句,这对我这种CTF小白来说根本没什么经验,所以咱就是说根本做不出来!,只能求助官方大大的wp才能勉强做出来
解题过程
方法1
通过html代码审计是post型传输,用hackbar工具分别传入整数和字符,大致推测是整型注入
query=1
目标回显1query=a
目标无回显,没什么错误信息,这个时候就可以先尝试整型注入了
通过数字型内联注入构造永真条件时发现目标存在过滤
query=1 or 1=1
再次尝试order by也被过滤了,那就别谈什么联合注入和盲注了,后来尝试报错注入也是被过滤了,下次遇到这个情况直接先尝试堆叠注入,如果目标存在堆叠注入那就可以节省很多渗透的时间
尝试堆叠注入去查询库中的表,目标回显了数据库中的表说明存在堆叠注入
query=1;show tables#
发现flag表
尝试show出flag表中的字段被目标过滤了,desc查看flag表也被过滤了,这样的话目标应该是过滤了“flag”字符串
query=1;show columns from flag #
query=1;desc flag#
因为表名也叫做flag再加上from后面的语句不好去编码绕过,所以到这边就不会做了,然后看了官方大大的wp,官方的意思是根据输入0和1推测目标sql代码包含"||"操作,目标sql原语句如下
select $_POST['query'] || flag from flag
说实话,这没点做题经验还真推不出来,因为输入1或0的回显信息太少了,我严重怀疑这是给东道主的题!
有了原sql语句就好做很多了,先构造*号再加上一个数字来补全后面"||"运算缺少的操作符就可以查出flag表中的所有数据了
query=*,1
注意这边查出flag表中的数据还多了一列1的数据,原理其实很容易理解
先来了解一下mysql的逻辑操作符知识点,也就是mysql如何处理逻辑运算的,官网其实有详细的解释,mysql的操作符运算对象是操作数也就是整数,那种字符串数据都视为0也就是假,"||“操作符也就是是或运算,格式为支持操作符的sql关键字+操作数对象1+||+操作数对象2,运算规则为两个操作数中只要一个结果为真就返回真,就返回1,下面直接通过实验来理解,使用select来进行”||"运算,`先来看为真的结果
select 1 || 1;select 1 || 0;
再来看看当||运算符返回假的结果select 0 || 0;
因为||操作符两边的操作数都为0,即两者都为假所以返回0
这时我们将右边的操作数0换成一个字符"a"
注意操作符会将双引号中的数字当成整型,也就是说"1"相当于整型1select 0 || "a";
可以看到"||“操作符将string数据视为假,即"字符/字符串”
了解这些后再配合完整的查询语句来看看select 1 || flag from flag;
在解释之前先来看看这条sql语句的执行顺序
- mysql先执行from语句将flag表中的数据零时存放到内存中
- 然后mysql执行select语句选择指定的数据,这时select发现有操作符运算先执行操作符运算
- 操作符||在对两边的操作数进行运算时发现右边的操作数对象既不是字符串又不是整型,于是又交给select
- select从内存中找出关于flag列名的内容,这时"1||flag"就变成了"1 || flag字符串",然后交给操作符||
- 操作符进行运算发现左边是真右边是假,或运算一真一假即为真,所以"1 || flag字符串"返回结果为1
- 最后select将最终结果"1"创建一个虚拟表打印出来
相信理解执行顺序后就应该这道为什么返回结果为1了吧!,至于为什么会将flag信息查出来是因为select在选择||操作符返回的数据以外还要选择"*"包含的数据也就是flag表中的所有内容,所以flag内容就直接被查出来了
方法2
网上搜了大佬的wp后还可以使用另外一种方法获取flag表中的内容,payload如下
query=1;set sql_mode=pipes_as_concat;select 1
原理很简单,就是通过堆叠注入修改sql服务器模式让操作符"||“变成连接符(和concat函数一样),这样原本的sql语句就变成了
select concat($_POST['query'],flag) from flag
mysql的模式模式可以通过修改系统变量sql_mode来改变服务模式,通过查询官网手册,发现这个服务模式主要是用于兼容不同mysql版本的sql语句能正常执行,而"pipes_as_concat"作用就是将操作符”||"变为连接符,官方解释如下
至于concat函数就不解释了后面的sql注入基础中会讲到