【发布时间】:2011-04-05 05:08:45
【问题描述】:
以下是否足以避免 SQL 注入?
mysql_real_escape_string(htmlentities (urlencode($_POST['postmessage'])));
【问题讨论】:
标签: php sql-injection xss
以下是否足以避免 SQL 注入?
mysql_real_escape_string(htmlentities (urlencode($_POST['postmessage'])));
【问题讨论】:
标签: php sql-injection xss
mysql_real_escape_string() 是您在这里需要的唯一方法。
在将数据插入数据库之前,您不应该执行htmlentities() 或urlencode()。这些方法通常是在您提供给用户的视图呈现期间执行的代码。
避免 SQL 注入的更好方法是使用准备好的语句。
资源:
关于同一主题:
【讨论】:
我认为您混淆了两个安全问题:SQL injection 和 cross-site scripting (XSS)。
如果在发送到 SQL 数据库的 SQL 查询中使用了未正确清理的用户输入,则网站很容易受到 SQL 注入的攻击。例如,这段代码引入了一个 SQL 注入漏洞:
mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . $_POST['postmessage'] . "')");
这个问题很容易通过使用mysql_real_escape_string之类的函数转义用户输入来解决:
mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . mysql_real_escape_string($_POST['postmessage']) . "')");
这就是您需要做的所有事情,但棘手的部分是要记住对 SQL 语句中使用的每个用户输入都执行此操作。
当用户输入用于发送到客户端的 HTML 中时,网站很容易受到跨站点脚本的攻击。例如,这段代码引入了 XSS 漏洞:
echo "<div class='postmessage'>" . $_POST['postmessage'] . "</div>";
XSS 漏洞已通过使用 htmlspecialchars 之类的函数转义用户输入来修复:
echo "<div class='postmessage'>" . htmlspecialchars($_POST['postmessage']) . "</div>";
同样,这很容易做到,但很容易忘记。
通常情况下,放置在数据库中的用户输入用于稍后发送回 HTML,不会被修改。也就是说,只使用了mysql_real_escape_string。但是,您可以转义用户输入以防止 XSS,然后转义 XSS 安全字符串以防止 SQL 注入:
mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . mysql_real_escape_string(htmlspecialchars($_POST['postmessage'])) . "')");
这样做的好处是,在将值写入 HTML 之前,您无需记住使用 htmlspecialchars 对数据库中的值进行转义。缺点是某些值可能需要使用不同的函数进行转义。例如,用户名可能会使用htmlspecialchars 进行转义,但“postmessage”可能允许使用 BBcode、Markdown 或 HTML 的子集。如果您转义了所有输入以防止 XSS,那么您需要从数据库中取消转义值,例如 htmlspecialchars_decode。
一个问题是取消转义转义字符串并不总是返回原始字符串(unescape(escape($orig)) 不一定与$orig 相同)。即使使用htmlspecialchars 和htmlspecialchars_decode,使用不同的引用样式也会导致此问题。另一个例子是,如果使用strip_tags,则信息被不可恢复地删除;您将无法撤消 strip_tags。因此,许多开发人员选择使用mysql_real_escape_string 仅将值保存到数据库中,而使用htmlspecialchars(或其他)从数据库中准备一个字符串以用于HTML。
【讨论】:
mysql_real_escape_string(或某些 DB 转义机制)和 htmlentities(或某些 XSS 转义机制)的原因。
是的,但不使用 mysql_real_escape_string() 是有原因的。首先,打字很痛苦。其次,您必须记住每次都使用它。第三,它让你的代码变得丑陋。第四,你必须记住引用你的字符串。第五,以这种方式在 db 中插入 blob 更加困难。
从长远来看,学习 PDO 将使您的生活更美好。它比简单地使用 mysql_real_escape_string() 更难学习,但长期的好处超过了学习曲线的不便。
您还应该确保在插入代码的地方使用"。
例如,如果你这样做
$_POST['userid'] = mysql_real_escape_string($_POST['userid']);
mysql_query('SELECT * FROM user WHERE userid = '. $_POST['userid']);
mysql_real_escape_string 无济于事。这是因为 $_POST['userid'] 没有被'包围。
所以你应该这样做
$_POST['userid'] = mysql_real_escape_string($_POST['userid']);
mysql_query('SELET * FROM user WHERE userid = \''. $_POST['userid'] .'\'');
改为。
因此,对变量使用 mysql_real_escape_string 并不意味着它们在任何查询中都是安全的。
另一种方法是使用prepared statements。
【讨论】: