【问题标题】:Escaping user data, without magic quotes转义用户数据,没有魔术引号
【发布时间】:2010-12-21 01:07:44
【问题描述】:

我正在研究如何在来自外部世界的数据被用于应用程序控制、存储、逻辑......之类的东西之前正确转义它。

很明显,随着魔术引号指令在 php 5.3.0+ 中很快被弃用,并在 php6 中被删除,这变得更加紧迫,对于任何想要升级和使用新语言功能的人来说,同时保持旧代码(不要'我们喜欢它..)。

但是,我没有看到的一件事是关于理论/最佳实践以及保护数据后该怎么做的大量讨论 - 例如,使用或不使用斜杠进行存储?我个人认为将转义数据保存在数据库中是一个坏举动,但希望听到讨论并最好阅读一些案例研究..

PHP 手册中的一些链接仅供参考:

PHP Manual - mysql_real_escape_string

PHP Manual - htmlspecialchars

等等等等

有什么建议吗?

【问题讨论】:

  • 您所说的“例如,使用或不使用斜杠进行存储”这一事实使我相信您可能对正确转义有一个错误的概念。如果您正确转义,则发送到需要斜杠的数据库的字符串将包含它们,但实际上不会存储在数据库中。如果您在数据库中看到斜线,则数据被不正确地转义。
  • 请详细解释一下 longneck - mysql 会在插入前删除转义符吗?有没有关于这个的页面?但你说得对——我想我在过去的某个时候忽略了这一点,现在正试图迎头赶上。
  • mysql_real_escape_string 不会转义斜杠等。它使字符串对于 SQL 查询是安全的。
  • 如果您要检查服务器是否打开了魔术引号,如果是,请删除斜杠,您需要查看 get_magic_quotes_gpc() 和 stripslashes() 函数。

标签: php mysql post get escaping


【解决方案1】:

对于数据库工作,检查参数化查询和准备好的语句。 PDOmysqli 很适合。

Htmlspecialchars 是在 html 文档中显示某些文本的正确工具。

而且,正如您提到的 php 5.3,您可以访问 filter functions,这是处理用户数据时必须使用的。

【讨论】:

    【解决方案2】:

    这很简单。在将所有传入数据插入数据库之前,应通过mysql_real_escape_string() 运行。例如,如果您知道某些内容需要是整数,请在插入之前将其设置为整数等。请记住,这只是为了停止 SQL 注入。 XSS 和数据验证是不同的。

    如果您希望某些内容成为电子邮件,显然需要在将其插入数据库之前对其进行验证。

    htmlentities() 清理数据,这意味着它修改数据。我认为您应该始终将原始数据存储在数据库中,当您获取该数据时,请选择您想要如何清理它。

    我喜欢将以下函数用作mysql_real_escape_string() 函数的“包装器”。

    function someFunction( $value )
    {
        if ( is_int( $value ) || is_float( $value ) ) {
            return $value;
        }
        return "'" . mysql_real_escape_string( (string) $value ) . "'";
    }
    

    如果值是浮点数或整数,则运行mysql_real_escape_string() 毫无意义。我在将值传递给mysql_real_escape_string() 之前将其转换为字符串的原因是,有时该值可能不是字符串。

    值不是字符串的示例:

    http://localhost/test.php?hello[]=test

    在 test.php 中,您在 $_GET['hello'] 上运行 mysql_real_escape_string(),期望 hello 是一个字符串。好吧,由于人将值设置为数组,因此实际上会引起通知,因为 hello 不是字符串。

    【讨论】:

    • 您的答案并不完全清楚。您是否建议不要使用 htmlentities?
    • 他的建议是在 DB 存储之前始终使用 mysql_real_escape_string
    • 什么时候存入数据库?是的,我的建议是不要使用 htmlentities。例如,如果我将数据输出到浏览器,那就是用户数据,那么是的,我将通过 htmlentities 运行它。有时我可能不想在某些情况下这样做,关键是当我访问该数据时我有这个选项。
    【解决方案3】:

    查看准备好的语句。我知道在 mysql 中这非常有效,并且是一种将数据输入数据库的安全形式。它也有一些性能优势。

    http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html

    如果你有兴趣,我还有一些资源。

    希望这就是你要找的东西,tc。

    编辑:

    我可以添加的一件事是将过滤器与准备好的语句结合使用。例如,要检查该值是否是您使用 FILTER_SANITIZE_STRING 的字符串,或者检查您使用 FILTER_SANITIZE_EMAIL 的电子邮件。

    这样可以节省一些代码并且效果很好。之后您可以随时使用自己的方法检查数据,但您可以使用很多过滤器。

    【讨论】:

    【解决方案4】:

    对于数据库插入,解决方案是使用bind variables

    一般来说,任何时候你发现自己转义了任何东西(shell 命令的参数、db 命令片段、用户提供的 html 等),这表明你没有使用正确的函数调用(例如,使用 @ 987654322@ 当您可以使用exec 的多参数形式时,或者您的框架有缺陷。在有缺陷的框架中工作的标准方法是增强它,这样您就可以回到不考虑引用的状态。

    考虑转义级别和引用级别可能会很有趣,但如果您真的很喜欢,请在业余时间与 Tcl 一起玩。对于实际工作,您不应该考虑引用,除非您正在设计一个供其他人使用的库,在这种情况下,您应该正确引用并让您的用户避免考虑引用。 (并且您应该非常仔细地准确记录您使用和不使用的引用类型)

    【讨论】:

      【解决方案5】:
      • 在运行查询时使用正确的数据转义方法: mysql_real_escape_string、准备好的查询等......

      • 将数据原封不动地存储在数据库中

      • 使用正确的方法转义输出数据: htmlspecialchars 等。

      【讨论】:

      • 谢谢,没有足够多的人意识到双方出于不同的原因需要对数据进行转义。 SQL 注入已经不那么令人担忧了,似乎很多人都理解它,但是 XSS 变得越来越普遍,我很高兴看到像 Galen 这样的人谈论它以及如何防止它。
      猜你喜欢
      • 2013-05-02
      • 2012-10-16
      • 2010-09-18
      • 1970-01-01
      • 2012-05-20
      • 2021-07-24
      • 2013-12-08
      • 2013-11-15
      • 2011-05-17
      相关资源
      最近更新 更多