SQL 注入 -“错误”的语句为什么会得到“正确”的结果?
故事发生在前段时间准备内部 CTF-SQL 注入题目过程中。
前景提要
首先看下表的结构以及数据:
题目是要求实现一个查询,然后通过注入获取到 admin 的商品及其密码,再看下我的查询语句:
起因
我尝试在 name 字段进行 SQL 注入,过程中拼接出这样一个 SQL 语句:
这个语句的后半部分比较奇怪,但是它的查询结果是“正确”的,得到了我们需要的 admin 的商品及其密码:
那我们就需要研究一下这个语句为什么可以得到这样的结果了。
其一
首先我们先看一下后半条 union select 的语句:
执行发现输出了表中所有的 password:
这条语句与常规语句的不同点在于等于号后面的值是在括号中的,那为什么会得到这个查询结果呢?我们一步一步来分析。
首先,如果括号中是一个单独的字符串,那么和正常的结果没有区别
如果括号中是一个条件语句,为 true 时无结果,为 false 时返回全部结果。
为什么会是这样的结果呢?多次尝试之后得到了答案。我们的两个 name 均为字符串,而字符串默认为 false,所以 name=flase 时会查询出所有 name 为字符串的 password。“字符串默认为 false,整数默认为 true”
所以这就可以解释为什么最开始的 where name =('admin' and password='123')可以把两个 password 都输出出来,因为在条件语句中,and 前面的'admin'相当于 false,所以这个条件语句的结果最后肯定是 false。
既然我们已经知道了原因,那么再来一个这样的语句看看结果:
首先针对 admin/admin123 这一条数据来说,password='admin123'结果为 true,where name=true,但是 name 是 admin 是一个字符串,是 flase,所以就不会输出了。针对 wangyibo/orange 这一条数据来说,password='admin123'结果为 false,name=false 就会输出这一条的 password;
其二
根据上述分析我们可以看到 union 后面的查询语句,实际上是会查询出两个 password 的,那为什么整条语句查询的时候会只查询出一个 password 呢?
这个问题其实比较好猜测,第一时间就想到了去重问题,我们的 product 和 password 都有一个 orange,那么是不是查询结果自动去重了呢?更改 password 之后发现果然如此:
但是要知道 select 是不会自动去重的,那么问题就出现在了 union 这儿:
使用 union all 就可以得到不去重的结果:
版权声明: 本文为 InfoQ 作者【BUG侦探】的原创文章。
原文链接:【http://xie.infoq.cn/article/5549554ba9e2a1c7d2d3f39cb】。文章转载请联系作者。
评论