【问题标题】:Filtering User Input过滤用户输入
【发布时间】:2011-08-23 10:38:29
【问题描述】:

我在这里阅读了很多关于过滤用户输入的问答,但大多数时候答案是这取决于你在做什么。这就是我正在做的事情:

通过将在 MySQL 查询中使用的表单提交的数据:

function clean($field, $link)
{
    return mysql_real_escape_string($field, $link);
}

通过表单提交的数据将显示在 HTML/PHP 页面或电子邮件中:

function output_html($value)
{
    return stripslashes(htmlspecialchars($value));
}

从数据库中显示的数据:

function output_db($value)
{
    return stripslashes($value);
}

这足以满足我的需求吗?有什么我没有考虑的吗?

谢谢!

【问题讨论】:

  • 您是在询问应用程序的安全性,即 SQL 注入吗?
  • @robert-harvey SQL 注入,并通过 JS 等向我的页面永久添加代码
  • output_db 表示您做错了。如果您正确地转义了您的内容,并且没有启用多余的magic_quotes,那么在数据库查询之后就不需要stripslashes()。 php.net/manual/en/security.magicquotes.disabling.php

标签: php mysql html forms input


【解决方案1】:

在将字符串插入 SQL 查询时使用mysql_real_escape_string(),无论输入来自何处。

在将字符串插入 HTML 代码时使用htmlspecialchars()htmlentities(),无论输入来自何处。

在将值插入 URL 的查询字符串时使用 urlencode(),无论值来自何处。

如果这些数据来自用户,那么你绝对应该做这些事情,因为用户有可能试图做坏事。但是抛开安全问题不谈——如果你想在 SQL 查询中插入一个合法的字符串,而这个字符串恰好有一个单引号字符呢?你仍然必须逃脱它。

【讨论】:

  • 这听起来像是一个愚蠢的问题,但只是为了澄清一下,urlencode() 是否适用于由表单自动生成的查询字符串?这些值被硬编码到表单中,所以我猜什么都不需要做,但我只是想澄清一下。谢谢
  • @Sarah 好问题。使用<form> 提交的值由浏览器自动进行 URL 编码。例如,在您的表单中,当用户单击提交按钮时,“search_content”文本框的值将由浏览器进行 URL 编码。
【解决方案2】:

如果您刚开始,我真的会考虑使用 PDO 之类的东西。您最终会希望以这种方式迁移,所以为什么不现在开始。

PDO 会自动清理您的输入,这很棒。它还将使用 prepare() 语句,因此您可以保证单个查询,从而防止有人使用“; DROP TABLE xxx;”进行攻击之类的。

http://php.net/manual/en/book.pdo.php

【讨论】:

    【解决方案3】:

    当您将数据插入 SQL 数据库时,您需要对其进行转义以防止 SQL 注入,而在 mysql 中使用 mysql_real_escape_string() 是正确的。但是,您必须记住将其用于所有内容,因此很容易出错。您应该改用 PDO 之类的东西,它会自动转义每个传入的值。

    来自数据库的数据通常不需要任何特殊处理(即取消转义)。我不知道你想用stripslashes() 做什么。如果是为了删除 PHP 插入的魔术引号,您应该在从 GET/POST/etc 中提取用户提供的值的地方执行此操作。 (或者完全禁用魔术引号,如果可以的话,并且没有任何其他依赖它的软件)

    输出到 html 的数据需要转义以防止 XSS。 htmlspecialchars() 是正确的功能。同样,我不知道您要使用 stripslashes() 做什么。同样,您需要记住转义每个值,这很容易出错。您至少应该考虑使用模板引擎或其他自动将所有值转义到 html 的东西的好处。

    【讨论】:

    • 您好,感谢您提供此信息:) 我只是想澄清一下,htmlspecialchars() 是我需要对输出到 html 的变量进行的唯一安全处理吗?当您说容易出错时,您的意思是它有时可能无法正常工作,因此不是 100% 安全吗?你知道有哪些模板引擎可用吗?谢谢,sarah
    • @Sarah:这是元素内部数据唯一需要的东西。 (当然,如果你将任意用户内容放在脚本元素中,你还是会搞砸的)我所说的容易出错的意思是很容易忘记在任何地方使用它,如果你甚至在一个地方忘记它,你'搞砸了。但是,如果您需要将用户定义的内容放入属性(例如 href),您需要做的还不止这些,因为恶意用户可以输入例如。 javascript:whatever。例如。对于 href,您可能只想将一些允许的协议列入白名单,因为浏览器允许“javascript:”的各种变体工作。
    • 感谢您的解释。我可以问你,就href属性而言..是否仅在用户定义的情况下?..在我的项目中,我从facebook检索json数据并在php中使用该数据,将此数据插入href属性和其他元素。但是在这种情况下,它全部来自 facebook,没有来自用户。在将其插入到我的 html 之前,我需要对这些数据执行安全措施吗?还是安全的?...谢谢...
    【解决方案4】:

    如果你有能力,我建议使用mysqli而不是mysql,并使用prepared statements:

    <?php
    $mysqli = new mysqli("localhost", "my_user", "my_password", "world");
    
    /* check connection */
    if (mysqli_connect_errno()) {
        printf("Connect failed: %s\n", mysqli_connect_error());
        exit();
    }
    
    $city = "Amersfoort";
    
    /* create a prepared statement */
    if ($stmt = $mysqli->prepare("SELECT District FROM City WHERE Name=?")) {
    
        /* bind parameters for markers */
        $stmt->bind_param("s", $city);
    
        /* execute query */
        $stmt->execute();
    
        /* bind result variables */
        $stmt->bind_result($district);
    
        /* fetch value */
        $stmt->fetch();
    
        printf("%s is in district %s\n", $city, $district);
    
        /* close statement */
       $stmt->close();
    }
    
    /* close connection */
    $mysqli->close();
    ?>
    

    来源:http://php.net/manual/en/mysqli.prepare.php

    这提供了基本的类型检查并为您转义。我不建议在输出数据库数据时使用stripslashes,因为:

    1. 数据库数据中可以有斜杠
    2. 无论如何,数据库不会为您转义

    关于显示HTML,还有htmlstriptags,它可以用标签之类的东西去除试图变得可爱的人。

    【讨论】:

      【解决方案5】:

      我会建议您使用 php 5.2 中引入的过滤器,它们非常棒,可以为您节省大量的数据验证和清理行。看这里

      filter_input

      【讨论】:

        猜你喜欢
        • 2013-04-16
        • 1970-01-01
        • 2010-11-05
        • 2018-12-29
        • 2013-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-18
        相关资源
        最近更新 更多