二次注入
二次注入原理
- 二次注入的原理:在第一次进行数据库插入数据的时候,仅仅只是使用了
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丶!