我正在尝试为我的 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';");
但是我得到一个语法错误,即使我PREPARE
在 pgAdminIII 中尝试这个命令。事实上,Postgres 手册表明PREPARE
只能准备“任何 SELECT、INSERT、UPDATE、DELETE 或 VALUES 语句”。
然后我尝试使用该pg_escape_string()
功能:
$user = pg_escape_string($_POST["user"]);
...
这在我使用普通密码时效果很好,如果我尝试设置密码''"
,之后我无法更改它。我已经尝试过根据手册pg_escape_literal
首选哪个pg_escape_string
,但我的 PHP 版本是 5.3.13,并且此命令仅适用于 5.4.4 及以后的版本。
问题是:在这种情况下,这是防止注入攻击的最佳方法吗?这真的可以防止攻击吗?
另一个问题:如果用户想在他/她的密码中使用撇号,是否有可能没有这个错误?