SQL-Labs 实验
Less-24:
这一关与之前的关卡都不同,进入之后,发现本关主要有以下几个功能,一是用户登陆页面;二是用户注册页面;三是用户修改密码页面;四是忘记密码页面。这里的忘记密码页面没什么用,主要是依托前三个页面,进行两个账号注册,然后修改密码进行二次注入,就可以破解用户登陆密码。

观察这一用户登陆页面,我们可以注意到这里有一个"New User click here?",点击之后,发现进入了新的注册页面,如下图:

这里我们注册一个新的账号:heze09,密码输入:123。
记住这里的密码,后面我们会发现,可以在不知道当前密码的情况下,修改这个账号的密码,使用新的密码登陆。
这个时候,我们观察一下原代码中,关于查询用户账号与密码的SQL语句:
php
function sqllogin(){
$username = mysql_real_escape_string($_POST["login_user"]);
$password = mysql_real_escape_string($_POST["login_password"]);
$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
//$sql = "SELECT COUNT(*) FROM users WHERE username='$username' and password='$password'";
$res = mysql_query($sql) or die('You tried to be real smart, Try harder!!!! :( ');
$row = mysql_fetch_row($res);
//print_r($row) ;
if ($row[1]) {
return $row[1];
} else {
return 0;
}
我们可以看到,在登陆用户界面时,使用mysql_real_escape_string()函数对账户名和密码进行了单、双引号的过滤,这里我们再次查询其他页面,发现在用户注册页面当中的SQL查询语句,没有严格的过滤单、双引号,我们就可以利用这一点修改Payload。
php
if (isset($_POST['submit']))
{
# Validating the user input........
//$username= $_POST['username'] ;
$username= mysql_escape_string($_POST['username']) ;
$pass= mysql_escape_string($_POST['password']);
$re_pass= mysql_escape_string($_POST['re_password']);
echo "<font size='3' color='#FFFF00'>";
$sql = "select count(*) from users where username='$username'";
$res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');
$row = mysql_fetch_row($res);
//print_r($row);
if (!$row[0]== 0)
{
?>
<script>alert("The username Already exists, Please choose a different username ")</script>;
<?php
header('refresh:1, url=new_user.php');
}
else
{
if ($pass==$re_pass)
{
# Building up the query........
$sql = "insert into users ( username, password) values(\"$username\", \"$pass\")";
mysql_query($sql) or die('Error Creating your user account, : '.mysql_error());
echo "</br>";
echo "<center><img src=../images/Less-24-user-created.jpg><font size='3' color='#FFFF00'>";
//echo "<h1>User Created Successfully</h1>";
echo "</br>";
echo "</br>";
echo "</br>";
echo "</br>Redirecting you to login page in 5 sec................";
echo "<font size='2'>";
echo "</br>If it does not redirect, click the home button on top right</center>";
header('refresh:5, url=index.php');
}
else
{
?>
<script>alert('Please make sure that password field and retype password match correctly')</script>
<?php
header('refresh:1, url=new_user.php');
}
}
}
我们构造一个新的账号:heze09'#,密码:789。这里实际上是将"heze09'#"作为一个字符串进行了输入,当作账户名。
这时我们返回最初的登陆界面,使用账号:heze09'#,密码:789来登陆系统。

登陆之后的页面如下图所示:

通过查询这个页面的源码,我们发现SQL语句可以进行修改密码的操作。
php
if (isset($_POST['submit']))
{
# Validating the user input........
$username= $_SESSION["username"];
$curr_pass= mysql_real_escape_string($_POST['current_password']);
$pass= mysql_real_escape_string($_POST['password']);
$re_pass= mysql_real_escape_string($_POST['re_password']);
if($pass==$re_pass)
{
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
$res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');
$row = mysql_affected_rows();
echo '<font size="3" color="#FFFF00">';
echo '<center>';
if($row==1)
{
echo "Password successfully updated";
}
else
{
header('Location: failed.php');
//echo 'You tried to be smart, Try harder!!!! :( ';
}
}
else
{
echo '<font size="5" color="#FFFF00"><center>';
echo "Make sure New Password and Retype Password fields have same value";
header('refresh:2, url=index.php');
}
}
上述代码中最重要的一句SQL更新用户名与密码的代码是这一句:
php
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
我们在用户名这里输入了"heze09'#",其中"#"将后面的语句注释掉了,实际上整条查询语句就变以下面这句:
php
$sql = "UPDATE users SET PASSWORD='$pass' where username='heze09'#' and password='$curr_pass' ";
可以看到,我们以heze09'#账号进入了一个可以修改用户密码的页面,这时在Current Password这里可以随便输入一个密码,如567,然后输入新的密码:456,并确认。
这里需要提醒大家的是,这个修改密码的操作,实际上是修改了账号:heze09的密码,上文提到这个账号的初始密码是123,我们修改了密码之后,就可以使用新的密码:456来登陆heze09的账户了。


这是使用账号heze09,密码:456,登陆进来的页面。由此,我们可以看到,这种情况下,不需要知道账号heze09原来的密码是什么,也可以成功重置密码进行登陆。