二次注入详解

0x01 前言

前几天看一些面经的时候,看到sql注入的二次注入,当时没一下子反应过来,好家伙,赶紧再次去那个靶场sqli-labs/Less24复现一下二次注入。

0x02 什么是二次注入?

二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。防御者即使对用户输入的恶意数据进行转义,当数据插入到数据库中时被处理的数据又被还原,Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入。

也就是说一次攻击造成不了什么,但是两次配合起来就会早成注入漏洞。

0x03 注入条件

两次注入分别是插入恶意数据利用恶意数据

所以也就是满足这两个条件即可

  • 用户向数据库插入恶意数据,即使后端对语句做了转义,如mysql_escape_string、mysql_real_escape_string等函数
  • 数据库能够将恶意数据取出

0x04 靶场实例

首先进入靶场,可以看到与其他靶场不同,这里多了忘记密码和注册密码选项

img

尝试常规post注入,未果。

image-20220409195347007

这里看到后端源码会发现使用了转义函数mysql_real_escape_string,常规SQL注入流程无法走了

既然可以注册账户那就去注册一下,这里直接注册admin'#

image-20220409200822312

用注册的账号登录进去后发现可以修改密码

image-20220409201032225

修改密码这个模块也可以利用,我们不妨想一下修改密码后端实现的逻辑,使用的肯定是sql增删改查中的改语句,于是猜想对应sql语句可能会是这样

update users set password='$new_pass' where username='$user' and password='$old_pass';

(当然闭合方式不一定就是单引号,这里需要碰运气吧。。)

如果我们注册一个这样的账号 admin'# 上述sql语句就变成这样

update users set password='$new_pass' where username='admin'# and password='$old_pass';

显而易见,语句原义被破坏,本来修改的是admin'# 用户的账号和密码,现在却是变成了直接修改admin用户的密码!

那就随便输入个密码123456修改后再拿它去尝试登录admin账户,发现成功登入。

image-20220409201506816

image-20220409201550144

image-20220409201620226

说明数据库中admin用户的密码已经被成功改为123456

0x05 如何防御二次注入?

  • 对输入一视同仁,无论输入来自用户还是存储,在进入到 SQL 查询前都对其进行过滤、转义。
  • 使用MySQLi参数化更新,事先编译的PHP代码能够带来高效的防护效果
posted @ 2022-04-09 22:28  jackie_le  阅读(1844)  评论(0编辑  收藏  举报