Quoting/Escaping variables in mail body

2019-02-21 11:06发布

问题:

I am feeling a bit awkward, because I am generating a mail-body with PHP without escaping the variables. In HTML I am using htmlspecialchars() or similar functions, for command lines escapeshellarg(), but for mails? For example something like this:

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

What could a possible attacker do with a script like the one above and how could I protect against such an attack? Or is PHP mail() save and why?

Update

Please refer to the example:

  • Only the body is affected (No Headers!)
  • Content-Type is text/plain
  • Some proof to the answer would be nice
  • MTA is a postfix sendmail with "/usr/sbin/sendmail -t -i"

回答1:

The basic e-mail message body is plain text. If you want a different type like HTML or a multipart message, you need to use the MIME extension and specify the type accordingly using Content-Type (e.g. text/html for HTML or multipart/… for a multipart message).

So from the security perspective, there is no way to inject anything harmful (at least not as per specification). Even non-ASCII characters should be handled correctly despite the lacking declaration of the used character encoding.

However, there still may be some flaws in e-mail clients which can be exploited this way. But I doubt that.



回答2:

It is not secured against XSS atack because if your mail contains HTML someone can inject it into mail.

The good behaviour is to check and valid data which you expect to have. If I were you I would escape this string. It costs almoust nothing and you don't have to worry about consequences of not using it.



回答3:

Good question. I don't believe you need to escape the body text, but I do know it's possible to add headers to a mail (like a BCC to thousands of addresses) if you allow the user to input a from address. So if you put variables in that, definitely check for newlines (\n and \r) to make sure no additional headers are added.



回答4:

Think of the body of the email this way: "Mission top secret destination unknown." We may not know what kind of client will read the message, but we can guess that we do not want live, user supplied, unescaped HTML to show up in it. Since many clients read mail in HTML, the best thing to do would be to htmlentities() the user supplied e-mail body.

A method from my escaper class.

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

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

At minimum, consider something like this and more as you do your research.

<?php
$esc = new Escaper();

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