在大多数情况下mysql_real_escape_string
是否足以清理用户输入?
:: EDIT ::
我主要考虑防止SQL注入,但我最终想知道在应用mysql_real_escape_string之后是否可以信任用户数据,或者我应该采取额外措施来清理数据,然后再将其传递给应用程序和数据库。
我知道清除HTML字符的位置很重要,但我不认为有必要信任用户输入。
Ť
答案 0 :(得分:36)
mysql_real_escape_string
在所有情况下都不够,但绝对是非常好的朋友。 更好解决方案正在使用 Prepared Statements
//example from http://php.net/manual/en/pdo.prepared-statements.php
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->bindParam(1, $name);
$stmt->bindParam(2, $value);
// insert one row
$name = 'one';
$value = 1;
$stmt->execute();
此外,不要忘记可以用来丢弃任何无效/可疑字符的 HTMLPurifier 。
...........
修改强> 根据下面的评论,我需要发布这个链接(我应该在抱歉造成混淆之前完成)
<强> mysql_real_escape_string() versus Prepared Statements 强>
<强>引用强>
mysql_real_escape_string()容易发生 同样的问题影响 和addslashes()。
Chris Shiflett (安全专家)
答案 1 :(得分:11)
你的问题的答案是否定的mysql_real_escape_string()不适合所有用户输入,mysql_real_escape_string()不会停止所有sql注入。 addslashes()是另一个在php中使用的流行函数,它也有同样的问题。
易受攻击的代码:
mysql_query("select * from user where id=".mysql_real_escape_string($_GET[id]));
poc exploit:
http://localhost/sql_test.php?id=1 or sleep(500)
补丁是在id:
周围使用引号mysql_query("select * from user where id='".mysql_real_escape_string($_GET[id])."'");
真正最好的方法是使用一些人们指出的参数化查询。 Pdo运行良好,adodb是另一个流行的php库。
如果你确实使用mysql_real_escape_string应该只用于sql注入,而不是别的。漏洞高度依赖于数据的使用方式。人们应该逐个功能地应用安全措施。是的,XSS是一个非常严重的问题。不对html进行过滤是一个严重的错误,黑客会用它来解决你的问题。请阅读xss faq。
答案 2 :(得分:5)
到数据库,是的。您还需要考虑为输出充分转义/编码数据。
您还应该考虑根据您的预期验证输入。
您是否考虑过使用prepared statements? PHP提供了许多与数据库交互的方法。其中大多数都比mysql_ *函数更好。
PDO,MDB2和MySQL Improved可以帮助您入门。
答案 3 :(得分:4)
什么情况?
对于SQL查询,它很棒。 (准备好的陈述更好 - 我为此投票PDO - 但函数逃脱得很好。)对于HTML等,它不是工作的工具 - 尝试通用htmlspecialchars
或更多像HTML Purifier这样的精确工具。
解决编辑问题:您可以添加的唯一其他图层是数据修正,例如确认如果要将整数放入数据库,并且期望正整数,则在尝试输入负整数时向用户返回错误。就数据完整性而言,mysql_real_escape_string
是您逃避的最佳选择(尽管如此,准备好的语句是一个更清晰的系统,可以避免完全逃避)。
答案 4 :(得分:2)
mysql_real_escape_string()
仅对防止SQL注入攻击很有用。它不会帮助您防止跨站点脚本攻击。为此,您应该在输出最初从用户输入收集的数据之前使用htmlspecialchars()
。
答案 5 :(得分:1)
有两种方法,一种是使用预准备语句(如其他答案中所述),但这会降低您的应用程序速度,因为您现在必须向数据库发送两个请求,而不是一个。如果你能忍受降低的表现,那就去吧;准备好的语句使您的代码更漂亮,更容易处理。
如果选择使用mysql_real_escape_string,请确保转义所有不受信任的字符串。 一个(mysql_real_escape_string)转义字符串是SQL注入安全。如果你没有逃脱所有的字符串,那么你就不安全了。你应该将mysql_real_escape_string与输入验证结合起来;检查您希望保留数字的变量是否真的是一个数字且在预期范围内。请记住,永远不要相信用户。
答案 6 :(得分:1)
有不同类型的“清洁”。
mysql_real_escape_string对于数据库数据已足够,但如果是HTML,浏览器仍会对其进行评估。
要从用户输入中删除HTML,您可以使用strip_tags。
我建议你考虑使用PDO而不是常规的MySQL东西,因为它支持开箱即用的预处理语句,并为你处理无效数据的转义。
答案 7 :(得分:1)
您可以尝试两者,例如
function clean_input($instr) {
// Note that PHP performs addslashes() on GET/POST data.
// Avoid double escaping by checking the setting before doing this.
if(get_magic_quotes_gpc()) {
$str = stripslashes($instr);
}
return mysql_real_escape_string(strip_tags(trim($instr)));
}
答案 8 :(得分:0)
最好的方法是使用Prepared Statements
答案 9 :(得分:0)
我想我会补充说,PHP 5.2+具有输入过滤功能,可以通过各种方式消毒用户输入。
这是manual entry以及blog post [由Matt Butcher]关于为什么他们很棒。