SQL约束攻击

Dec 20, 2017 09:54 · 107 words · 1 minute read PHP

感觉最终的效果和万能密码的差不多。

简介

sql约束攻击也是针对数据库的攻击,它的作用类似于万能密码,可以实现登录任意账号,但是原理不同。

利用条件

  • 注册时可以输入任意长度或者大于数据库字段限制的长度的用户名。

产生背景

假设后台处理用户注册的代码如下

<?php
//此处省略的是连接数据的代码
$username = mysql_real_escape_string($_GET['username']);
$password = mysql_real_escape_string($_GET['password']);
$query = "SELECT * FROM users WHERE username='$username'";
$res = mysql_query($query, $database);
if($res) {
  if(mysql_num_rows($res) > 0) {
    // 用户名已存在
  }
  else {
    // 将用户数据插入数据库
    $query = "INSERT INTO users(username, password) VALUES ('$username','$password')";
    mysql_query($query);
  }

后台处理用户登录的代码如下

//此处省略的是连接数据的代码
$username = mysql_real_escape_string($_GET['username']);
$password = mysql_real_escape_string($_GET['password']);
$query = "SELECT * FROM users WHERE username='$username' and password='$password'";
$res = mysql_query($query);
if($res){
    if(mysql_num_rows($res)>0){
        echo "成功登陆"
    }else{
        echo "登录失败";
    }
}

可以看到这两段代码都对传入的数据做了转义,万能密码肯定是不行的。但是这样就没有办法了?这里就可以用到sql约束攻击。

漏洞原理

在mysql的select语句中,下面两条语句是相同的

select * from user where username='username';

select * from user where username='username    ';

亲测有效

原因就是在SQL中执行字符串处理时,字符串末尾的空格符将会被删除。

在创建数据表的时候会用varchar(30)来限制存入数据的数据长度,如果数据长度大于30,那么大于30的部分就会被丢弃,最终存入数据库的就是原本数据的前30位。

假如用户的用户名为admin,那么我们注册一个名字大于30并且前几位等于admin的用户。例:

admin                                                              1

注意要在最后添加一个字符,不然注册的时候会提示用户名已存在。

那么最终存入数据库的用户名就是admin加上一串空格。

现在再去登录admin用户,输入自己注册时的密码,就可以成功登录了。登陆后搜索该用户名的SELECT查询都将返回第一个数据记录,也就是原始用户的数据记录。这样的话,攻击者就能够以原始用户身份登录。

防御手法

限制用户注册的用户名长度。

tweet Share