MySQL二次注入原理与实战分析

SQL二次注入也有人称它为SQL二阶注入。

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

 

一、什么是SQL二次注入?

简单的说,二次注入是指已存储(数据库、文件)的用户输入被读取后再次进入到 SQL 查询语句中导致的注入。

网站对我们输入的一些重要的关键字进行了转义,但是这些我们构造的语句已经写进了数据库,可以在没有被转义的地方使用

可能每一次注入都不构成漏洞,但是如果一起用就可能造成注入。

 

普通注入与二次注入的区别:

 

普通注入:

  • 在http后面构造语句,是立即直接生效的
  • 一次注入很容易被扫描工具扫描到

 

二次注入:

  • 先构造语句(有被转义字符的语句)
  • 我们构造的恶意语句存入数据库
  • 第二次构造语句(结合前面已经存入数据库的语句,成功。因为系统没有对已经存入数据库的数据做检查)
  • 二次注入更加难以被发现

 

二、SQL 二次注入原理

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

 

二次注入,可以概括为以下两步:

第一步:插入恶意数据

进行数据库插入数据时,对其中的特殊字符进行了转义处理,在写入数据库的时候又保留了原来的数据。

 

第二步:引用恶意数据

开发者默认存入数据库的数据都是安全的,在进行查询时,直接从数据库中取出恶意数据,没有进行进一步的检验的处理。

 

二次注入漏洞原理示意图

三、MYSQL二次注入实战

这里我们使用php+mysql搭建的源码 “ sqli-labs/Less24”为例,进行二次注入方法的练习。

 

1、打开页面可以看到一个登陆界面,尝试用 admin'# 进行注入,失败。

SQL二次注入

 

部分源代码如下:

$username = mysql_real_escape_string($_POST["login_user"]);
$password = mysql_real_escape_string($_POST["login_password"]);
$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";

可以看到使用了 mysql_real_escape_string 进行转义处理,无法进行SQL注入。

 

2、继续研究,发现登陆页面可以进行用户注册,这里我们注册一个 admin'# 的账号,登陆该账号后可以进行密码修改。SQL二次注入

 

注册新用户的源代码如下:

if (isset($_POST['submit']))
{
    $username=  mysql_escape_string($_POST['username']) ;
    $pass= mysql_escape_string($_POST['password']);
    $re_pass= mysql_escape_string($_POST['re_password']);
    
    echo "<font size='3' color='#FFFF00'>";
    $sql = "select count(*) from users where username='$username'";
    $res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');
    $row = mysql_fetch_row($res);
    
    //print_r($row);
    if (!$row[0]== 0) 
        {
        ?>
        <script>alert("The username Already exists, Please choose a different username ")</script>;
        <?php
        header('refresh:1, url=new_user.php');
        } 
        else 
        {
            if ($pass==$re_pass)
            {
                # Building up the query........
                
                $sql = "insert into users ( username, password) values(\"$username\", \"$pass\")";
                mysql_query($sql) or die('Error Creating your user account,  : '.mysql_error());
                    echo "</br>";

              ··················

可以看到传入的 username、password、re_password 仍均被 mysql_escape_string 进行了转义处理,但是在数据库中还是插入了 admin'#

SQL二次注入

 

这是因为当数据写入到数据库的时候反斜杠会被移除,所以写入到数据库的内容就是原始数据,并不会在前面多了反斜杠。

 

3、这时,我们用 admin'# 登陆,并进行密码修改,密码修改为`123456`

SQL二次注入

 

执行后,查看数据库数据:

SQL二次注入

 

可以看到 admin 的密码由原来的 123 修改为 123456

$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
这是因为上面的数据库更新语句,在用户名为 "admin'#" 时执行的实际是:
$sql = "UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass' ";

 

因为我们将问题数据存储到了数据库,而程序再取数据库中的数据的时候没有进行二次判断便直接带入到代码中,从而造成了二次注入。

付杰
  • ¥ 498.0元
  • 市场价:998.0元
  • ¥ 129.0元
  • ¥ 298.0元
  • 市场价:899.0元
  • ¥ 1980.0元
  • 市场价:2980.0元

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: