二次注入

二次注入漏洞是一种在Web应用程序中广泛存在的安全漏洞形式。相对于一次注入漏洞而言,二次注入漏洞更难以被发现,但是它却具有与一次注入攻击漏洞相同的攻击威力。

什么是二次注入?

简单的说,二次注入是指已存储(数据库、文件)的用户输入被读取后再次进入到 SQL 查询语句中导致的注入。
网站对我们输入的一些重要的关键字进行了转义,但是这些我们构造的语句已经写进了数据库,可以在没有被转义的地方使用
可能每一次注入都不构成漏洞,但是如果一起用就可能造成注入。

普通注入与二次注入:

普通注入  (1)在http后面构造语句,是立即直接生效的

                (2)一次注入很容易被扫描工具扫描到



二次注入   (1) 先构造语句(有被转义字符的语句)

                (2)我们构造的恶意语句存入数据库

                (3)第二次构造语句(结合前面已经存入数据库的语句,成功。因为系统没有对已经存入数据库的数据做检查)

                (4)二次注入更加难以被发现

二次注入的原理:

二次注入的原理,在第一次进行数据库插入数据的时候,仅仅只是使用了 addslashes 或者是借助 get_magic_quotes_gpc 对其中的特殊字符进行了转义,在写入数据库的时候还是保留了原来的数据,但是数据本身还是脏数据。

在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次进行需要进行查询的时候,直接从数据库中取出了脏数据,没有进行进一步的检验和处理,这样就会造成SQL的二次注入。比如在第一次插入数据的时候,数据中带有单引号,直接插入到了数据库中;然后在下一次使用中在拼凑的过程中,就形成了二次注入。

由“强网杯”的three hit聊聊二次注入

二次注入原理案列详解:

假如有一个网站管理员的用户名为:root 密码为:123456789 ,攻击者注册了一个账号 : root'-- 密码为:123因为账号当中有特殊字符,网站对于特殊字符进行了转义,一次注入在这就行不通了。虽然账号被转义了,但是他在数据库当中任然是以 root'-- 的方式被储存的。现在攻击者开始实施正真的攻击了,他开始对账号修改密码。普通网站修改密码的过程为:先判断用户是否存在------》确认用户以前的密码是否正确--------》获取要修改的密码---------》修改密码成功。 在数据库中 -- 表示注释的意思,后面的语句不会执行,而root后面的那个单引号又与前面的 ' 闭合,而原本后面的那个单引号因为是在 -- 之后,所以就被注释掉了,所以他修改的其实是 root 的密码。
下面就是一个例子
实例:
sqli-labs24
本关为二次排序注入的示范例。二次排序注入也成为存储型的注入,就是将可能导致sql注入的字符先存入到数据库中,当再次调用这个恶意构造的字符时,就可以出发sql注入。二次排序注入思路:

  1. 黑客通过构造数据的形式,在浏览器或者其他软件中提交HTTP数据报文请求到服务端进行处理,提交的数据报文请求中可能包含了黑客构造的SQL语句或者命令。

  2. 服务端应用程序会将黑客提交的数据信息进行存储,通常是保存在数据库中,保存的数据信息的主要作用是为应用程序执行其他功能提供原始输入数据并对客户端请求做出响应。

  3. 黑客向服务端发送第二个与第一次不相同的请求数据信息。

  4. 服务端接收到黑客提交的第二个请求信息后,为了处理该请求,服务端会查询数据库中已经存储的数据信息并处理,从而导致黑客在第一次请求中构造的SQL语句或者命令在服务端环境中执行。

  5. 服务端返回执行的处理结果数据信息,黑客可以通过返回的结果数据信息判断二次注入漏洞利用是否成功。

此例子中我们的步骤是注册一个admin'#的账号,接下来登录该帐号后进行修改密码。此时修改的就是admin的密码。

Sql语句变为UPDATE users SET passwd="New_Pass" WHERE username =' admin' # ' AND password=' ,也就是执行了UPDATE users SET passwd="New_Pass" WHERE username =' admin'
1.注册admin'#账号

image

2.注意此时的数据库中出现了admin'#的用户,同时admin的密码为admin

image

3.登录admin'#,并修改密码

image

4.这时并没有修改admin'#的密码,而是修改了admin的密码。原理上面已经提过

简单的二次注入案例

测试代码1:
sql2.php



 
   
     
     <?php echo $date['title']."啦啦啦啦啦啦"?>
   
   
      


作者:
时间:
概述:
正文:

测试代码2
sql22.php

  
 
   
     
     sql22
   
   
      
主题title:
作者author:
概述description:
正文content:
" . mysqli_error($conn); } echo $insert; mysqli_query($conn,"set names utf8"); //设置编码 if($result=mysqli_query($conn,$insert)){ $num=mysqli_affected_rows($conn); echo $num;} } else {echo '插入失败';} ?>

代码1是显示页面,显示各个数据,代码2是添加页面,进行数据添加。
首先我们简单分析分析一下这两段代码。
测试代码1是一个内容显示页面,通过传入的id在数据库进行查询,然后在页面调用输出,我们可以看到传递的参数id并没有经过过滤,可以成为一个典型的字符串GET注入,但是我们今天要讨论的是二次注入,暂时不考虑这个注入。
测试代码2是一个添加页面,通过表单POST的数据执行INSERT语句插入数据,成功后返回数据库影响行数,而且这里的每一个参数都用addslashes函数进行了转义。
两段代码结合,我们可以发现一个典型的二次注入点,虽然文章添加页面中过滤的非常严格,但是addslashes有一个特点就是虽然参数在过滤后会添加 “\” 进行转义,但是“\”并不会插入到数据库中,再配合内容显示页面中的查询是通过id查询的,所以我们就可以利用这个构造一个二次注入。
在之前先看一下正常显示页面


图片.png

然后我们插入一条注入语句

添加post数据
id=0' union select 1,version(),database(),user(),4'
&author=111
&content=xxx

图片.png

可看到添加的id为sql注入语句,结果显示添加成功,可以看到图片中的结果是已经被转义,也意味着此语句没有任何作用,但已经被添加到数据库中,且储存在数据库中的值是不含转义字符的也就是原来post提交的数据
我们去数据库看一下


图片.png

确实数据库里的并没有转义,说明第一次构造成功了。
这时我们再回到显示页面查参数id,因为我们将注入语句通过id参数插入到数据库tilte列中。
查询 id=0' union select 1,version(),database(),user(),4'

图片.png

数据库用户,名字,版本都出来了

例子很简单,也很垃圾,意思大概就是这个意思。
二次注入防范方法:
解决SQL注入最推荐的方法还是预处理+数据绑定。
另一个防御的点就是 对输入一视同仁,无论输入来自用户还是存储,在进入到 SQL 查询前都对其进行过滤、转义。
对于二次注入这种小众的漏洞,一般没有专门针对的方案,只能从流程上进行优化,例如做代码审查的时候禁止开发用拼接的方式执行sql。
总结一下二次注入的精髓就是,第一次构造的语句只是为了第二次构造做的铺垫,第二次才是正真的攻击。

你可能感兴趣的:(二次注入)