准备()准备语句(不是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。*
感谢这可能是最佳实践解决方案的重要信息。
编辑(标记为解决方案后):感谢非常启发性的答案!
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
因为它没有连接准备查询。