【问题标题】:Is FILTER_SANITIZE_EMAIL pointless if already using FILTER_VALIDATE_EMAIL?如果已经使用 FILTER_VALIDATE_EMAIL,FILTER_SANITIZE_EMAIL 是否毫无意义?
【发布时间】:2011-11-09 13:54:05
【问题描述】:

我只是在创建一个注册表单,我只想将有效且安全的电子邮件插入数据库。

为了安全起见,一些网站(包括 w3schools)建议在运行 FILTER_VALIDATE_EMAIL 之前运行 FILTER_SANITIZE_EMAIL;但是,这可能会将提交的电子邮件从无效的电子邮件更改为有效的电子邮件,这可能不是用户想要的,例如:

用户有电子邮件地址 jeff!@gmail.com,但不小心插入了 jeff"@gmail.com。

FILTER_SANITIZE_EMAIL 将删除 " 使 FILTER_VALIDATE_EMAIL 所说的电子邮件 jeff@gmail.com 有效,即使它不是用户的实际电子邮件地址。

为了避免这个问题,我打算只运行 FILTER_VALIDATE_EMAIL。 (假设我不打算输出/处理任何声明无效的电子邮件)

这将告诉我电子邮件是否有效。如果是这样,则不需要通过 FILTER_SANITIZE_EMAIL 传递它,因为任何非法/不安全的字符,都会导致电子邮件无效,对吗?

我也不知道任何被 FILTER_VALIDATE_EMAIL 批准为有效的电子邮件可用于注入/xss,因为空格、括号 () 和分号会使电子邮件无效。还是我错了?

(注意:除此之外,我将使用准备好的语句插入数据,我只是想澄清一下)

【问题讨论】:

  • 所以,下面的所有答案实际上都证明了 FILTER_SANITIZE_EMAIL 确实毫无意义,因为我们可以单独使用 FILTER_VALIDATE_EMAIL。
  • 是的,这是因为它正在测试字符串是否与电子邮件类型的字符串匹配。它在失败时返回 false,因此任何风险都在攻击点被抵消。
  • 我想说这个问题最大的争论是将净化过滤器定性为“毫无意义”(见问题标题)。拥有这个过滤器确实很有用,甚至是必要的。这个问题最好是询问是否有必要对当前已经通过验证过滤器的字符串运行清理过滤器。并且删除表征过滤器本身的语言是“无用的”。为了清楚起见,我来到这里是因为我有同样的好奇心。我保留了两个JIC。此外,如果验证例程发生变化,我不希望后端受到损害。

标签: php xss


【解决方案1】:

这是仅插入有效电子邮件的方法。

<?php
$original_email = 'jeff"@gmail.com';

$clean_email = filter_var($original_email,FILTER_SANITIZE_EMAIL);

if ($original_email == $clean_email && filter_var($original_email,FILTER_VALIDATE_EMAIL)){
   // now you know the original email was safe to insert.
   // insert into database code go here. 
}

FILTER_VALIDATE_EMAILFILTER_SANITIZE_EMAIL 都是有价值的函数,并且有不同的用途。

验证是测试电子邮件是否为有效格式。 消毒是从电子邮件中清除坏字符。

<?php
$email = "test@hostname.com"; 
$clean_email = "";

if (filter_var($email,FILTER_VALIDATE_EMAIL)){
    $clean_email =  filter_var($email,FILTER_SANITIZE_EMAIL);
} 

// another implementation by request. Which is the way I would suggest
// using the filters. Clean the content and then make sure it's valid 
// before you use it. 

$email = "test@hostname.com"; 
$clean_email = filter_var($email,FILTER_SANITIZE_EMAIL);

if (filter_var($clean_email,FILTER_VALIDATE_EMAIL)){
    // email is valid and ready for use
} else {
    // email is invalid and should be rejected
}

PHP 是开源的,因此这些问题只需使用它即可轻松回答。

Source for FILTER_SANITIZE_EMAIL:

/* {{{ php_filter_email */
#define SAFE        "$-_.+"
#define EXTRA       "!*'(),"
#define NATIONAL    "{}|\\^~[]`"
#define PUNCTUATION "<>#%\""
#define RESERVED    ";/?:@&="

void php_filter_email(PHP_INPUT_FILTER_PARAM_DECL)
{
    /* Check section 6 of rfc 822 http://www.faqs.org/rfcs/rfc822.html */
    const unsigned char allowed_list[] = LOWALPHA HIALPHA DIGIT "!#$%&'*+-=?^_`{|}~@.[]";
    filter_map     map;

    filter_map_init(&map);
    filter_map_update(&map, 1, allowed_list);
    filter_map_apply(value, &map);
}    

Source for FILTER_VALIDATE_EMAIL:

void php_filter_validate_email(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
{
const char regexp[] = "/^(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){255,})(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){65,}@)(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22))(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\\]))$/iD";

pcre       *re = NULL;
pcre_extra *pcre_extra = NULL;
int preg_options = 0;
int         ovector[150]; /* Needs to be a multiple of 3 */
int         matches;


/* The maximum length of an e-mail address is 320 octets, per RFC 2821. */
if (Z_STRLEN_P(value) > 320) {
    RETURN_VALIDATION_FAILED
}

re = pcre_get_compiled_regex((char *)regexp, &pcre_extra, &preg_options TSRMLS_CC);
if (!re) {
    RETURN_VALIDATION_FAILED
}
matches = pcre_exec(re, NULL, Z_STRVAL_P(value), Z_STRLEN_P(value), 0, 0, ovector, 3);

/* 0 means that the vector is too small to hold all the captured substring offsets */
if (matches < 0) {
    RETURN_VALIDATION_FAILED
}

}

【讨论】:

  • Validation is testing if the email is a valid format. Sanitizing is to clean the bad characters out of the email. 这是问题的一部分。此答案未解决所要求的内容。
  • 好的,很公平@Izkata。已更新答案,因此他只能插入有效的电子邮件。
  • 您能否举一个例子,清楚地说明如何清理电子邮件并通过验证?似乎您的第一个块仅在无法清理的情况下才使电子邮件通过,还是我错过了明显的东西?如果是这样,为什么首先要进行消毒?看起来多余。
  • 好的,添加了一个示例,清楚地显示了应该如何使用消毒。在第一个示例中,我关注的是它们返回的内容以及应该如何使用它们。感谢您的反馈和建议。
  • filter_var($email,FILTER_SANITIZE_EMAIL)修改用户输入的地址有什么意义?如果提供的电子邮件地址无效,则应予以拒绝,而不是盲目地通过清理“修复”并事后验证。
【解决方案2】:

执行此操作的“正确”方式是两次询问用户的电子邮件(这是常见/良好的做法)。但要回答您的问题,FILTER_SANITIZE_EMAIL 并非毫无意义。它是一个过滤器,可以清理电子邮件,并且做得很好。

您需要了解validates 的过滤器会返回truefalse,而sanitizes 的过滤器实际上会修改给定的变量。两者作用相同。

【讨论】:

  • The two do not serve the same purpose. 这正是问题的一部分。这没有解决所要求的内容。
  • filter_var 带有验证过滤器(例如 FILTER_VALIDATE_EMAIL)不会返回 truefalse
  • 这是误导。 VALIDATE 过滤器并不都返回布尔值。例如,数字返回数字。
【解决方案3】:

我读了同一篇文章并想到了同样的事情:仅仅改变一个无效的变量是不够的。我们需要真正告诉用户存在问题,而不是仅仅忽略它。我认为解决方案是将原始版本与经过消毒的版本进行比较。 IE。要使用 w3schools 示例,只需添加:

$cleanfield = filter_var($field, FILTER_SANITIZE_EMAIL);

if ($cleanfield != $field){
    return FALSE;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-17
    • 1970-01-01
    • 1970-01-01
    • 2021-04-07
    • 2011-09-02
    • 1970-01-01
    • 2021-01-21
    • 1970-01-01
    相关资源
    最近更新 更多