首页 文章

pg_prepare()预处理语句(不是PDO)是否会阻止SQL注入?

提问于
浏览
3

PDO ist not supported in target system I'm working on 虽然我在 PostGres-DB 8.2+ 上使用 PHP 5.1.x 寻求防止SQL注入的解决方案 . 目前 no 有机会切换到PDO .

我现在的解决方案是pg_prepare-prepared声明:

// Trying to prevent SQL-Injection
$query = 'SELECT * FROM user WHERE login=$1 and password=md5($2)';
$result = pg_prepare($dbconn, "", $query);
$result = pg_execute($dbconn, "", array($_POST["user"], $_POST["password"]));
if (pg_num_rows($result) < 1) {
  die ("failure");
}

But pg_prepare-documentation lacks about an important information:

it tells about "later usage"

pg_prepare()创建一个准备好的语句,以便稍后使用pg_execute()或pg_send_execute()执行 . [...]

it tells about "named/anonymous statements"

该函数从查询字符串创建名为stmtname的预准备语句,该语句必须包含单个SQL命令 . stmtname可能是“”来创建一个未命名的语句,在这种情况下,任何预先存在的未命名语句都会自动替换; [...]

it tells about "typecasting"

也可以通过执行SQL PREPARE语句来创建与pg_prepare()一起使用的预准备语句 . (但是pg_prepare()更灵活,因为它不需要预先指定参数类型 . )此外,尽管没有用于删除预准备语句的PHP函数,但SQL DEALLOCATE语句可用于此目的 .

but it does not tell, if this implementation of prepared statements is safe from SQL-injection

*此安全问题的几乎所有注释都涉及PDO解决方案,其中在文档中注意到驱动程序阻止了SQL注入 . 但如果一个简单的解决方案可能是pg_prepare,我现在会使用pg_prepare . *

感谢您提供最佳实践解决方案的重要信息 .

EDIT (after marked as solution): 感谢非常有启发性的答案!

  • 我将Frank Heikens的解决方案标记为最佳答案,因为它解释了SQL注入中的一个重要点 . 程序员可能会使用准备好的状态,但SQL注入缺乏可能仍然存在错误!

  • 除了Frank Heikens的回答,hoppa显示使用pg_prepare / pg_query_params阻止了SQL注入 . 谢谢 .

  • 现在将使用 pg_query_params 的优化代码(感谢Milen A. Radev)

  • pg_escape_string() 作为替代方案(感谢halfer)

所有答案都很有帮助:)

// Trying to prevent SQL-Injection (**updated**)
$sql_query = 'SELECT * FROM user WHERE login=$1 and password=md5($2);';
$result = pg_query_params($dbconn_login, $sql_query, array($_POST["user"], $_POST["password"]));
if (pg_num_rows($result) < 1) {
  die('failure');
}

4 回答

  • 2

    准备好的语句对于SQL注入是安全的,因为没有人可以更改它准备好的查询计划 after . 但是,如果您的语句已经被破坏,您仍然会遭受SQL注入:

    <?php 
    // how NOT to construct your SQL....
    $query = 'SELECT * FROM user WHERE login=$1 and password=md5($2) LIMIT '. $_POST['limit']; -- injection!
    $result = pg_prepare($dbconn, "", $query);
    $result = pg_execute($dbconn, "", array($_POST["user"], $_POST["password"]));
    if (pg_num_rows($result) < 1) {
      die ("failure");
    }
    ?>
    
  • 6

    准备好的语句内置于MySQL(http://dev.mysql.com/doc/refman/5.6/en/sql-syntax-prepared-statements.html)中 . 注入防止机制也在MySQL中,请参阅之前链接页面的引用:

    防止SQL注入攻击 . 参数值可以包含未转义的SQL引号和分隔符 .

    PHP库只是将它们的功能映射到MySQL函数(可能使用http://docs.oracle.com/cd/E17952_01/refman-5.0-en/c-api-prepared-statement-function-overview.html) . 所以是的,pg_prepare也应该保护你注射 .

    [编辑]我刚刚注意到你在谈论PostgreSQL,对于PostgreSQL也是如此,它是内置的language feature,而不是PHP库提供的东西 .

  • 2

    就我从文档中收集而言,它应该防范SQL注入 .

    更通用的方法是使用pg_query_params,因为它与准备查询无关 .

  • 1

    使用预准备语句通常是最好的方法,因为您还应该从可以跳过的数据库优化中获得更好的SQL性能 .

    但是,了解其他处理方法总是好的,因此请记住,您可以在受污染的变量上使用pg_escape_string(),然后直接在SQL查询中使用输出 .

相关问题