首页 > 数据库 > mysql教程 > 如何在准备语句中安全地使用参数化表名来防止 SQL 注入?

如何在准备语句中安全地使用参数化表名来防止 SQL 注入?

Mary-Kate Olsen
发布: 2025-01-23 18:08:10
原创
325 人浏览过

How Can We Securely Use Parameterized Table Names in Prepared Statements to Prevent SQL Injection?

准备好的语句中的参数化表名:一个困境

尽管 mysqli_stmt_bind_param 已被证明可以有效防止 SQL 注入,但当变量影响时,它会遇到限制涉及到表名。如提供的代码片段所示:

function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol )
{
    $statement = $mysqli->prepare("INSERT INTO " .$new_table . " VALUES (?,?,?,?,?,?,?);");
    mysqli_stmt_bind_param( $statment, 'sssisss', $Partner, $Merchant, $ips, $score, $category, $overall, $protocol );
    $statement->execute();
}
登录后复制

$new_table 的有问题的串联引入了 SQL 注入漏洞。尝试用另一个占位符替换它,如以下代码片段所示,失败:

function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol )
{    
    $statement = $mysqli->prepare("INSERT INTO (?) VALUES (?,?,?,?,?,?,?);");
    mysqli_stmt_bind_param( $statment, 'ssssisss', $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol );
    $statement->execute();
}
登录后复制

准备语句的局限性

核心问题在于无法准备好的语句来保护定义 SQL 语句结构的参数,例如表名。这是因为准备好的语句只允许参数值不改变语句的含义。由于表名决定了 SQL 语句的有效性,因此在执行期间修改它们可能会使其无效。

即使使用像 PDO 这样的数据库接口,通过在将参数发送到数据库之前替换参数来模拟准备好的语句,占位符值仍然是SQL 语句中包含的字符串。结果,SELECT FROM ?使用 mytable 作为参数最终会将 SELECT FROM 'mytable' 发送到数据库,使其无效。

降低风险

最安全的方法仍然是在字符串中使用 $mytable,但它必须附带一个用于检查用户输入的表白名单。这可以防止恶意行为者在任意表上执行 SQL 语句。因此,以下代码演示了安全实现:

if (whitelisted_tables($mytable)) {
    $statement = $mysqli->prepare("INSERT INTO $mytable VALUES (?,?,?,?,?,?,?);");
    mysqli_stmt_bind_param( $statment, 'sssisss', $Partner, $Merchant, $ips, $score, $category, $overall, $protocol );
    $statement->execute();
}
登录后复制

以上是如何在准备语句中安全地使用参数化表名来防止 SQL 注入?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板