如何保护ODBC查询免受SQL注入

时间:2012-02-16 11:29:32

标签: php sql odbc

保护此查询免受sql注入的最佳方法是什么? 这个例子只是一个例子,我在互联网上阅读了一些文章,但无法理解参数化查询。任何有用文章的链接都会得到投票,但我认为看到这个例子会对我有所帮助。

$id = $_GET["id"];
$connection = odbc_connect("Driver={SQL Server};Server=SERVERNAME;Database=DATABASE-NAME;", "USERNAME", "PASSWORD");
$query = "SELECT id firstname secondname from user where id = $id";
$result = odbc_exec($connection, $query);
while ($data[] = odbc_fetch_array($result));
odbc_close($connection);

谢谢,

编辑:我没有说明显,但我使用的是SQL Server而不是mysql。 这只是一个例子,它并不总是我正在搜索的数字。 如果答案使用参数化查询会很好,因为很多人建议这样做,并且对于所有查询都是相同的,而不是针对不同类型的用户输入的不同类型的验证。

4 个答案:

答案 0 :(得分:3)

我认为PDO objects是最好的。

简而言之,这就是你如何使用它们。

$databaseConnection = new PDO('mysql:host='. $host .';dbname=' . $databaseName, $username, $password);

$sqlCommand = 'SELECT foo FROM bar WHERE baz=:baz_value;';
$parameters = array(
    ':baz_value'    => 'some value'
);

$preparedStatement = $databaseConnection->prepare($sqlCommand);
$preparedStatement->execute($parameters);

while($row = $preparedStatement->fetch(PDO::FETCH_ASSOC))
{
    echo $row['foo'] . '<br />';
}

您为SELECT条件输入的值将替换为以冒号开头的参数(如:field_value)。然后在参数中为参数分配值,这些值将单独传递。

在我看来,这是一种更好的处理SQL查询的方法。

参数与查询分开发送到数据库,并防止SQL注入。

答案 1 :(得分:1)

首先,请注意您在查询中使用的变量,尤其是那些来自外部来源的变量,例如$_GET, $_POST, $_COOKIE and $_FILES。要在查询中使用变量,您应该:

  • 将数字数据转换为整数或浮点数(取决于哪个)
  • 使用适当的转义来逃避其他数据

mysql数据库的一个简单示例:

$id = $_GET["id"];     // contains: OR 1 = 1
$name = $_GET["name"]; // contains: ' OR '' ='
$query = "SELECT * FROM table WHERE id = " . intval($id) . " AND name = '" . mysql_real_escape_string($name) . "'";
// SELECT * FROM table WHERE id = 0 AND name = '\' OR \'\' =\''

对于其他数据库,转义练习会有所不同。但通常你应该用'转义''字符,所以:

$id = $_GET["id"];     // contains: OR 1 = 1
$name = $_GET["name"]; // contains: ' OR '' ='
$query = "SELECT * FROM table WHERE id = " . intval($id) . " AND name = '" . str_replace("'", "''", $name) . "'";
// SELECT * FROM table WHERE id = 0 AND name = ''' OR '''' ='''

话虽如此,也许您可​​能想切换到PDO。它允许您使用prepared statements,PDO驱动程序可以执行所有转义。

答案 2 :(得分:1)

使用准备好的陈述。首先使用odbc_prepare()函数构建一个语句,然后将参数传递给它并使用odbc_execute()执行它。

这比自己逃避字符串更安全,更容易。

Lewis Bassett关于PDO的建议是好的,但可以使用ODBC编写的语句,而无需切换到PDO。

示例代码,未经测试!

try {
  $dbh = new PDO(CONNECTION_DETAILS_GO_HERE);
  $query = 'SELECT id firstname secondname from user where id = :id';
  $stmt = $dbh->prepare($query);
  $stmt->bindParam(':id', $id, PDO::PARAM_STR);
  $result = $stmt->execute();
  $data = $stmt->fetchAll();
} catch (PDOException $e)
  echo 'Problem: ', $e->getMessage;
}

注意:$ e-&gt; getMessage();可能会暴露您不想暴露的内容,因此当您的代码生效时,您可能希望在该行上执行不同的操作。它虽然可用于调试。

编辑:不确定您是否需要PDO或ODBC示例,但两者基本相同。

编辑:如果你对我不以为然,请发表评论并告诉我原因。

答案 3 :(得分:0)

mysql变体附带了一个名为mysql_real_escape_string的方法,该方法适用于所针对的SQL版本。你能做的最好的事情是编写一个方法来逃避Id。重要的是你的转义方法适用于目标数据库。您还可以执行基本类型检查,如is_numeric,数字输入将立即拒绝SQL字符串注入。

参见How to escape strings in SQL Server using PHP? 并按照一些相关链接获取明确的例子