目标系统不支持PDO我正在努力虽然我在上寻求使用 PHP 5.1.x 防止SQL注入的解决方案PostGres-DB 8.2 + 。目前没有机会切换到PDO。
我目前的解决方案是pg_prepare-prepared statement:
// 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。*
感谢您提供最佳实践解决方案的重要信息。
编辑(标记为解决方案后): 感谢非常有启发性的答案!
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');
}
答案 0 :(得分: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");
}
?>
答案 1 :(得分:2)
预编译语句内置于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 :(得分:2)
就我从文档中收集而言,它应该防范SQL注入。
更通用的方法是使用pg_query_params
,因为它与准备查询无关。
答案 3 :(得分:1)
使用预准备语句通常是最好的方法,因为您还应该从可以跳过的数据库优化中获得更好的SQL性能。
然而,了解其他处理方法总是好的,因此请记住,您可以对受污染的变量使用pg_escape_string(),然后直接在SQL查询中使用输出。