关于php:我从mysql注入安全吗?

Am I safe from a mysql injection?

本问题已经有最佳答案,请猛点这里访问。

这是否足以避免SQL注入?

1

这里只需要mysql_real_escape_string()方法。在将数据插入数据库之前,不应该执行htmlentities()urlencode()。这些方法通常是在呈现您提供给用户的视图期间编写的代码。

避免SQL注入的更好方法是使用准备好的语句。

资源:

  • php.net-用pdo编写语句

关于同一主题:

  • php:mysql-real-escape-string是否足以清除用户输入?


我认为您混淆了两个安全问题:SQL注入和跨站点脚本(XSS)。

如果在发送到SQL数据库的SQL查询中使用了未正确清理的用户输入,则网站容易受到SQL注入的攻击。例如,此代码引入了一个SQL注入漏洞:

1
mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . $_POST['postmessage'] ."')");

这个问题很容易通过使用像mysql_real_escape_string这样的函数来转义用户输入来解决:

1
mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . mysql_real_escape_string($_POST['postmessage']) ."')");

这就是您需要做的全部工作,但最棘手的部分是记住要为SQL语句中使用的每一个用户输入完成这项工作。

当用户输入在发送到客户机的HTML中使用时,网站容易受到跨站点脚本攻击。例如,此代码引入了一个XSS漏洞:

1
echo"" . $_POST['postmessage'] ."";

通过使用类似于htmlspecialchars的函数来转义用户输入,可以修复XSS漏洞:

1
echo"" . htmlspecialchars($_POST['postmessage']) ."";

同样,这很容易做到,但很容易被遗忘。

通常,将用户输入放在数据库中以便在以后发送HTML时使用的输入保存为未修改的。也就是说,只使用mysql_real_escape_string。但是,您可以转义用户输入以防止XSS,然后转义XSS安全字符串以防止SQL注入:

1
mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . mysql_real_escape_string(htmlspecialchars($_POST['postmessage'])) ."')");

好处是,在将值写入HTML之前,不需要记住使用htmlspecialchars从数据库中转义值。缺点是一些值可能需要使用不同的函数进行转义。例如,用户名可能与htmlspecialchars一起转义,但"postmessage"可能允许bbcode、markdown或html的子集。如果您对所有输入进行转义以防止XSS,那么您将需要使用htmlspecialchars_decode等工具从数据库中取消对值的scape。

一个问题是,取消转义字符串的转义并不总是返回原始字符串(unescape(escape($orig))不一定与$orig相同)。即使使用htmlspecialcharshtmlspecialchars_decode,使用不同的引号样式也会导致此问题。另一个例子是,如果使用了strip_tags,那么信息将无法恢复地被删除;您将无法撤消strip_tags。因此,许多开发人员选择使用mysql_real_escape_string只将值保存到数据库中,而htmlspecialchars则从数据库中准备一个字符串以用于HTML。


是的,但不使用mysql_real_escape_string()是有原因的。首先,打字很痛苦。其次,你必须记住每次都要使用它。第三,它会使代码变得丑陋。第四,你必须记住引用你的字符串。第五,以这种方式在数据库中插入blob更困难。

从长远来看,学习PDO将使你的生活变得更好。学习起来比简单使用mysql_real_escape_string()更困难,但是长期的好处超过了学习曲线带来的不便。


您还应该确保在插入代码的地方使用"around"。

例如,如果你这样做

1
2
$_POST['userid'] = mysql_real_escape_string($_POST['userid']);
mysql_query('SELECT * FROM user WHERE userid = '. $_POST['userid']);

mysql-real-escape-string没有任何帮助。这是因为"$u post['userid']没有被包围"。

所以你应该这么做

1
2
$_POST['userid'] = mysql_real_escape_string($_POST['userid']);
mysql_query('SELET * FROM user WHERE userid = \''. $_POST['userid'] .'\'');

相反。

所以在变量上使用mysql-real-escape-string并不意味着它们在任何查询中都是安全的。

另一种方法是使用准备好的语句。