【问题标题】:htmlentities - How do I keep my form safe in PHP?htmlentities - 如何在 PHP 中保持表单安全?
【发布时间】:2018-04-02 17:44:32
【问题描述】:

我有一个需要主题、姓名、电子邮件和消息的小型联系表单。所有这些字段都经过以下处理:

function sanitize($string){
    return htmlentities($string, ENT_QUOTES, 'UTF-8');
}

我使用 PHP 中的 mail() 函数发送电子邮件,并使用 subject 字段作为电子邮件标题/主题。问题是在主题中我有一个单引号:

I'd like to explore

但是在我清理它之后,我在收件箱中收到了电子邮件,但是那个单引号被清理了并且看起来像这样:

I'd like to explore

如何确保我的表单安全,但同时如何让我的电子邮件主题使用单引号而不是 'd-thing?

【问题讨论】:

  • 安全来自于您如何处理用户生成的输入。当您想将用户生成的内容打印为 html 时,Htmlentities 很有用。但是,如果您处理的是纯文本,则可以将其存储为纯文本。您无需跳过转换过程。
  • @k0pernikus 你应该把这一切都放在答案中
  • 编码与清理不同。编码为 HTML 对电子邮件、数据库、JavaScript、URL 等没有帮助。不要盲目地将所有内容编码为 HTML。

标签: php html-encode html-escape-characters


【解决方案1】:

您使用您的sanitize 函数存储数据,如果您想显示数据,您需要“去消毒”为原始格式。

$str = 'I'd like to explore';

echo html_entity_decode($str, ENT_QUOTES, 'UTF-8');

严格来说,存储任何数据都不会带来安全风险。然而,数据存储的过程可能会导致安全问题。使用 HTML 实体通常用于将数据存储在数据库中并在以后使用。但是存储这些数据的更好方法是使用准备好的语句,这完全没有必要。

问题真的是,您要清理的存储是什么。

【讨论】:

  • 我只是想向我的 roundcube 电子邮件地址发送一封电子邮件,所以基本上你是在说我不需要为发送电子邮件而清理该表格? :-?
  • 您确实需要清理格式错误的输入,可能需要(重新)验证码以避免机器人发送邮件。此外,它很大程度上取决于您在表单中发送的内容,也许是文件?如果是这样,请过滤特定的文件类型。但简短的回答是否定的。
  • 我只发送文本:3 个单选按钮 - 选择主题、姓名、电子邮件和消息 - 没有文件 - 如果复选框,我还将他们的电子邮件插入数据库已检查-所以我想我应该只清理该电子邮件,但实际上我在执行查询之前已经准备好了(PDO 准备功能)。但是我同意圆形立方体,如果我不对这些字段进行消毒,圆形立方体会出现什么问题吗? :-s
  • Sanitize 是名称 [a-zA-Z0-9 ] ,使用 filter_var 检查电子邮件是否正确并验证复选框是否只是布尔值。就是这样。
  • @emma 我不同意filter_var 用于电子邮件检查,因为它仅适用于拉丁字符(无 UTF8)并且它拒绝 RFC5321 允许的有效电子邮件地址。我宁愿将电子邮件地址也视为纯文本。见:php.net/manual/en/function.filter-var.php#112492
【解决方案2】:

htmlentities 用于在您自己的网站上将用户生成的内容打印为 HTML 时使用。用户生成的内容可能包含破坏 HTML 的符号,因此它用 HTML 实体替换字符。 (错误的' 可能会终止字符串,或者如果巨魔插入</div>,您网站的整个布局就会中断。)

'-thing 是',而,从任何 html-rendering-engine 的角度来看,都是一个撇号,并且将这样显示。你可以找到a list of these entities online

该过程的逆过程是html_entity_decode,以便再次从中获取纯文本。

关于保持表单安全的用例:htmlentities 不适合做这件事。

如果您想以纯文本形式发送该电子邮件,请将其保留为纯文本。确实,您不应该信任用户生成的内容和行为,但是您应该防范数据库插入问题(准备好的语句)并防止在表单本身上重复 POST,以免向人们发送垃圾邮件。

然而,将用户输入视为原始文本并将该内容作为原始文本发送并没有固有的危害。 (如果您想发送包含用户生成内容的 HTML 电子邮件,那么 htmlentities 也会派上用场。)

【讨论】:

    【解决方案3】:

    消毒是在上下文中完成的。换句话说,您应该知道您正在“清理”什么:SQL 注入、html 脚本攻击等等。考虑到这一点,正确的方法是分别处理每个问题:在存储在数据库中时清理 SQL 注入,但尽可能将数据存储在“原始”附近。这意味着数据库中的数据将被“净化”。然后,根据您打算如何处理数据,您相应地对其进行处理:发送电子邮件?只是转储内容。在网页上显示? html_entities它。

    请注意,每次输出内容时不必使用消毒剂处理的“优化”问题是不同的。如果需要,必须单独处理。

    多年来,这已证明对我来说是一种合理的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-24
      • 2013-02-17
      • 2012-03-12
      • 2015-07-23
      • 1970-01-01
      • 2014-07-06
      • 2016-11-29
      • 2017-10-27
      相关资源
      最近更新 更多