美文网首页
login1(SKCTF) (sql约束攻击)

login1(SKCTF) (sql约束攻击)

作者: wuli_decade | 来源:发表于2018-08-26 12:34 被阅读222次

    题目

    image.png

    背景知识

    最近,我遇到了一段有趣的代码,它尝试尽一切可能来保护数据库的访问安全,例如每当新用户进行注册时,将运行以下代码:

    <?php 
    // Checking whether a user with the same username exists 
    $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) { 
        // User exists, exit gracefully 
        . 
        . 
      } 
      else { 
        // If not, only then insert a new entry 
        $query = "INSERT INTO users(username, password) 
                  VALUES ('$username','$password')"; 
        . 
        . 
      } 
    } 
    

    为了验证登录信息,将用到下列代码:

    <?php 
    $username = mysql_real_escape_string($_GET['username']); 
    $password = mysql_real_escape_string($_GET['password']); 
    $query = "SELECT username FROM users 
              WHERE username='$username' 
                  AND password='$password' "; 
    $res = mysql_query($query, $database); 
    if($res) { 
      if(mysql_num_rows($res) > 0){ 
          $row = mysql_fetch_assoc($res); 
          return $row['username']; 
      } 
    } 
    return Null; 
    

    攻击手法

    首先,在处理SQL中的字符串时,字符串末尾的空格字符都会被删除。换句话说,“vampire”与“vampire ”几乎是等效的,这在大多数情况下是正确的,例如WHERE子句中的字符串或INSERT语句中的字符串。例如,以下语句的查询结果,与使用用户名“vampire”进行查询时的结果是一样的。

           SELECT * FROM users WHERE username='vampire '; 
    等同于  SELECT * FROM users WHERE username='vampire'; 
    

    究其原因是因为在字符串比较的过程中,内部在比较之前先进行了补充,使其长度一致再进行比较。

    下面再本地复现一遍。

    image.png
    image.png
    SELECT username FROM users WHERE username='vampire' AND password='random_pass';
    

    当执行这条语句后,数据库将返回我们自己注册的账户信息,但是注意此处的return $username,虽然此时查询出来的是我们自己的用户信息,但是返回的用户名则是目标的用户名。如果此后的业务逻辑直接以该用户名为准,则我们就达到了水平越权的目的。

    现在讲一下sql约束攻击的条件:

    1.mysql处于ANSI模式。如果是TRADITIONAL模式或者STRICT_TRANS_TABLES模式会报错data too long for column。

    2.服务端没有对用户名长度进行限制。如果服务端限制了用户名长度就自然就不客能导致数据库截断,也就没有利用条件。

    3.登陆验证的SQL语句必须是用户名和密码一起验证。如果是验证流程是先根据用户名查找出对应的密码然后再比对密码,当使用vampire为用户名来查询密码的话,数据库此时就会返回两条记录,而一般取第一条即目标用户的记录,那么传输的密码肯定和目标用户密码匹配不上的。

    4.验证成功后返回的必须是用户传递进来的用户名,而不是从数据库取出的用户名。因为当我们以用户vampire和密码random_pass登陆时,其实数据库返回的是我们自己的用户信息,而我们的用户名其实是vampire+若干个空格,如果此后的业务逻辑以该用户名为准,那么就不能达到越权的目的了。

    回到题目之中。

    我们注册一个如下账号


    image.png

    然后直接 username:admin password:As123123登陆


    相关文章

      网友评论

          本文标题:login1(SKCTF) (sql约束攻击)

          本文链接:https://www.haomeiwen.com/subject/knewbftx.html