【问题标题】:Sanitize array before echo PHP在回显 PHP 之前清理数组
【发布时间】:2016-10-09 20:31:35
【问题描述】:

您认为清理以下数组的最佳方法是什么?我正在考虑在每个 $row 之前添加 htmlentites 或者使用下面的方法。

<?php 
$result = $conn->query("SELECT formula.id, tokens, direction, graph, module FROM formula INNER JOIN syntics ON formula.moduleid = syntics.id"); 

while ($row = $result->fetch_array())
filter_var_array($row, FILTER_SANITIZE_SPECIAL_CHARS); // OK?

echo                    "<td>". 
     $row['tokens']    ."<td>". 
     $row['direction']  ."<td>". 
     $row['graph']     ."<td>".
     $row['module ']   ."<td>". 
     "<a href='upong.php?soya=" . $row['id'] . "'>Specific type</a>" . "</tr>";
?>

【问题讨论】:

  • 重要的是您的数据是什么。前 4 个字段是保存为文本还是 html?我可以假设 id 是一个整数吗?
  • 前4个字段保存为html。你是对的,id 是整数。
  • 你从数据库输出,你认为你需要“清理”什么?
  • 请您提供更多信息,说明您为什么要进行消毒?你想防止什么?
  • 我认为如果不阻止字符、DB 和实际输出之间的界限,就会出现 XSS 风险。如果黑客可能会以某种方式将输出从 DB 更改为自己的字符串/脚本。当用户单击“特定类型”时,它会被定向到另一个页面。然后在查询之前对接收 ID 进行清理。

标签: php


【解决方案1】:

我觉得您可以从有关消毒和逃生主题的一些一般信息中受益。

  • 要了解如何编写安全的 PHP 代码,您需要防止 针对 XSS。
  • 为了防止 XSS,您需要 实施正确的输出转义,可能需要实施数据清理。
  • 要实施数据清理和输出转义,您需要了解为什么会出现问题以及如何正确处理。

消毒

应在将数据保存到数据库之前进行清理。它确保不应该保存到数据库中的东西不是。在您从数据库中读取数据后再次执行此操作也很好,以防您遗漏了某些内容并且您的数据库现在包含有害内容。通常,如果您只是存储文本,您可能希望允许保存任何文本,在这种情况下,清理并不是真正必要的。但听起来你正在存储 html...

如果您要存储 html,您可能计划在某个时候将其输出到浏览器,并且您不希望它包含有害的脚本以供用户执行。清理 html 以删除有害的 javascript 实际上非常非常困难,因为您可以通过多种方式插入 javascript。整个 PHP 库(例如wp_kses_*)已专门为此编写,仅删除所有 标记是不够的,正如一些 SO 答案所建议的那样。此外,您还需要使您的 html 清理代码保持最新,以防止最新的攻击。总而言之,这是一个非常高风险/维护的解决方案。如果你想走这条路,有一些解决方案here

通常您会希望让您的用户能够使用 html 提供的子集(例如粗体、斜体、下划线和可能的一些颜色)来格式化他们的文本,更好的方法是使用更轻量级的语言,例如 @ 987654323@或BBCode

您还应该考虑将您的字段仅保存为文本,并在您的应用程序中完全处理样式。

输出转义

这是输出数据之前的步骤。当您拼凑 HTML 以在 PHP 中输​​出时,您需要将任何不是 html 的内容转换为安全的 html。如果您使用模板语言,则会自动为您处理。在我看来,这是当今 PHP 开发人员最容易误解的概念,不幸的是,它是最重要的概念之一。我不会在这里讨论它,但我强烈推荐this further reading

重要更新

此代码不是数据清理,它是输出转义。

filter_var_array($row, FILTER_SANITIZE_SPECIAL_CHARS);

我现在可以看到令人困惑的是,“Filter”这个词在这个答案中具有如此笼统的含义,可以说是指both消毒和逃生。我已将其从我的答案中删除,以帮助消除任何混淆。

您的示例 - 消毒

我不会说永远不要将 html 存储在数据库字段中,但这种方式要困难得多。您需要决定什么是预期的和有效的。如果您使用有关特定数据的更多详细信息更新您的问题,那么这些限制应该是什么就会变得很清楚。

您的示例 - 输出转义

如果您的变量已经包含格式良好的 HTML 片段字符串,那么您可以使用“.”安全地附加您的变量。 (字符串连接运算符)在打开和关闭标记内。您在问题代码中输入的内容是正确的。但是,我更喜欢使用带有短标签的直接输出,因为它使代码更具可读性,并且实际上不需要将所有内容都放入 PHP 字符串中。

<td><?= $row['tokens'] ?></td>
<td><?= $row['direction'] ?></td>
<td><?= $row['graph'] ?></td>
<td><?= $row['module'] ?></td>

注意:如上所述,通过输出 html,您要求客户端信任、解析和显示它。如果这些变量确实包含无效或错误的 HTML,则说明您的清理存在问题。

  • 输出转义应该/不会清理您的数据。
  • 清理应该/不应该转义您的数据。

它们只是两个不同的概念一起工作。

由于您的 id 应该是数据库中的一个整数,因此您可以像这样对其进行强制转换以确保它是。

<a href='upong.php?soya=<?= (int)$row['id'] ?>Specific type</a>

如果该值不能转换为整数(因为发生了您没有考虑到的意外情况),那么您的 url 中最终会出现 0,这通常不会那么有害。

【讨论】:

  • 非常感谢您的澄清。这确实是一个非常有趣的主题,我将继续阅读链接。数据保存自 echo => $_POST => filter_input => query => db。然后输出 db => query => echo。所以我应该对每一行使用 htmlentites/specialchar 来最小化 XSS,如 htmlentities($row['tokens']) htmlentities($row['direction'] etc?
  • 这取决于数据是什么以及您在什么上下文中输出。从您的 cmets 中,您说这 4 个字段是 html 而不是文本,并且由于您在“”标签之间插入它们,因此您的上下文也是 html。所以在这种情况下,你不需要逃避任何事情(我在上面撒了谎)。事实上,像这样转义它们会将 html 显示为纯文本,以便您可以看到标签。这就是为什么在您的数据库中存储 html 时,您应该确保在输出之前对其进行清理并再次对其进行清理。
  • 我现在很迷茫。数据从用户输入存储为 POST,然后进行清理并将查询插入数据库。输出在我的第一篇文章中声明。如果理解正确,我需要在回显之前对整个阵列进行消毒?以什么方式输入最一致?
  • 请更新您的问题以包含您的一些数据。重要的是数据是什么
【解决方案2】:

我相信您必须使用自定义过滤器来清理您的阵列。 请阅读url中的php文档

【讨论】:

    【解决方案3】:

    如果您担心 XSS 攻击,那么您真的应该在将输入插入数据库之前通过使用 htmlentities() 处理该问题。永远不要相信用户输入。

    【讨论】:

    • 我强烈建议永远不要在数据上持久化之前使用 htmlentities。清理和转义之间是有区别的,假设输出格式总是 html 是不好的。
    猜你喜欢
    相关资源
    最近更新 更多
    热门标签