PHP:mysql_real_escape_string是否足以清除用户输入?

时间:2010-03-01 03:06:09

标签: php security

在大多数情况下mysql_real_escape_string是否足以清理用户输入?

:: EDIT ::

我主要考虑防止SQL注入,但我最终想知道在应用mysql_real_escape_string之后是否可以信任用户数据,或者我应该采取额外措施来清理数据,然后再将其传递给应用程序和数据库。

我知道清除HTML字符的位置很重要,但我不认为有必要信任用户输入。

Ť

10 个答案:

答案 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_ *函数更好。

PDOMDB2MySQL 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]关于为什么他们很棒。