This site nicely explains the problem. Essentially, nearly all php mail() examples that are given are vulnerable to header injection attacks. The referenced site gives a regex sanitation solution but I'm not satisfied with it. Is there a built in header sanitation function? What would one need to do to really protect against this sort of attack?
3 Answers
As a matter of fact PHP includes a function to check the validity of a provided address.
http://php.net/manual/en/function.filter-var.php
http://www.php.net/manual/en/filter.filters.validate.php
Ex: filter_var($_POST['from'], FILTER_VALIDATE_EMAIL) ? send() : die("You murdered me. D:");
-
-
1I'd assume that valid email addresses can't contain characters that can cause header injection attacks (but that isn't guaranteed unless one read the spec). Let's assume so. What about injection attacks with the subject? filter_var won't help in that case (at least I don't think it will) Dec 15, 2010 at 4:23
This is how pear does it in their 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);
}
}
Obviously, for this method to be adapted to work with the built-in mail() function, some work will need to be done. Instead of working with associative arrays for headers, the mail() function just accepts a string. So you (the user of mail()) would have to sanitize each piece of the header similar to the above as you build up the headers string.
I'd like to hear in the comments if this indeed covers every injection threat (from those that are more experienced with issues like this).
Clearly you can never trust data from users. The solution is not to rely on convinient sanitizing in the header function, but instead never trust DIRTY data from your users.
No matter when and how, but if your data is coming from outside you need to clean it. In this example a simple / would escape the /n character, and the attack would not work.
-
3I agree with your assessment of the problem but my issue is how to go about sanitizing input. For html you have html entities. For sql you have prepared statements. In both cases you don't try and do it yourself (because you'll most likely miss an edge case). That's what I'm worried about here -- edge cases. Sure the author's (and your) solution will fix the examples given. But is this really a universal solution? Dec 11, 2010 at 16:53
-
I understand. I've actually seen header injection risks before, but then it was not possible to inject because of the php's magic quotes. I wish I could recommend you a good sanitizing library, but I dont know of any good ones yet. Dec 11, 2010 at 17:15
-
3Magic Quotes is deprecated and being removed from php (last I checked). And I don't think it would solve these problems. Jun 16, 2011 at 7:40