0

我还在学习 PHP 和 SQL。我正在尝试为网站的事件列表创建一个简单的内容管理系统。所有输入表单字段都是文本区域或文本框(是的,我希望它们那样),并且我想让用户能够在这些字段中添加除了文本之外的 HTML 链接。以下功能似乎是开始清理我从用户那里获得的输入的好地方,但由于我是新手,所以我想获得更多知识渊博的开发人员的意见。我还应该做些什么来保护数据库?

PS 感谢这些功能的CSS-Tricks

function cleanInput($input) {

    $search = array(
         '@<script[^>]*?>.*?</script>@si',   // Strip out javascript
         '@<style[^>]*?>.*?</style>@siU',    // Strip style tags properly
         '@<![\s\S]*?--[ \t\n\r]*>@'         // Strip multi-line comments
    );

    $output = preg_replace($search, '', $input);
    return $output;
}

function sanitize($input) {
    if (is_array($input)) {
       foreach($input as $var=>$val) {
          $output[$var] = sanitize($val);
       }
    }
    else {
       if (get_magic_quotes_gpc()) {
          $input = stripslashes($input);
       }
       $input  = cleanInput($input);
   $output = htmlentities($output);
       $output = mysql_real_escape_string($input);
     }
     return $output;
}
4

2 回答 2

1

很容易:

$testinput = "<script>alert('p0wned');</script >\n
    <a href='http://example.org' onclick=\"alert('p0Wned again!)\">Click me!</a>";

var_export(cleanInput($testinput));

此外,htmlescape几乎总是使用错误的东西——它会破坏 utf8 输入。此外,您不应将 html 转义数据存储在数据库中。我什至不知道你为什么在这里使用它——你不需要对 html 进行转义来显示它吗?

但是,您正在以错误的方式解决此问题。

  1. 不要使用正则表达式解析/清理 html。使用真正的 html 解析器,例如DOMDocumentorhtml5libtidylib. 不幸的是,PHP 似乎没有像Python 上的 Bleach那样美妙的东西,所以你必须自己动手。带有白名单的 XSLT 样式表似乎是处理这种特殊清理条件的好方法。更新:另一位用户指出HTML Purifier,它也是一个基于白名单的 html sanitizer。我从未使用过它,但它看起来像“PHP 中的漂白剂”。你绝对应该调查。
  2. 宁愿逃跑也不愿消毒。PHP 文化痴迷于清理,这确实是完全错误的。在应用程序(输出和数据库)的边界处转义数据。在您的应用程序的核心,您的数据应该是其本机形式,没有任何转义。

处理的大致轮廓如下:

  1. 输入

    1. 在您的 php 设置中关闭魔术引号。在您的应用程序顶部包含代码,以便在应用程序打开时很难失败:if (get_magic_quotes_gpc()) die ('TURN OFF MAGIC QUOTES!!!!');
    2. 根据每个字段的预期类型验证和规范化/清理输入的特定字段。例如,“美元金额”与列入白名单的 html 片段字段具有不同的验证标准。(也许您应该找到并使用验证库。)
    3. 如果有错误,请使用适当的 HTTP 响应代码将其发回给用户。
    4. 使用支持参数绑定的数据库库(例如PDO带有预处理语句的库)将数据保存到数据库中。这样您就不需要记住手动转义数据。
    5. 成功后,重定向(代码 303)到显示创建或修改记录的页面。
  2. 输出

    1. 从数据库中检索数据。
    2. 将数据提供给模板,该模板是处理数据结构的 html 显示的 PHP 代码。它不应该知道如何检索数据或包含任何“应用程序驱动”行为的详细信息。将模板视为接受数据结构并返回字符串的函数。
    3. 在您的模板中转义您的数据。您的数据的各个字段将需要以不同的方式转义。您几乎总是需要htmlspecialchars在输出之前运行它;您不会这样做的唯一情况是您需要显示的数据已经是html(即您的白名单过滤的 html 字段)。像这样定义一个辅助函数并在您的模板中使用它:

      function h($str) {
          return htmlspecialchars($str, ENT_QUOTES, 'utf-8');
      }
      

      更好的是,尝试使用自动为您转义字符串并要求您明确关闭转义的模板库。(常见的情况应该是简单的避免错误,不得不转义是常见的情况!)

    4. 您的 html 页面是从您的模板返回的字符串。您现在可以将其显示给用户。
于 2013-02-14T17:35:34.167 回答
0

虽然您不必清理您在浏览器中显示或存储在数据库中的自己的字符串数据,但您必须清理您的网站通过 INPUT 元素、TEXTAREA 元素、通过 JavaScript/DOM 事件从键盘获得的所有用户输入,来自上传的文件,以及我忘记列出的所有其他来源。

虽然数据库清理有据可查,并且在最新版本的服务器端语言(如 PHP)中部分强制执行,但仍然没有普遍接受的方法来清理我列出的其他用户输入源。

我自己的贡献是这段 PHP 代码,它允许任何用户输入显示在网页上或通过 GET 或 POST 控件和 FORM 元素中的字段或通过 Ajax 发送到另一个网页,而不会打开您的网站以供恶意使用:

function HTMLToSafeHTML($Str)
    {
    return str_replace(['&','<','>','"','\''], ['&amp;','&lt;','&gt;','&quot;','&apos;'], $Str);
    } // HTMLToSafeHTML

要正确使用此功能,您必须识别和跟踪所有用户输入,然后在显示或以其他方式允许将用户输入解释为 Web 处理或编程的一部分之前调用此功能。识别用户输入允许您仅调用此函数一次。多次调用它会显示其难以阅读的编码,这作为文本没有用。

例如,如果您想以粗体显示某些用户输入的错误消息,则必须在将用户输入封闭之前调用 HTMLToSafeHTML(您可以给它一个更短的名称)<strong>...</strong>以使其变为粗体。虽然显示“ <strong>”是无害的,但显示用户输入可能是恶意用户为了传播病毒或出于其他邪恶目的而故意尝试闯入您的网站的结果,这绝非无害。

于 2019-08-19T20:15:48.053 回答