|
为了便于理解直接从隐式转换的注入例子开始来往下分析.
创建表,加入俩个用户
CREATE TABLE `users` (
`userid` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(45) NOT NULL,
`password` varchar(45) NOT NULL,
PRIMARY KEY (`userid`)
);
INSERT INTO `users` (`username`, `password`) VALUES (‘admin’, ‘MySuperS3cretPass!’);
INSERT INTO `users` (`username`, `password`) VALUES (’666admin’, ‘nataSmaI’);
看如下查询
mysql> SELECT * FROM users WHERE username = ‘a’+'b’ AND password = ‘a’+'b’;
+——–+———-+——————–+
| userid | username | password |
+——–+———-+——————–+
| 1 | admin | MySuperS3cretPass! |
+——–+———-+——————–+
1 row in set, 7 warnings (0.00 sec)
mysql> SHOW WARNINGS;
+———+——+——————————————————–+
| Level | Code | Message |
+———+——+——————————————————–+
| Warning | 1292 | Truncated incorrect DOUBLE value: ‘admin’ |
| Warning | 1292 | Truncated incorrect DOUBLE value: ‘b’ |
| Warning | 1292 | Truncated incorrect DOUBLE value: ‘a’ |
| Warning | 1292 | Truncated incorrect DOUBLE value: ‘MySuperS3cretPass!’ |
| Warning | 1292 | Truncated incorrect DOUBLE value: ‘b’ |
| Warning | 1292 | Truncated incorrect DOUBLE value: ‘a’ |
| Warning | 1292 | Truncated incorrect DOUBLE value: ’666admin’ |
+———+——+——————————————————–+
7 rows in set (0.00 sec)
好奇这个结果怎么回事这样的. 没错,这里利用了隐式转换注入.回过头来分析一下原理.
mysql> SELECT 1+1;
+—–+
| 1+1 |
+—–+
| 2 |
+—–+
1 row in set (0.00 sec)
如上查询没什么问题…这里不说了..接着下面
mysql> SELECT ‘foo’+1;
+———+
| ‘foo’+1 |
+———+
| 1 |
+———+
1 row in set, 1 warning (0.00 sec)
mysql> SHOW WARNINGS;
+———+——+—————————————–+
| Level | Code | Message |
+———+——+—————————————–+
| Warning | 1292 | Truncated incorrect DOUBLE value: ‘foo’ |
+———+——+—————————————–+
1 row in set (0.00 sec)
这里发生了隐式转换,结果为查询结果为1.这里’foo’被转换成double类型.但是显然他不是数字,所以他将转换成0.
mysql手册说明如下:
When an operator is used with operands of different types, type conversion occurs to make the operands compatible.
那么添加俩个字符串呢?不需要转换吗?看下面sql执行
mysql> SELECT ‘a’+'b’;
+———+
| ‘a’+'b’ |
+———+
| 0 |
+———+
1 row in set, 2 warnings (0.00 sec)
mysql> SHOW WARNINGS;
+———+——+—————————————+
| Level | Code | Message |
+———+——+—————————————+
| Warning | 1292 | Truncated incorrect DOUBLE value: ‘b’ |
| Warning | 1292 | Truncated incorrect DOUBLE value: ‘a’ |
+———+——+—————————————+
2 rows in set (0.00 sec)
这里+是个算术运算符.俩个字符串转化为数值.0+0..结果自然就是0了.
现在知道俩个字符串的总合是0.通过查询我们知道 SELECT ‘a’ + ‘b’ = 0的结果是true(数值就是1).
那么比较下俩个字符串总和和另外一个字符串.
mysql> SELECT ‘a’+'b’='c’;
+————-+
| ‘a’+'b’='c’ |
+————-+
| 1 |
+————-+
1 row in set, 3 warnings (0.00 sec)
mysql> SHOW WARNINGS;
+———+——+—————————————+
| Level | Code | Message |
+———+——+—————————————+
| Warning | 1292 | Truncated incorrect DOUBLE value: ‘b’ |
| Warning | 1292 | Truncated incorrect DOUBLE value: ‘a’ |
| Warning | 1292 | Truncated incorrect DOUBLE value: ‘c’ |
+———+——+—————————————+
3 rows in set (0.00 sec)
从warning我们可以看出都进行了隐式转换.查询执行应该是select 0=0…结果就是1.
mysql手册说明如下:
In all other cases, the arguments are compared as floating-point (real) numbers.
好了,基础了解到这里,来理解下文章开头那个案例.
SELECT * FROM users WHERE username = ‘a’+'b’ AND password = ‘a’+'b’;
在查询的时候数值进行隐式转换和比较.比如第一条记录的username过程应该是这样的..
select ‘admin’='a’+'b’结果自然为1,password以此类推.
到第二条记录的时候,select ’666admin’='a’+'b’,进一步分析select 666=’a'+’b',结果为假.数值就是0.所以开头那个案例的查询结果就是那样的了…
如果需要查询满足第二个条件select ’666admin’=666这个可以满足,利用如下:
mysql> SELECT * FROM users WHERE username = ‘a’+’666′ AND password = ‘a’+'b’;
+——–+———-+———-+
| userid | username | password |
+——–+———-+———-+
| 2 | 666admin | nataSamI |
+——–+———-+———-+
1 row in set, 6 warnings (0.00 sec)
|
|