SQL injection’s less well-known sibling, email header injection, hijacks Web forms that send email. An attacker can use this technique to send spam via your mail server. Any form that constructs email headers from Web form data is vulnerable to this kind of attack. Let’s look at the canonical contact form found on many sites. Usually this sends a message to a hard-coded email address and, hence, doesn’t appear vulnerable to spam abuse at first glance.
However, most of these forms also allow the user to type in his own subject for the email (along with a “from” address, body, and sometimes a few other fields). This subject field is used to construct the “subject” header of the email message. If that header is unescaped when building the email message, an attacker could submit something like “hello\ncc:[email protected]” (where “\n” is a newline character). That would makethe constructed email headers turn into:
To: [email protected]: hellocc: [email protected]
Like SQL injection, if we trust the subject line given by the user, we’ll allow him to construct a malicious set of headers, and he can use our contact form to send spam.
The Solution – We can prevent this attack in the same way we prevent SQL injection: always escape or validate user-submitted content. Django’s built-in mail functions (in django.core.mail) simply do not allow newlines in any fields used to construct headers (the from and to addresses, plus the subject). If you try to use django.core.mail.send_mail with a subject that contains newlines, Django will raise a BadHeaderError exception. If you do not use Django’s built-in mail functions to send email, you’ll need to make sure that newlines in headers either cause an error or are stripped. You may want to examine the SafeMIMEText class in django.core.mail to see how Django does this.