繁体   English   中英

pg_prepare()准备好的语句(不是PDO)会阻止SQL注入吗?

[英]Does pg_prepare() prepared statement (not PDO) prevent SQL-Injection?

我正在工作的目标系统中不支持PDO ist ,尽管我寻求一种解决方案来防止在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可以是“”以创建未命名的语句,在这种情况下,任何先前存在的未命名的语句都会被自动替换; [...]

它讲述了“类型转换”

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

但是并不能说明这种预准备语句的实现是否可以安全地从SQL注入

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

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

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

  • 我将Frank Heikens的解决方案标记为最佳答案,因为它解释了SQL注入中的重要点。 程序员可以使用准备好的状态表,但是错误地仍然可能存在SQL-injection-lack!
  • 除了弗兰克·海肯斯(Frank Heikens)的答案外,hoppa还显示了使用pg_prepare / pg_query_params阻止了SQL注入。 不过谢谢
  • 现在将通过pg_query_params使用优化的代码(感谢Milen A. Radev)
  • pg_escape_string()作为替代(感谢混血儿)

所有答案都是有帮助的:)

// 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-zh/c-api-prepared-statement-function-overview.html )。 所以是的,pg_prepare也应该保护您进行注射。

[编辑]我刚刚注意到您在谈论PostgreSQL,对于PostgreSQL同样,它是内置语言功能 ,而不是PHP库提供的功能。

据我所知,它应该防止SQL注入。

一种更通用的方法是使用pg_query_params因为它与准备查询没有关系。

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

但是,最好知道其他的处理方式,因此请记住,可以在受污染的变量上使用pg_escape_string() ,然后直接在SQL查询中使用输出。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM