准备好的语句:它们可以处理参数化表名称吗?
本文解决了预处理语句是否可以有效处理参数化表名以防止 SQL 注入漏洞的关键问题。
问题:
直接将用户提供的数据(包括表名)嵌入到 SQL 查询中是一个主要的安全风险。 考虑这个例子:
<code class="language-php">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(); }</code>
如果 .$new_table.
未正确清理,串联 $new_table
会使该函数容易受到 SQL 注入的攻击。
尝试参数化:
缓解此问题的常见尝试是尝试参数化表名称:
<code class="language-php">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(); }</code>
现实:
不幸的是,这种方法失败了。 准备好的语句旨在防止运行时值注入,而不是防止更改SQL查询本身的结构。 数据库解析器将表名解释为查询结构的一部分,而不是运行时参数。 用占位符替换它会导致无效的 SQL。
即使系统提供预准备语句模拟(例如 PDO),结果也将是无效查询(例如, 而不是 SELECT * FROM 'mytable'
)。SELECT * FROM mytable
解决方案:
处理用户提供的表名时防止 SQL 注入的唯一可靠方法是采用严格的白名单。 这涉及预先定义允许的表名列表,并确保在查询中使用之前对照此白名单检查任何用户提供的表名。 切勿直接使用用户输入来构造涉及表名的 SQL 查询。
以上是准备好的语句可以处理参数化表名以防止 SQL 注入吗?的详细内容。更多信息请关注PHP中文网其他相关文章!