这段 PHP 代码是否安全?

4

我知道应该使用预处理语句,但我的下一个项目将使用预处理语句,我只需要完成这个简单的小应用程序。

所以我的问题是:

以下代码片段是否安全?

我已经使用了htmlentities和mysql_real_escape_string,因为我认为这是一个安全的选项。

//Image 
$imageInput = $_POST['Image'];
$imageClean = htmlentities($imageInput, ENT_QUOTES, 'UTF-8');



//Inserts values into relevant field and creates a new row.
mysql_query("UPDATE ***** SET image='" . mysql_real_escape_string($imageClean) . "'     WHERE id=" . mysql_real_escape_string($idClean) . "");

添加$idClean的代码如下:

//Id to change
if(ctype_digit($_POST['testimonial']))
{
    $idInput = $_POST['testmonial'];
    $idClean = htmlentities($idInput, ENT_QUTOES, 'UTF-8');
}

感谢您的帮助。
顺便提一下,如果您能提出一些可以添加的建议,那就太好了。

3
当 $idclean = "1 OR 1=1" 时,想一想会发生什么。 - Piskvor left the building
&Piskvor 我应该在 $idClean 中使用 if(cytpe_digit) 吗? - Oliver Bayes-Shelton
1
@Oliver Bayes-Shelton:假设id是一个整数,我会选择将$idClean强制转换为(int)类型。 - Piskvor left the building
你也应该将id部分用引号括起来。 - Pekka
2
@Oliver:你为什么不使用参数化查询呢?这是我在你之前提出的同样标题的问题中所建议的。http://stackoverflow.com/questions/2289295/is-this-php-code-secure/2289326#2289326 - Jørn Schou-Rode
显示剩余2条评论
6个回答

4

+1 非常好。你完全正确。除了你注入的 SQL 不是有效的。攻击者会使用子查询来利用它。 - rook

3
您只需要在输出时应用实体转义 - 在将数据插入数据库之前转义数据是没有意义的。话虽如此,您在使用mysql_real_escape_string方面做得很正确。
除此之外,正如@Piskvor所说,idClean变量存在潜在问题。(例如,是否被强制转换为int?)
例如,您可以使用以下内容:
mysql_real_escape_string(intval($idClean))

你能解释一下实体转义吗?我应该做些什么替代它? - Oliver Bayes-Shelton
我能使用以下代码吗://更改ID if(ctype_digit($_POST['testimonial'])) { $idInput = $_POST['testmonial']; $idClean = htmlentities($idInput, ENT_QUTOES, 'UTF-8'); } - Oliver Bayes-Shelton
1
-1 不需要在整数上运行mysql_real_escape_string(),这是多余的。 - rook
@Michael Brooks - 很好的观点。(我这边脑子有点抽了。) - John Parker

2

$idClean从哪里来的?

另一个$_POST?它应该是一个整数,不是吗?

不要对它进行HTML清理,只需$idClean =(int)$ _POST ['id']; …将“强制”它成为整数,“杀死”所有可能的xss / sql注入(仅针对$idClean)

总的来说,没有一个“最佳方法”来净化输入;一切都取决于输入应包含什么,它将被存储在何处以及将来如何使用。

编辑:在middaparka答案中发表评论后,我认为$idClean来自表单(可能是一个隐藏的输入)。

如果您想防止甚至是恶意使用该表单,我建议您添加另一个带有哈希的隐藏字段$idclean,然后在处理页面中检查哈希以查看是否有人手动更改了ID(如果您尚未执行此操作)

这通常是用户管理中的错误设计,不知道是否是您的行为。


1
假设 $_POST['Image'] 是一个 URI,那么不行。有人可能使用 javascript: 方案提交一个 URI,导致其他人运行任意的 JavaScript。

0

“Image”和ID的预期字符范围是什么?虽然转义输入是一个好主意,但您应该始终检查输入是否只包含给定数据类型的合法字符。例如:

if (preg_match("/\w(\w|\\.){0,31}/", $imageInput) && preg_match("/\d{1,12}/", $idClean)) {
// do database update
} else {
// invalid input, let the user know!
}

对于$imageInput的正则表达式应该只允许包含字母数字、下划线和句点的图像名称。长度为1到32个字符(您需要将其与数据库定义匹配)。不允许使用其他字符。我是凭记忆写的正则表达式,如果转义不正确,请原谅我,但使用正则表达式来清理已知良好输入的原则是正确的。

数据库安全性并不是您需要考虑的唯一安全方面。想想跨站脚本攻击(XSS)。如果用户将图像名称输入为:javascript:alert('abc'); 那么当您将其显示回给用户时,它将在他们的浏览器中执行!


0

如前所述,您有一个与id=xyz有关的问题。但是,与其在php中将其转换为整数,我会将其作为字符串文字传递,原因有两个:

  • 您可以更改id字段的类型,而无需触及代码的特定部分。 id并不总是必须是整数。
  • php整数的值范围(尤其是最大值)可能小于字段定义的类型。

连接字符集会影响mysql_real\escape_string()的行为。因此,您应该将连接资源作为第二个参数传递给mysql_real\escape_string()。

在插入数据之前是否使用htmlentities()取决于您想要实现什么。如果您需要将数据用作html / utf-8之外的其他内容,则必须将其转换回来。但是,由于这与安全性无关....随你喜欢;-)

$mysql = mysql_connect('..', '..', '..');
//...
$query = sprintf("
  UPDATE
    *****
  SET
    image='%s'
  WHERE
    id='%s'
  ", 
  mysql_real_escape_string($imageClean, $mysql),
  mysql_real_escape_string($id, $mysql)
);

顺便提一下:关于预处理语句的必要提示:http://docs.php.net/pdo.prepared-statements


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接