二次注入是指攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中,当Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入
观察页面,是一个登陆框,考虑是否存在POST型注入,参考MYSQL POST 型注入
经测试之后,账号密码处都不存在注入点;忘记密码点击之后没有响应,点击新建用户之后,可以看到新建用户,并会存在数据库中,此过程会触发post请求,执行SQL Insert请求,添加一个正确的用户尝试登陆
登陆之后的界面,发现需要修改密码,则这里会有一个update修改操作
结合所有的操作来看,那么如果构造存在危害的字段插入到数据库,那么在修改密码处可能触发二次注入
创建用户的时候,mysql_escape_string()
将'
,#
之类的转义了,所以导致没有办法注入;
创建用户执行Insert操作
$username= mysql_escape_string($_POST['username']) ;
$pass= mysql_escape_string($_POST['password']);
$re_pass= mysql_escape_string($_POST['re_password']);
echo "";
$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>;
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_escape_string()
函数将用户名和密码做了处理,所以在最开始是测试是否存在POST注入,是没有办法闭合单引号;当数据库存在该用户,则登录进入logged-in.php
登录执行Select操作
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;
}
}
$login = sqllogin();
if (!$login== 0)
{
$_SESSION["username"] = $login;
setcookie("Auth", 1, time()+3600); /* expire in 15 Minutes */
header('Location: logged-in.php');
}
可以发现,$username= $_SESSION["username"];
此代码是关键,username
是从session
中取,并且,在登录的时候可以发现,登录成功之后,$_SESSION["username"] = $login;
$_session["username"]
是直接存,直接取的
修改密码执行SQL Update
操作
session_start();
if (!isset($_COOKIE["Auth"]))
{
if (!isset($_SESSION["username"]))
{
header('Location: index.php');
}
header('Location: index.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' ";
}
}
?>
通过分析,以及查看关键代码,想想是否可以二次注入?二次注入主要是将有危害的语句写入数据库,那么能写入的页面则是执行创建用户,insert数据库,执行恶意SQL语句的页面则是在更新密码的时候
// Insert
$username= mysql_escape_string($_POST['username']) ;
$pass= mysql_escape_string($_POST['password']);
$sql = "insert into users ( username, password) values(\"$username\", \"$pass\")";
// Update
$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']);
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
观察除了Update中username处没有使用mysql_escape_string()
函数处理过,那么可以在此处做文章
and password= '$curr_pass'
(正确密码))猜测该表里有admin用户,且admin为管理员
那么由于在insert的时候,通过mysql_escape_string()
函数转义了特殊字符并没有删除特殊字符,update更新表的时候,直接从session里取用户名,那么可以构造用户名为admin'#
,那么带入SQL更新则是
UPDATE users SET PASSWORD='$pass' where username='admin'# and password='$curr_pass' ";
无论正确密码是多少,都可以更改admin用户的密码
在insert中插入报错语句updatexml
或者extractValue
可以看到表中,username字段是有长度限制的,所以报错注入行不通,就更别说盲注了