二次注入
二次注入原理
- 二次注入的原理:在第一次进行数据库插入数据的时候,仅仅只是使用了 addslashes或者是借助mysqli_real_escape_string对其中的特殊字符进行了转义,但是addslashes有一个特点就是虽然参数在过滤后会添加\进行转义,但是\并不会插入到数据库中,在写入数据库的时候还是保留了原来的数据。
- 如下代码所示:
| 1 | 
 | 
- 在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次进行需要进行查询的时候,直接从数据库中取出了脏数据,没有进行下一步的检验和处理,这样就会造成 SQL的二次注入。
源码分析
- 一个经典的二次注入场景,所以下面来理一下源码(SQLi_lab24):
index.php
- 主要记录了表单相关的信息,没有啥敏感代码,当做 index.html来看待就可以了,具体的界面如下:

- 提示输入用户名和密码,用户名和密码正确之后就可以成功登陆,否则登陆失败。 
- 下面两个链接分别是: - Forgot your password?:跳转到- forgot_password.php,简单的一张图,没啥用。
- New User click here?:跳转到- new_user.php,可以创建一个新用户。
 
failed.php
- 检测会话,如果 Cookie里面没有Auth参数的话,就跳转到index.php。
- 密码重置失败后,跳转到此。
forgot_password.php
- 没啥用,过。
Logged-in.php
- 登录成功界面,可以进行密码重置,具体的界面如下:

new_user.php
- 创建新用户界面,本文件主要存放前段代码当作静态页面看就行,具体的界面如下:

login_create.php
- 创建新用户的后端代码,下面来简单理一下代码的流程:
| 1 | # 判断是否有参数提交 | 
login.php
- 登录用户名和密码都被过滤了:
| 1 | $username = mysql_real_escape_string($_POST["login_user"]); | 
pass_change.php
- 分析一下代码:
| 1 | if 检测未登录: | 
思路分析
- 先查看创建用户的地方:
| 1 | username = mysql_escape_string($_POST['username']) ; | 
- $_POST['username']被- mysql_escape_string函数转义了。
- 再看下更新密码的核心语句:
| 1 | UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' | 
- 这里直接使用单引号拼接了 $username所以当$username可控的话 ,这里是存在SQL注入的,假设用户注册的username的值为:admin'#,那么此时的完整语句就为:
| 1 | UPDATE users SET PASSWORD='$pass' where username='admin'# and password='$curr_pass' | 
- 此时就完全改变了语义,直接就修改掉了 admin用户的密码。
- 回头看看 pass_change.php文件,发现$username取值来自$_SESSION["username"],而这个值取自login.php的$_SESSION["username"] = $login,是从数据库中查出来的,有苗头。
步骤演示
- 注册一个admin'#的用户,注册完成后数据库的记录信息如下:
| 1 | select * from security.users; | 
- 成功添加了记录,虽然之前被转义了但转义不过是暂时的,最后存入到数据库的时候还是没变的。
- 接下来登录 admin'#用户,然后修改当前的密码:

- 此时来数据库中查看,可以发现成功修改掉了 admin用的密码了:
| 1 | select * from security.users; | 
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Yongz丶!









