目录
初探
有一天突然发现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 |

本文探讨了Mysql中字符串与数字比较时的特殊行为,包括字符串自动转换为数字、判断列名存在性及利用这些特性进行SQL注入攻击的方法。揭示了如何通过巧妙运用这些规则,实现字符串列数据的提取、万能密码的构造等技巧。
1098

被折叠的 条评论
为什么被折叠?



