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

Pon*_*nti 3 php security postgresql prepared-statement

我正在研究的目标系统中不支持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");
}
Run Code Online (Sandbox Code Playgroud)

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

它讲述了"以后的用法"

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

它讲述了"命名/匿名陈述"

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

它讲述了"类型转换"

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

但是它没有说明,如果准备好的语句的这种实现是安全的SQL注入

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

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

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

  • 我将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');
}
Run Code Online (Sandbox Code Playgroud)

Fra*_*ens 6

准备好的语句对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");
}
?>
Run Code Online (Sandbox Code Playgroud)