准备()准备语句(不是PDO)阻止SQL

我正在研究的目标系统中不支持PDO ,尽管我正在寻找一种在PostGres-DB 8.2+上使用PHP 5.1.x防止SQL注入的解决方案。 目前没有机会切换到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");
}

但是pg_prepare-documentation缺少关于重要信息的信息:

它讲述了“后期使用”

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

它讲述了“命名/匿名语句”

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

它讲述了“类型转换”

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

但它并没有说明,这个准备好的语句的实现是否对SQL注入是安全的

*这个安全问题几乎所有的评论都是指PDO解决方案,其中文档被注意到驱动程序阻止SQL注入。 但如果一个简单的解决方案可能是pg_prepare,那么我现在会使用pg_prepare。*

感谢这可能是最佳实践解决方案的重要信息。

编辑(标记为解决方案后):感谢非常启发性的答案!

  • 我将Frank Heikens的解决方案标记为最佳答案,因为它解释了SQL注入中的一个重要问题。 程序员可以使用准备好的statemtents,但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');
    }
    

    准备好的语句对SQL注入是安全的,因为没有人可以准备好之后更改查询计划。 但是,如果您的声明已经被破坏,您仍然遭受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");
    }
    ?>
    

    预编译语句内置于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也是如此,它是一种内置的语言功能,而不是PHP库提供的功能。


    据我可以从文档中收集它应该防范你注入SQL。

    更通用的方法是使用pg_query_params因为它没有连接准备查询。

    链接地址: http://www.djcxy.com/p/16753.html

    上一篇: prepare() prepared statement (not PDO) prevent SQL

    下一篇: Do PHP PDO prepared statements need to be escaped?