在没有键验证的情况下使用 pg_update() 和 pg_insert() 不安全!
您需要检查您获得的数据对,以及是否允许更新此列。
示例
您有一个包含三列的表:用户名、密码、用户级别。
您的用户只能更改他们的用户名和密码,但不能更改他们的用户级别。
如果您没有过滤请求数组中的键,那么每个用户现在都可以通过发送带有 "userlevel=>100" 的 POST 请求来更改其用户级别。
因此,如果您不检查请求数组中的键是否允许,那么您的代码中将存在严重的 SQL 注入漏洞。
(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)
pg_update — 更新表
$connection
,$table_name
,$values
,$conditions
,$flags
= PGSQL_DML_EXEC
pg_update() 更新与 conditions
匹配的记录,并将值更新为 values
。
如果指定了 flags
,则 pg_convert() 会使用指定的标志应用于 values
。
默认情况下,pg_update() 传递原始值。值必须转义,或者必须在 flags
中指定 PGSQL_DML_ESCAPE
标志。PGSQL_DML_ESCAPE
引用和转义参数/标识符。因此,表/列名称区分大小写。
请注意,转义或准备好的查询都无法保护 LIKE 查询、JSON、数组、正则表达式等。这些参数应根据其上下文进行处理。例如,转义/验证值。
connection
一个 PgSql\Connection 实例。
table_name
要更新行的表的名称。
values
一个 array,其键是表 table_name
中的字段名称,其值是要更新匹配行的值。
conditions
一个 array,其键是表 table_name
中的字段名称,其值是行必须满足的更新条件。
flags
任何数量的 PGSQL_CONV_FORCE_NULL
、PGSQL_DML_NO_CONV
、PGSQL_DML_ESCAPE
、PGSQL_DML_EXEC
、PGSQL_DML_ASYNC
或 PGSQL_DML_STRING
的组合。如果 PGSQL_DML_STRING
是 flags
的一部分,则返回查询字符串。当设置了 PGSQL_DML_NO_CONV
或 PGSQL_DML_ESCAPE
时,它不会在内部调用 pg_convert()。
成功时返回 true
,失败时返回 false
。如果通过 flags
传递了 PGSQL_DML_STRING
,则返回 string。
版本 | 说明 |
---|---|
8.1.0 | connection 参数现在期望一个 PgSql\Connection 实例;以前,期望的是一个 resource。 |
示例 #1 pg_update() 示例
<?php
$db = pg_connect('dbname=foo');
$data = array('field1'=>'AA', 'field2'=>'BB');
// 这在某种程度上是安全的,因为所有值都被转义了。
// 但是 PostgreSQL 支持 JSON/数组。这些既不是
// 由转义,也不是由准备好的查询来保证安全的。
$res = pg_update($db, 'post_log', $_POST, $data);
if ($res) {
echo "Data is updated: $res\n";
} else {
echo "User must have sent wrong inputs\n";
}
?>
在没有键验证的情况下使用 pg_update() 和 pg_insert() 不安全!
您需要检查您获得的数据对,以及是否允许更新此列。
示例
您有一个包含三列的表:用户名、密码、用户级别。
您的用户只能更改他们的用户名和密码,但不能更改他们的用户级别。
如果您没有过滤请求数组中的键,那么每个用户现在都可以通过发送带有 "userlevel=>100" 的 POST 请求来更改其用户级别。
因此,如果您不检查请求数组中的键是否允许,那么您的代码中将存在严重的 SQL 注入漏洞。
> 返回值
>
> 成功时返回 TRUE,失败时返回 FALSE。如果
> PGSQL_DML_STRING 通过选项传递,则返回字符串。
我发现在我的 PHP 副本(版本 4.4.0)中,如果您使用 'PGSQL_DML_STRING' 选项,该函数不会执行任何查询。它只是返回将要执行的查询。
我注意到的另一件事是,pg_update 似乎没有使用 pg_trace(至少在 4.4.0 中没有)。
PS 这不是错误报告,只是对一些我注意到的未记录功能的解释。正如手册中所说,该函数仍在开发中,因此这种行为可能因版本而异。
此函数类似于 PEAR::DB 的 autoExecute() 函数,唯一的区别是 where 子句是数组而不是字符串。
此外,如果您想将您的 DB 类实例与此函数一起使用,您可以使用 $db->connection 引用现有的资源连接。
一个示例是
<?
pg_update($db->connection, $arr_update, $arr_where);
?>