【发布时间】:2012-08-07 12:18:12
【问题描述】:
我正在处理的目标系统不支持 PDO,尽管我正在寻找一种解决方案来防止在 上使用 PHP 5.1.x 进行 SQL 注入PostGres-DB 8.2+。目前没有机会切换到 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().[...]
它讲述了“命名/匿名声明”
该函数从 查询字符串,它必须包含单个 SQL 命令。 stmtname 可能是 "" 创建一个未命名的语句,在这种情况下,任何预先存在的 未命名的语句被自动替换;[...]
它讲述了“类型转换”
与 pg_prepare() 一起使用的准备好的语句也可以由 执行 SQL PREPARE 语句。 (但 pg_prepare() 更灵活 因为它不需要预先指定参数类型。)另外, 虽然没有用于删除准备好的语句的 PHP 函数, SQL DEALLOCATE 语句可用于此目的。
但它并不能说明这种预准备语句的实现是否可以避免 SQL 注入
*这个安全问题的几乎所有 cmets 都指的是 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()作为替代方案(感谢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');
}
【问题讨论】:
-
我认为确实如此,但您可以随时尝试查看
:)。注入您自己的DROP TABLE语句来代替其中一个参数值,看看是否可以让它删除一个虚拟表。
标签: php security postgresql prepared-statement