【问题标题】:Am I safe from a MySQL injection? [duplicate]我可以免受 MySQL 注入吗? [复制]
【发布时间】:2011-04-05 05:08:45
【问题描述】:

以下是否足以避免 SQL 注入?

mysql_real_escape_string(htmlentities (urlencode($_POST['postmessage'])));

【问题讨论】:

    标签: php sql-injection xss


    【解决方案1】:

    mysql_real_escape_string() 是您在这里需要的唯一方法。

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

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


    资源:

    关于同一主题:

    【讨论】:

    • +1 表示准备好的语句。在适当的情况下,它们也可以帮助提高性能。
    【解决方案2】:

    我认为您混淆了两个安全问题:SQL injectioncross-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 相同)。即使使用htmlspecialcharshtmlspecialchars_decode,使用不同的引用样式也会导致此问题。另一个例子是,如果使用strip_tags,则信息被不可恢复地删除;您将无法撤消 strip_tags。因此,许多开发人员选择使用mysql_real_escape_string 仅将值保存到数据库中,而使用htmlspecialchars(或其他)从数据库中准备一个字符串以用于HTML。

    【讨论】:

    • 使用准备好的语句不是更好吗,看起来更简洁,一旦掌握了它可能更容易使用。
    • @Xeross:当然。准备好的语句可以更容易地一致地转义用户输入。然而,在回答 OP 的问题时,我想确保他/她理解使用 mysql_real_escape_string(或某些 DB 转义机制)和 htmlentities(或某些 XSS 转义机制)的原因。
    【解决方案3】:

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

    从长远来看,学习 PDO 将使您的生活更美好。它比简单地使用 mysql_real_escape_string() 更难学习,但长期的好处超过了学习曲线的不便。

    【解决方案4】:

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

    例如,如果你这样做

    $_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

    【讨论】:

      猜你喜欢
      • 2013-02-19
      • 2018-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-13
      • 1970-01-01
      • 1970-01-01
      • 2016-02-12
      相关资源
      最近更新 更多