二次注入原理
二次注入(存储型注入),这种手法所利用的原理是:在网站处理用户提交的数据的时候,只是将某些敏感字符进行了转义。因而使得用户第一次提交的时候不会被当做代码执行。但是这些数据存入数据库的时候却没有转义(比如用户输入的数据为admin'#
,进行执行代码的时候会转义为admin\'#
,存入数据库的数据仍为admin'#
),而网站程序默认数据库中的数据都是安全的,当网站程序第二次调用刚才存储的脏数据的时候,则不会转义使用而是直接使用,因此就会达到注入的效果。
注意两点:
1、网站会将数据原封不动的存入数据库中。
2、网站会直接调用数据库中的数据而不会对其进行检测等操作。(信任数据库中的数据)
第一次进行数据库插入数据的时候,使用了 addslashes 、get_magic_quotes_gpc、mysql_escape_string、mysql_real_escape_string等函数对其中的特殊字符进行了转义,但是addslashes有一个特点就是虽然参数在过滤后会添加 “\” 进行转义,但是“\”并不会插入到数据库中,在写入数据库的时候还是保留了原来的数据。在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次进行需要进行查询的时候,直接从数据库中取出了脏数据,没有进行进一步的检验和处理,这样就会造成SQL的二次注入。
- 第一步:插入恶意数据
进行数据库插入数据时,对其中的特殊字符进行了转义处理,在写入数据库的时候又保留了原来的数据。 - 第二步:引用恶意数据
开发者默认存入数据库的数据都是安全的,在进行查询时,直接从数据库中取出恶意数据,没有进行进一步的检验的处理。并不会进行转义操作,而是直接拼接到SQL语句中执行。
Less24黑盒
一个用户登录界面,可以注册新用户和登录。
我们登录一个Dumb:Dumb
看一下
可以更改密码
我们看一下我们当前的users表
我们注册一个新用户admin'#
,密码为123456
admin'#
是直接原数据存入了数据库
我们登录admin'#
用户,进行修改密码
将密码修改为nihao
但发现admin
用户的密码变为了nihao
然后我们就获得了admin:nihao
,可以登录这个账户了。这就是我们的目的
Less24白盒
注册用户
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.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');
}
}
}
?>
对用户输入的数据进行了转义
$username= mysql_escape_string($_POST['username']) ;
$pass= mysql_escape_string($_POST['password']);
$re_pass= mysql_escape_string($_POST['re_password']);
插入数据库
insert into users ( username, password) values(\"$username\", \"$pass\")
为什么插入的是原数据而不是转义后的数据,我觉得应该是数据库内部的操作,自动去除了转义符\
。
之所以转义,是为了预防用户进行SQL注入
修改密码
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.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');
}
}
?>
同样对用户输入的数据进行了转义
$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']);
但是注意,这里的username是直接拿过来的,没有进行转义操作!!!
如果对username进行转义了,就不会出现二次注入漏洞了
UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass'
https://blog.csdn.net/hhhhhhhhh85/article/details/121328475
https://blog.csdn.net/weixin_43901998/article/details/107288123