SQL中存在的约束攻击

一句话

原因是SQL中不同操作对长度和空格的处理方式存在了差异

内容

背景

1) 我们假设现在有一个注册页面的逻辑是:

  1. 先用select语句检查输入的用户名是否存在在DB中,如果存在,就说明已经注册过了,便会不让你注册。

    select * from table where username = '$username'
  2. 当用户名不存在的时候,就用insert来把你输入的用户名和密码插入到DB中

    insert into table values('$username','$password');

2) 现在数据库存在一条数据:用户名:admin,密码:12345

原因

在MySQL中select和insert对代空格的处理方式有差异:select是删除,insert则是截取最大长度的字符串。

假设我们设置了insert的最大长度是25,我们输入用户名为admin[20个空格]1,密码123456789。当执行第一条语句select的时候因为用了select,所以中间的空格被忽略,最后是以admin1来进行数据库检索,因此我们自然找不到重合的用户。

所以这个时候我们就注册了一个新用户admin1,密码123456789。但是当我们的数据库在插入新的数据用insert操作的时候,是不会删除空格,而是截取我们的这个admin[20个空格]1 。

因此我们最后就存了用户名:admin[20个空格],密码:123456789进入了数据库作为新的用户。这时候如果我们用admin 去查找,用select语句,就会返回两条记录,一条是真正的admin另一条是我们绕过用户名检测假的admin(数据库里面的空格也在查询的时候被删除了再比较),这时我们用admin和自己设的密码就可以登陆了。

一言以蔽之:用假密码登录真用户。

结论

有差异,就有漏洞

最后提醒

查询条件中建议对字符串做trim处理,在数据入库的时候最好也做trim处理。