引用/转义邮件正文中的变量


Quoting/Escaping variables in mail body

我感觉有点尴尬,因为我正在用PHP生成邮件正文,而没有转义变量。在HTML中,我使用htmlspecialchars()或类似的函数,对于命令行escapeshellarg(),但对于邮件?例如:

<?php
$usercontent = $_GET['usercontent'];
mail("dummy@nowhere.tld", "My Subject", "My body with $usercontent included");
?>

一个可能的攻击者可以用上面的脚本做什么,我如何防止这样的攻击?或者PHP mail()是保存的,为什么?

请参考示例:

  • 只有正文受到影响(没有标题!)
  • 内容类型为text/plain
  • 一些答案的证据会很好
  • MTA是带有"/usr/sbin/sendmail -t -i"的后缀sendmail

基本的电子邮件正文是纯文本。如果你想要一个不同的类型,如HTML或多部分消息,你需要使用MIME扩展并使用Content-Type指定相应的类型(例如,HTML的text/html或多部分消息的multipart/…)。

因此,从安全的角度来看,没有办法注入任何有害的东西(至少不是按照规范)。即使非ascii字符也应该被正确处理,尽管缺少所使用字符编码的声明。

然而,电子邮件客户端仍然可能存在一些可以被这种方式利用的缺陷。但我对此表示怀疑。

问得好。我不认为您需要转义正文,但我确实知道,如果允许用户输入发件人地址,则可以向邮件添加标题(例如向数千个地址发送密件)。因此,如果您在其中放入变量,一定要检查换行符('n'r),以确保没有添加额外的标题。

这样想:"任务是最高机密,目的地未知。"我们可能不知道什么样的客户端将读取消息,但我们可以猜测,我们不希望在其中显示实时的、用户提供的、未转义的HTML。由于许多客户端读取HTML格式的邮件,最好的做法是htmlentities()用户提供的电子邮件正文。

我的escaper类中的一个方法。

<?php
class escaper
{
    public function superHtmlEntities($string)
    {
        return htmlentities($string, ENT_QUOTES | ENT_HTML5, 'UTF-8', true);
    }
}
?>

========================================

在你做研究的时候,至少要考虑这样的事情。

<?php
$esc = new Escaper();
$usercontent = $_GET['usercontent'];
mail("dummy@nowhere.tld", "My Subject", $esc->superHtmlEntities("My body with $usercontent included"));
?>

这是不安全的XSS攻击,因为如果你的邮件包含HTML,有人可以注入到邮件。

好的行为是检查您期望拥有的有效数据。如果我是你,我会转义这个字符串。它的成本几乎为零,你也不必担心不使用它的后果。