简单的来说,就是第一次注入时,开发者进行了编码等限制,无法直接进行注入,但是在数据库中保留了我们注入的语句,程序在其它地方再次调用保存着我们注入的语句时发生了注入,这就是二阶注入,有点类似存储型XSS漏洞的意思。
text数据库里有张users表,目前里面已有admin和root账户
-
-
<html lang="en">
-
<head>
-
<meta charset="UTF-8">
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
-
<meta http-equiv="X-UA-Compatible" content="ie=edge">
-
<title>用户注册
title>
-
head>
-
-
function check($str){
-
$str1=str_replace(
"'",
"''",$str);
-
$str1=str_replace(
'"',
'""',$str1);
-
return $str1;
-
}
-
if(
isset($_POST[
'submit'])){
-
$username=check($_POST[
'username']);
-
$passwd=check($_POST[
'passwd']);
-
$email=check($_POST[
'email']);
-
$mysqli=
new mysqli();
-
$mysqli->connect(
'localhost',
'root',
'root');
-
if($mysqli->connect_errno){
-
die(
'数据库连接失败:'.$mysqli->connect_error);
-
}
-
$mysqli->select_db(
'text');
-
if($mysqli->errno){
-
die(
'打开数据库失败:'.$mysqli->error);
-
}
-
$mysqli->set_charset(
'utf-8');
-
$sql=
"SELECT * FROM users WHERE username='{$username}'";
-
$sl=$mysqli->query($sql);
-
if(!$sl){
-
die(
'SQL语句执行错误:'.$mysqli->error);
-
}
else
if($sl->num_rows>
0){
-
$sl->free();
-
$mysqli->close();
-
die(
'该用户已被注册,请使用其它账户');
-
}
else {
-
$sql=
"INSERT INTO users VALUES(NULL,'{$username}',md5('{$passwd}'),'{$email}')";
-
echo
'SQL执行语句'.$sql.
'
';
-
$sl=$mysqli->query($sql);
-
if(!$sl){
-
die(
'SQL语句执行错误:'.$mysqli->error);
-
}
else {
-
die(
"恭喜你注册{$username}成功!");
-
}
-
}
-
$sl->free();
-
$mysqli->close();
-
}
-
?>
-
<body>
-
<h1>用户注册
h1>
-
<form action="" method="post">
-
用户名:
<input type="text" name="username">
<br />
-
密码:
<input type="password" name="passwd">
<br />
-
邮箱:
<input type="text" name="email">
<br />
-
<input type="submit" name="submit" value="注册">
-
form>
-
body>
-
html>
-
-
<html lang="en">
-
<head>
-
<meta charset="UTF-8">
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
-
<meta http-equiv="X-UA-Compatible" content="ie=edge">
-
<title>修改用户密码
title>
-
head>
-
-
if(
isset($_POST[
'submit'])){
-
$username=$_POST[
'username'];
-
$passwd=$_POST[
'passwd'];
-
$newpasswd=$_POST[
'newpasswd'];
-
$mysqli=
new mysqli();
-
$mysqli->connect(
'localhost',
'root',
'root');
-
if($mysqli->connect_errno){
-
die(
'数据库连接失败:'.$mysqli->connect_error);
-
}
-
$mysqli->select_db(
'text');
-
if($mysqli->errno){
-
die(
'打开数据库失败:'.$mysqli->error);
-
}
-
$mysqli->set_charset(
'utf-8');
-
$sql=
"SELECT * FROM users WHERE username='{$username}' AND passwd=md5('{$passwd}')";
-
$sl=$mysqli->query($sql);
-
if(!$sl){
-
die(
'SQL语句执行错误:'.$mysqli->error);
-
}
else
if($sl->num_rows==
0){
-
$sl->free();
-
$mysqli->close();
-
die(
'修改密码失败,用户或原密码错误');
-
}
else {
-
$sql=
"UPDATE users SET passwd=md5('{$newpasswd}') WHERE username='{$username}'";
-
$sl=$mysqli->query($sql);
-
if(!$sl){
-
die(
'SQL语句执行错误:'.$mysqli->error);
-
}
else{
-
die(
'修改密码成功!');
-
}
-
}
-
$sl->free();
-
$mysqli->close();
-
}
-
?>
-
<body>
-
<h1>用户密码修改
h1>
-
<form action="" method="post">
-
用户名:
<input type="text" name="username">
<br />
-
原密码:
<input type="password" name="passwd">
<br />
-
新密码:
<input type="password" name="newpasswd">
<br />
-
<input type="submit" name="submit" value="修改">
-
form>
-
body>
-
html>
首先用户注册页面,对用户提交的数据进行了check()函数过滤,对单引号和双引号进行了闭合,故无法闭合SQL语句。
如:id=1' => id=1''
这里很明显,无法直接一阶注入,但用户修改密码页面对这个表中的数据没有过滤或限制就调用了(开发人员相信数据库中数据),那么此时就存在二阶注入。
首先注册一个用户名为:admin'#的用户,经过check函数就变成了admin''#,此时就无法直接注入。
在数据库中,已插入一个用户名为admin'#的用户
然后在用户修改密码界面中,输入admin'#用户和相应的密码
此时,修改密码的SQL为:
-
UPDATE
users
SET passwd=
md5(
'123123')
WHERE username=
'admin'#
';
-
=
-
UPDATE users SET passwd=md5('
123123
') WHERE username='
admin
';
此时,查看数据中记录,发现是admin用户的密码被修改了。