【问题标题】:PHP secure user variablePHP 安全用户变量
【发布时间】:2015-10-17 05:16:19
【问题描述】:

在我的网站上,我有一个名为 $user_data 的变量,其中包含来自表单的输入。然后我在用户页面上显示这个变量(通过 echo)。

使用此变量避免任何安全风险的最佳方法是什么?我用strip_tags(),但是还不够。

这个变量也被保存到 MySQL 数据库中。

【问题讨论】:

  • strip_tags() 是垃圾,不用html标签就可以利用xss。
  • @The Rook — 是的,但它们通常更加晦涩难懂,例如输出到链接href。即便如此,htmlspecialchars 肯定要好得多,出于这个原因等等。
  • @Matchu 我认为我们谈论的是相同的攻击,例如注入 onClick 或其他事件处理程序。这实际上可以使用 htmlspeiclchars,你必须使用 htmlspecialchars($var,ENT_QUOTES); 但我想你知道......

标签: php sql mysql security


【解决方案1】:

为了避免严重的安全问题,您必须做两件非常重要的事情。

  1. 在将用户输入放入 SQL 查询之前,您需要对其进行转义。转义是指将'等所有特殊字符转义;幸运的是,有一个函数已经自动完成了:mysql_real_escape_string

    如果您不逃避用户输入,可能会发生令人讨厌的事情。假设您的查询是INSERT INTO userdata VALUES ('$user_data')。现在假设用户写了'; DROP DATABASE userdata;

    如果不转义,查询将变为:INSERT INTO userdata VALUES (''; DROP DATABASE userdata;')。正如您可以想象的那样,这并不好:如果您启用了多条语句,您可以告别您的数据库。这称为 SQL 注入 攻击。

  2. 当您将变量输出给用户时,您还需要用 HTML 实体正确替换 HTML 特殊字符。幸运的是,还有一个函数可以做到这一点:htmlspecialchars()。它会将特殊的 HTML 字符(例如 <)转换为 <

    这似乎是一个经常被低估的问题,但实际上它非常严重。想象一下如果$user_data 包含<script>SomeNastyScript()</script>。它可以利用用户浏览器中的现有漏洞,或者它可以向攻击者发送一个非 HTTPOnly cookie(可能包含保存的密码),或者它可以欺骗用户在通过操纵生成的表单上写入他们的密码DOM(可能在 javascript 中),或许多其他不好的东西。

    这称为 XSS(跨站点脚本)。


短版

  1. 在将字符串插入 SQL 查询之前,在字符串上调用 mysql_real_escape_string(但不是在您 echo 时)。

  2. 在将字符串显示给用户之前调用htmlspecialchars(但不是在将其放入数据库时​​)。

【讨论】:

  • 只是 htmlspecialchars,没有更多功能?
  • 重要的是,在将数据插入数据库之前不要做htmlspecialchars()。在存储用户数据之前,您需要避免无用的转换。
  • 更重要的事情。 ' 不是“特殊字符”,而只是一个分隔符。转义只是为了区分分隔符和文本。显然,转义仅适用于引号分隔的字符串,与数字无关。
  • @WorkingHard 不是那么完美。它有2个主要缺陷,会直接导致SQL注入。不仅是"user input ",还有 1. 在查询中将用引号分隔的每个字符串,无论我的来源如何。 2. 只转义字符串,因为它对数字没有帮助。数字以及标识符和运算符(如果有)需要特殊处理
【解决方案2】:

当你要输出一些东西时,strip_tagshtmlspecialchars 很好。我更喜欢后者,因为这样您就不会完全破坏 <3 之类的东西,因为它们从来都不是 HTML 标记。

将值直接放入查询时,mysql_real_escape_string 是合适的转义方式,或者仅使用 PDO 和准备好的语句。

当然,最好仅在您将需要这些转义方法时才使用它们,而不是将两者都应用于所有变量。如果您想在将其放入数据库之前实际使用它,那么必须将斜杠从 MySQL 转义变量中剥离出来总是很痛苦,这并不比 PHP4 的魔术引号好。同样,您不希望在将某人的密码“one

【讨论】:

    【解决方案3】:

    没有所谓的“安全性”。
    没有办法只保护一个抽象变量。一切都取决于场景。
    为安全起见常用的避孕套。你会用安全套保护你的钱吗?我想 - 不。
    同样在这里。 您最好区分这两个问题 - 数据库安全性和显示安全性。

    数据库一比“调用mysql_real_escape_string”稍微复杂一点。我已经在this answer

    中全面描述了所有规则

    【讨论】:

      【解决方案4】:

      您也可以这样做:

      $way = preg_replace('#[^a-z0-9]#i', '', 
          strip_tags(htmlentities(htmlspecialchars(mysqli_escape_string($db_conx, $_GET['way'])))));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-02
        • 2019-07-25
        • 1970-01-01
        • 2015-11-16
        • 2012-12-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多