目录
一,二次注入
1.二次注入原理
2.二次注入代码分析
3.二次注入案例演示
二,堆叠注入
1.堆叠注入原理
2.堆叠注入条件
3.堆叠注入案例演示
二次注入主要分为两步
第一步:插入恶意数据:第一次进行数据库数据插入的时候,仅仅对其中的特殊字符进行了转义,在写入数据库的时候还是保留了原来的数据,但是数据本身包含恶意内容。
第二步:引用恶意数据:在将数据存入到数据库中之后,开发者就认为数据是可信的 ,在下一次需要进行查询的时候,直接从数据库中取出了恶意数据,没有进行进一步的检查和处理,这样就会造成SQL的第二次注入。
二次注入原理图
假设一个真实环境进行理解:
例如我们通常熟悉的找回密码功能,找回密码是用户输入对应的用户名,然后经过验证(例如手机验证码),验证成功就可以修改密码了。用户验证成功后,后台是不是就要根据用户输入 的用户名找到对应的用户,然后用UPDATE语句对密码进行更新。现在我们假设用户注册的时候,用户名输入的是一条SQL注入的语句,那么在用户更改密码的时候就造成了SQL注入,修改密码的sql语句:update user set password='123456' where username='SQL注入代码' ,简单来说就是先将SQL注入语句存入到数据库,然后再次使用数据的时候触发SQL注入
二次注入中1.php页面的代码如下所示,实现了简单的用户注册功能,程序获取到GET参数usemame和参数password,然后将usermame和password拼接到SQL语句,使用insert语句插入数据库中。由于参数usermame使用addslashes进行转义(转义了单引号,导致单引号无法闭合),参数password进行了MDS哈希,所以此处不存在SQL注入漏洞。
当访问username=test'&password=123456时,执行的SQL语句为:insert into users('username','password') values ('test\'','e10adc3949ba59abbe56e057f20f883e')
在二次注入中,2.php中的代码如下所示,首先将GET参数ID转成int类型(防止
拼接到SQL语句时,存在SQL注入漏洞),然后到users表中获取ID对应的username,
接着到person表中查询username对应的数据。
此处没有对$username进行转义,在第一步中我们注册的用户是test',此时执行的SQL语句为:select * from person where 'username'='test'',单引号被带入到SQL语句中,由于多了一个单引号,所以页面会报错。
sql-labs第24关
先注册一个用户,用户名为admin'#,密码为123456
然后登入
由于注册登入的时候对数据进行了转义所以会把实际输入的值加入带SQL语句中
登入admin'#后就可以修改密码,修改密码之前admin'#的密码为123456,admin的密码为123
修改成功后我们发现admin'#的密码并没有进行修改,反而admin的密码被修改了
这是什么原因呢,我们看看源码,源码中,在修改用户密码时,并没有对获取的用户名进行转义
实际的SQL语句是这样的 :UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='123'
mysql数据库sql语句的默认结束符是以";"号结尾,在执行多条sql语句时就要使用结束符隔 开,而堆叠注入其实就是通过结束符来执行多条sql语句
堆叠注入触发的条件很苛刻,因为堆叠注入原理就是通过结束符同时执行多条sql语句,这就需要服 务器在访问数据端时使用的是可同时执行多条sql语句的方法,比如php中mysqli_multi_query()
函数,这个函数在支持同时执行多条sql语句,而与之对应的mysqli_query()
函数一次只能执行一条sql语句,所以要想目标存在堆叠注入,在目标主机没有对堆叠注入进行黑名单过滤的情况下必须存在类似于mysqli_multi_query()
这样的函数,简单总结下来就是 1. 目标存在sql注入漏洞 2. 目标未对";"号进行过滤 3. 目标中间层查询数据库信息时可同时执行多条sql语句
sql-labs第38关源码:
Less-38 **stacked Query**
Welcome Dhakkan
';
printf("Your Username is : %s", $row[1]);
echo "
";
printf("Your Password is : %s", $row[2]);
echo "
";
echo "";
}
// mysqli_free_result($result);
}
/* print divider */
if (mysqli_more_results($con1))
{
//printf("-----------------\n");
}
//while (mysqli_next_result($con1));
}
else
{
echo '';
print_r(mysqli_error($con1));
echo "";
}
/* close connection */
mysqli_close($con1);
}
else { echo "Please input the ID as parameter with numeric value";}
?>
sql-labs第38关
简单测试发现是字符型union注入
这里巩固一下之前学的手工union注入获取当前表名
测列数:?id=1' order by 4 --+
测显位:?id=1' and 1=2 union select 1,2,3 --+
获取当前数据库名:?id=1' and 1=2 union select 1,database(),3 --+
获取表名:?id=1' and 1=2 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security' --+ //emails,referers,uagents,users
于是尝试堆叠注入将id为1的用户密码改成123,可以配合联合查询来判断sql是否执行
1' union select 1,2,3;update users set password=123 where id=1--+
然后再次查询id为1的用户时发现password信息已经被成功执行,说明目标存在堆叠注入,如果目标没有限制执行的sql语句,那就可以随心所欲的执行你想要执行的sql语句了!