强网杯2019 - 随便注

这题靠我自己当然是做不出来的,看了 n 多边题解才学会,直接说做法。

首先简单测一下,可以发现外边是包了单引号的,而且 1’ or ‘1’='1 可以把表中所有数据都拉出来。

select 之类的指令被禁用了,但是可以使用堆叠注入。堆叠注入就是使用分号,在一条查询语句中塞入多个数据库指令。本题就使用堆叠注入。

show tables 查看所有表:

1
1'; show tables; #

看到有 words 和 1919810931114514 两个表。

desc 查看表结构:

1
1'; desc words; #

可以看到表有两个字段 id 和 data 。

推测出后端查询语句大概是 select id, data from words where id = 。

select 被禁用了,那如何跨表查询呢?

这里脑洞就来了 =。=

把 words 改成其他名字,把装 flag 的表改成 words ,然后再在当前表查询,就能查到 flag 。

这里如果只把 words 改跑,而没有把别的表改成 words ,那么数据库就会被注坏。因为查询语句是从 words 里查的,这个是写死的,所以如果没有把 words 的位置补上,查询语句就在一开始出错,后面就无法再进行操作了。

所以要同时改两次名:

1
1'; rename tables words to word; rename tables `1919810931114514` to words; #

这样改两次名之后你会发现数据库还是被注坏了,提示 Unknown column ‘id’ in ‘where clause’ 。

这是因为另一个表的没有名为 id 的字段,如果不改列名同样会让查询语句出错。

首先查另一个表的表结构,得知字段是 flag ,然后修改列名:

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

最后用 1’ or ‘1’='1 把当前表的所有值全拉出来就得到 flag 。