24

Sure thing, when using MySQL you use mysqli_real_escape_string() and check that the type of input received is the kind you expect (string, number, etc) and you can be pretty sure you can use it as input to mysqli_query() quite securely... right?

Well, the questions are:

  • What is the best way to escape a string that's going to be used in mail()?
  • If the email recipient will be the email address entered in a text field, what things should I be careful about to avoid injections or exploits?

I have a pretty good idea how to do this but I'm digging into best practices on this subject to know if I'm missing something, or if there's a better way.


EDIT: The idea of this question is not to have THE answer, but to make a comprehensive collaborative list of all the things to take care of when doing email with PHP.

Kevin Fegan
  • 1,292
  • 1
  • 16
  • 29
Juan Ignacio
  • 3,217
  • 8
  • 33
  • 53
  • 1
    I can think of XSS attacks and header injections maybe; so sanityze your html (if you're using that MIME type), and be sure no-one enters custom code in your mail headers – Damien Pirsy Nov 09 '11 at 21:33
  • Strip any non-printable character, use US-ASCII encoding. Remove \r\n characters as well. Convert tabs into spaces. – hakre Nov 09 '11 at 21:56
  • 1
    Excellent question. I only wish I hadn't exhausted my pathetic vote limit for the day. – Lightness Races in Orbit Nov 09 '11 at 22:38
  • You say you have a pretty good idea, so why not show what you came up with so noone has to repeat your work? ;-) – CodeCaster Nov 09 '11 at 22:58
  • Notice I said "idea", not "I know" and that because I meant it that way. I have ideas, I know some stuff but I'm no pro in this subject so I thought maybe a community collaborative list of things to take care of was better than me mentioning my guesses. And I'm doing this question because I googled a lot and I found lots of material on the matter but no comprehensive article (nothing even close to "the definite guide to safe php emailing which would be nice) – Juan Ignacio Nov 10 '11 at 14:50

1 Answers1

13

The idea behind email-injection is that attacker inject line feed (LF) in the email headers and so he adds as many headers as he wants. Stripping those line feeds will protect you from this attack. For detailed info check http://www.phpsecure.info/v2/article/MailHeadersInject.en.php

The best practice is to rely on a well-written, frequently updated and widely-used code. For that I would suggest using PEAR_MAIL OR Zend_Mail

If you don't want to load those modules or you need to keep things very simple. You can extract the filtering functionality from those modules. Although I do recommend to use them and frequently update the library so that if new attack appears in future you will just need to update your library (Pear or Zend) and you are done.

This is the function that sanitize headers in Pear Mail package:

function _sanitizeHeaders(&$headers)
{
    foreach ($headers as $key => $value) {
        $headers[$key] =
            preg_replace('=((<CR>|<LF>|0x0A/%0A|0x0D/%0D|\\n|\\r)\S).*=i',
                         null, $value);
    }
}

Zend_Mail uses different filter for email,name and other fields:

function _filterEmail($email)
{
    $rule = array("\r" => '',
                  "\n" => '',
                  "\t" => '',
                  '"'  => '',
                  ','  => '',
                  '<'  => '',
                  '>'  => '',
    );

    return strtr($email, $rule);
}

function _filterName($name)
{
    $rule = array("\r" => '',
                  "\n" => '',
                  "\t" => '',
                  '"'  => "'",
                  '<'  => '[',
                  '>'  => ']',
    );

    return trim(strtr($name, $rule));
}

function _filterOther($data)
{
    $rule = array("\r" => '',
                  "\n" => '',
                  "\t" => '',
    );

    return strtr($data, $rule);
}
IMSoP
  • 89,526
  • 13
  • 117
  • 169
Laith Shadeed
  • 4,271
  • 2
  • 23
  • 27
  • I think there is another attack which allow to add multiple messages after each body. It's not that well documented however. [Suhosin](http://www.hardened-php.net/suhosin/) protects PHP against mail header injection. – hakre Nov 09 '11 at 22:48
  • Seems very interesting library. This is the first time I see it. But how we can make sure it does not have any side effect on the PHP itself, I checked its source code it plays with the PHP internals. Is it used in some large, trusted websites ? – Laith Shadeed Nov 10 '11 at 11:20
  • Well, it ships per default with PHP on Debian ;) – hakre Nov 10 '11 at 11:22
  • Readers coming across this might want to note that PEAR_Mail is no longer "frequently updated". The last release was over a year ago, and the one before that was 6 years before. Zend_Mail (now branded zend-mail) looks to still be actively maintained, it's docs are now here: http://zendframework.github.io/zend-mail/intro/ Other popular and currently maintained libraries are [PHPMailer](https://github.com/PHPMailer/PHPMailer) and [Swift Mailer](http://swiftmailer.org/). – IMSoP Mar 06 '17 at 14:17