在动态SQL中防止SQL注入

时间:2014-05-09 11:27:51

标签: php mysql sql sql-injection

我被迫生成动态SQL。我意识到这样做非常复杂,下面的例子很愚蠢,显然不需要动态SQL,只是用来说明这个问题。

转义用户提供的数据是不够的,下面脚本中的第3个查询可能是SQL注入。

我发现设计应用程序通常最容易,因此所有用户输入都是整数,只需使用(int)$_POST['user_input']对其输入进行类型转换。

我现在需要user_input需要是text。我该怎么做才能防止SQL注入?一个选项是PHP的ctype_alpha(),但是,我不希望“用户,输入”结果为FALSE,但应保持原样或转换为“userinput”(或者scenerio对我来说没问题)。我在想$user_input= preg_replace('/[^a-z0-9,]/i', '', $_POST['user_input']);之类的东西。这是100%安全吗?

修改

请注意,我没有执行以下查询,而是将其插入到数据库中,因此,准备好的语句不适用。您可能认为永远不应该使用动态SQL生成,但告诉我使用预准备语句是不对的。

<?php
$id=123;
$query='SELECT * FROM someTable WHERE someColumn="'.$_POST['user_input'].'"';
$sql='INSERT INTO meta_table (id,sql) VALUES (?,?)';
$stmt=db::db()->prepare($sql);
$stmt->execute(array($id,$query));

$sql='SELECT sql FROM meta_table WHERE id=123';
$stmt = db::db()->exec($sql);
$query=$stmt->fetchColumn();

$stmt = db::db()->exec($query); //Prone to SQL Injection
$rs=$stmt->fetchColumn();
?>

1 个答案:

答案 0 :(得分:4)

啊哈哈,这太棒了! 最后,我设法理解这个家伙在他的动态sql&#34;中意味着什么。难怪它在第一眼和第二眼就完全伪装成普通的SQL!

以下是答案:

不要这样做。如初。

你的想法&#34;动态&#34; SQL本质上是错误的。没有人这样做。

我不知道你的特定任务,但你的解决方案显然是错误。并且肯定有一种理智的方式来做到这一点。只需遵循以下简单规则:

  • 摆脱meta_table
  • 摆脱存储在数据库中的SQL查询
  • 仅从两个来源在您的应用程序中编写(或构建)所有查询:
    • 硬编码的SQL,预先写入您的代码
    • 为所有可变部分准备好的陈述

让您的所有SQL完全安全