写点什么

SQL 注入 -“错误”的语句为什么会得到“正确”的结果?

作者:BUG侦探
  • 2022 年 2 月 23 日
  • 本文字数:886 字

    阅读完需:约 3 分钟

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 就可以得到不去重的结果:







发布于: 刚刚阅读数: 2
用户头像

BUG侦探

关注

还未添加个人签名 2021.06.08 加入

专注于发掘程序员/工程师的有趣灵魂,对工作中的思路与总结进行闪光播报。

评论

发布
暂无评论
SQL注入-“错误”的语句为什么会得到“正确”的结果?