【发布时间】:2013-09-20 14:10:26
【问题描述】:
我正在尝试为我的 PSQL 数据库创建一个 PHP 接口,我希望一些在 PSQL 上注册的本地用户能够登录到我的数据库。我会首先为每个用户创建每个用户名,使用通用密码,如“Password123”,然后用户可以稍后更改他/她的密码。
为此,我想到了使用一个简单的 PHP 表单:
<form action="" method="post">
<table>
<tr> <td> User: </td> <td> <input type="text" name="user" /> </td> </tr>
<tr> <td> Old password: </td> <td> <input type="password" name="old" /> </td> </tr>
<tr> <td> New password: </td> <td> <input type="password" name="new1" /> </td> </tr>
<tr> <td> Repeat new password: </td> <td> <input type="password" name="new2" /> </td> </tr>
<tr> <td> <input type="submit" name="submit" value="Change password" /> </td> </tr>
</form>
<?php
if ($_POST) {
$user = $_POST["user"];
$old = $_POST["old"];
$new1 = $_POST["new1"];
$new2 = $_POST["new2"];
$link = pg_connect("dbname=mydb host=localhost user=$user password=$old connect_timeout=1");
if (!$link) {
die("Error connecting to mydb: ".pg_last_error($link));
}
if ($new1 <> $new2) {
pg_close($link);
die("New passwords do not match.");
}
$res = @pg_query($link,"ALTER ROLE $user WITH ENCRYPTED PASSWORD '$new1';");
if ($res) {
echo "Password successfully changed!<br>";
} else {
echo "Failed to change password...<br>";
}
pg_close($link);
}
?>
它确实像我预期的那样工作!
但是我读到有一些 SQL 注入攻击可以在这样的表达式上进行,其中 SQL 查询中有一个简单的变量插值。所以我读到PREPARE 语句是进行此类查询的最安全方法。我希望做类似的事情:
pg_prepare($link,"change_user","ALTER ROLE $1 WITH ENCRYPTED PASSWORD '$2';");
但我得到一个语法错误,即使我尝试在 pgAdminIII 中 PREPARE 这个命令。实际上,Postgres manual 表明 PREPARE 只能准备“任何 SELECT、INSERT、UPDATE、DELETE 或 VALUES 语句”。
然后我尝试使用pg_escape_string()函数:
$user = pg_escape_string($_POST["user"]);
...
这在我使用普通密码时效果很好,如果我尝试设置像''" 这样的密码,之后我将无法更改它。我根据手册试过pg_escape_literalwhich is preferred到pg_escape_string,但是我的PHP是5.3.13版本,这个命令只适用于5.4.4以后。
问题是:在这种情况下,这是防止注入攻击的最佳方法吗?这真的可以防止攻击吗?
另一个问题:如果用户想在他/她的密码中使用撇号,是否有可能没有这个错误?
【问题讨论】:
标签: php postgresql escaping postgresql-9.2