SitePoint Sponsor

User Tag List

Results 1 to 18 of 18

Thread: email injection

  1. #1
    SitePoint Zealot
    Join Date
    Nov 2004
    Location
    Lytham
    Posts
    163
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    email injection

    I have the following code and I have tried to stop e-mail injection attacks but they still seem to be occuring

    PHP Code:
    $name strip_tags($_POST['name']) ;
    $number strip_tags($_POST['number']) ;
    $email strip_tags($_POST['email']);

       if (
    eregi("\r",$email) || eregi("\n",$email)){
         die(
    "E-mail Injection");
       }

    $comments strip_tags($_POST['comments']);
    $ownermail strip_tags($_POST['ownermail']);

    $cc "info@example.com";

    $to  "$ownermail"

    $subject "Website Enquiry";
      
    $message "message sent via www.example.com\n\n";
    $message .= "Name: $name\n";
    $message .= "Tel: $number\n";
    $message .= "Email: $email\n\n";
    $message .= "$comments\n\n";
      
    $headers "To: $ownermail\r\n"
    $headers .= "From: $email\r\n"
    $headers .= "Reply-To: $email\r\n"
      
    mail ($to$subject$message$headers); 
    what am I missing to make this safe?

  2. #2
    Programming Team silver trophybronze trophy
    Mittineague's Avatar
    Join Date
    Jul 2005
    Location
    West Springfield, Massachusetts
    Posts
    16,445
    Mentioned
    160 Post(s)
    Tagged
    1 Thread(s)

    securing email form

    My suggestion in this thread may be helpful
    http://www.sitepoint.com/forums/showthread.php?t=298559

  3. #3
    SitePoint Zealot
    Join Date
    Jun 2002
    Posts
    128
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

  4. #4
    SitePoint Zealot
    Join Date
    Nov 2004
    Location
    Lytham
    Posts
    163
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    As you can see from the code I posted above I've put the code suggested in to stop the e-mail injection:

    PHP Code:
    $email strip_tags($_POST['email']); 

       if (
    eregi("\r",$email) || eregi("\n",$email)){ 
         die(
    "E-mail Injection"); 
       } 
    however I still seem to be getting some messages through, one of the articles suggested above says these are test messages but I don't know how to stop them

  5. #5
    Programming Team silver trophybronze trophy
    Mittineague's Avatar
    Join Date
    Jul 2005
    Location
    West Springfield, Massachusetts
    Posts
    16,445
    Mentioned
    160 Post(s)
    Tagged
    1 Thread(s)

    stop email abuse

    I don't know how well testing for newlines works, but I posted a couple of snippets that use substr to limit input length and test for valid domain in the thread I referred to previously.

  6. #6
    SitePoint Zealot
    Join Date
    Apr 2005
    Posts
    139
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Im posting this here so i dont open a new thread...

    There is something i dont quite get about email injection in forms.
    If in my script:

    PHP Code:
    $to ''// Hardcoded
    $subject ''// Hardcoded
    $headers ''// Hardcoded
    $message ''// Dynamic (entered by user)
    mail($to,$subject,$message,$headers); 
    The only dynamic variable is $message and all the other 3 ($to, $subject and $haders) are HARDCODED, can someone exploit my form?

    I added referer check to my forms, filtering specific values, and other checks. But my question is...can someone exploit it by using the $message variable OR they can only exploit it if one of my header variables is dynamic?

    Thanks in advance.

  7. #7
    SitePoint Zealot
    Join Date
    Jun 2004
    Location
    Netherlands
    Posts
    172
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    It seems it is a widespread problem the last couple of weeks. People getting spammed on their contact forms all over the place. There are many, many solutions suggested. Now, the question is, which one(s) work the best? I'm afraid I can't tell for sure.
    First here the problem is explained very well, and the following suggested as a solution:

    Code:
    <?php $from=$_POST["sender"];
    if (eregi("\r",$from) || eregi("\n",$from)){
         die("Why ?? :(");
       }
    On phpnet here, someone suggests the following:
    Code:
    <?php
    if(eregi("MIME-Version: ",$_POST['field1'].$_POST['feild2'].$_POST['etc'])){die('Get out, spammer.');}
    ?>
    On codingforums, another solution is presented:
    Code:
    <?php
    
    function email_injection_filter($formInput) 
      { 
      $injectionStrings = array("apparently-to", 
                                "bcc", 
                                "boundary=", 
                                "charset", 
                                "content-disposition", 
                                "content-type", 
                                "content-transfer-encoding", 
                                "errors-to", 
                                "in-reply-to", 
                                "message-id", 
                                "mime-version", 
                                "multipart/mixed", 
                                "multipart/alternative", 
                                "multipart/related", 
                                "reply-to", 
                                "x-mailer", 
                                "x-sender", 
                                "x-uidl" 
                                ); 
      foreach ($injectionStrings as $spam) 
        { 
        $pos = strpos(strtolower($formInput), $spam); 
        if ($pos !== false) 
          { 
          error_log(...) 
          exit("<html><title>Fatal Error</title><body><p>We're sorry, your message could not be processed due to a fatal error.</p><p>Please contact us at 1-800-xxx-xxxx.</p></body></html>"); 
          } 
        } 
      }
    
    $sendto="myname@mydomain.com"; 
    $emailsubject="Reply from Website"; 
    $thankyou="http://www.mydomain.com/thanks.html"; 
    $msg = 'Tel: ' . $visitorPhone . "\r\n" . stripslashes($comments); 
    $from = "From: ".$_POST['visitorName']." <".$_POST['visitorEmail'].">\r\n"; 
    
    if ($_POST['submit_x']) { 
    
       foreach ($_POST as $formInput) 
         { 
         email_injection_filter($formInput); 
         }
    
    mail($sendto, $emailsubject, $msg, $from); 
    header("Location: $thankyou"); 
    } 
    ?>
    and last but not least a very long thread on anders.com

    Any suggestions? Which solution is best for using in simple contact forms?

    EDIT:
    another suggested solution was to use mysql_real_escape_string function:
    Mackan from Sweden
    #30 posted on Sat, Jul 30, 2005 03:48 PM
    If you use PHP:

    Run function mysql_real_escape_string() on your POST-data. This function will replace the following characters: \x00, \n, \r, \, ', " and \x1a. For more information read the manual:
    http://se2.php.net/manual/en/functio...ape-string.php
    Last edited by matthijsA; Sep 14, 2005 at 01:39.

  8. #8
    SitePoint Zealot
    Join Date
    Apr 2005
    Posts
    139
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I also saw all those posible solutions. Although it dont think that the last one it's a very good one (mysql_real_escape_string), because mysql_real_escape_string is a MySQL specific function and we dont have MySQL in our form examples.

    I guess the first thing before finding a solution, would be to know exactly where is the problem...

    in the sender variable?
    In the message variable?
    In every dynamic variable?
    What happens if i have all hard-coded and the only dynamic variable is the message? Can they still change the headers?

    Nicolas

  9. #9
    SitePoint Zealot
    Join Date
    Jun 2004
    Location
    Netherlands
    Posts
    172
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    The problem is in any variable. First, a spambot runs tests on every formfield, with different injection methods. If it succeeds in one of the fields, a cc: or bcc: message is sent to some email. As soon as that email arrives, they/it know/knows a form has a weak spot. From that moment on LOTS of mail is going to be injected via the form.

    The best solution in my opinion is to filter for any possible injection attack, and as soon as a suspicious data is entered exit/die the script. That's why I like the solution from codingforums I mention above. If you only replace the bad input with empty string by using some regexp still lets the mails arrive. Not good.

    The latest variant I found is from http://www.downforce.info/2005/09/15...ime-form-spam/:

    PHP Code:
    foreach ( $_POST as $key => $value ) {
    $postVars .= $value;
    }

    if(
    eregi(”MIME-Version:,$postVars)) {
    die(
    ’Your message containts the words
    MIME
    -Versionthis is considerd as spam!);

    But this is basicly a simplified version of the other one.

    Another one is from Chris Snyder himself http://blogs.apress.com/archives/000633.html:

    PHP Code:
    <?php
    // email validation function
    function email_checker$string ) {
      
    // validate against regex here ...
      
    return $string;
    }

    // Check email header inputs for CR and LF
    function email_input$string ) {
      if ( 
    strpos$string"\r" )!==FALSE || strpos$string"\n" )!==FALSE ) {
        exit( 
    "No thanks." );
      }
    }

    // hardcoded to address
    $to 'csnyder@chxo.com';

    // get other vars from post
    if ( !empty( $_POST ) ) {
     
      
    // check header inputs!
      
    $name email_input$_POST['name'] );
      
    $email email_inputemail_checker$_POST['email'] ) );
      
    $subject email_input$_POST['subject'] );

      
    $comment $_POST['comment'];

      
    // build better headers
      
    $headers "From: $name\r\nReply-to: $email\r\n";

      
    // send the comment to webmaster
      
    mail$to$subject$comment$headers );

    }

    ?>
    I'm no regexp-expert myself, but it seems there are 2 classes of solutions:
    the ones looking for strings that contain "bcc", "cc", MIME-Version, etc etc.
    And the ones looking for \n and/or \r

    It's all very sad.

  10. #10
    SitePoint Zealot
    Join Date
    Apr 2005
    Posts
    139
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Great, nice explanation.
    There was my problem: i though that they could only inject code in the headers variables, not in body or message itself. But i guess i was wrong.
    If that's the case...the last function you posted from Chris Snyder (which seems great BTW), Does't check the body of the message....in this case the $comment variable.

    So i guess we should do some checking on the body of the message also.

    Nicolas

  11. #11
    SitePoint Zealot
    Join Date
    Jun 2004
    Location
    Netherlands
    Posts
    172
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi Nicolas,
    You were not wrong. As I understand now, filtering the body of the message is not strictly nessecary as long as there isn't any possibility to inject the headers of the mail() function. However, IF the headers can be injected, the body can also be used to post all kinds of multi-part messages.


    From the NYPHPlist:

    The article is dangerously ambiguous on this point, but I think you're
    right on here, Dan. In order to insert new MIME parts into the message
    body, you need to be able to set the boundary marker in the headers.

    So the message body itself is safe, provided your headers are properly
    sanitized.
    http://lists.nyphp.org/pipermail/tal...er/016153.html

    A very good discussion over there.

    Indeed, the script given by Chris Snyder looks good. However, I'm think I would like to filter for more then only /n and /r.
    Note that 'e-mail injection' exploits don't need a 'return' byte at all, so there's no use scanning for \n or \r. The safest way to prevent the exploit is to eregi() search all fields for 'MIME-Version:
    from:
    http://us3.php.net/mail

    I have used the script with the function email_injection_filter($formInput) since yesterday, on [i]all[/] incoming variables, and all attempts have been stopped so far.

  12. #12
    Non-Member Gator99's Avatar
    Join Date
    Sep 2004
    Location
    Florida
    Posts
    613
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    As long as the variable, $owneremail, is in your form anyone can hijack the form and use it to produce massive amounts of spam. The recipient should be hard coded into the form handler or set as a variable in your form handler class.

  13. #13
    Programming Team silver trophybronze trophy
    Mittineague's Avatar
    Join Date
    Jul 2005
    Location
    West Springfield, Massachusetts
    Posts
    16,445
    Mentioned
    160 Post(s)
    Tagged
    1 Thread(s)

    Email form security

    I don't know if you've followed the link I posted above. Because the senders "from" email is in the "headers" 2 simple ways of making the form more secure are
    PHP Code:
    ...
    $atSymbol strstr($_POST['email'], '@');
    $domainPortion substr($atSymbol1);
    if (!
    checkdnsrr($domainPortion,"MX")){
    //do or do not do stuff here
    ... 
    and
    PHP Code:
    ...
    $reasonableLength 35;
    if (
    strlen($_POST['email'])>$reasonableLength) {
    $email substr($_POST['email'], 0$reasonableLength);
    }
    ... 

  14. #14
    SitePoint Wizard
    Join Date
    Jan 2004
    Location
    3rd rock from the sun
    Posts
    1,005
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This just goes to show you must scrub or sanitise all input.

    It doesnt matter if its coming from a form like the above, any variable, be it GET, POST COOKIE whatever, you have to cleanse it first.

    What if you stored some of the information in your email form in a database? No w you need to check for sql injection too, or someone could wipe out your tables. http://en.wikipedia.org/wiki/Sql_injection

    When I see things like "select * from table where id=$_GET[id]" I just want to swoon... look up security on your php docs.

  15. #15
    SitePoint Addict MBScott's Avatar
    Join Date
    Oct 2002
    Posts
    261
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    After scrubbing and sanitizing all input, we also added a snippet to reject any submission that contained our own domain name. Cured, for the time being, of those annoying tester emails.

    Also, Pauly, from the post above:
    Run function mysql_real_escape_string() on your POST-data. This function will replace the following characters: \x00, \n, \r, \, ', " and \x1a. For more information read the manual:
    http://se2.php.net/manual/en/functi...cape-string.php
    will keep your database safe. I freaked when I saw those "tester" emails in one of my databases. It had tried the injection attack in each field, but wasn't successful.

    Missy

  16. #16
    Who turned the lights out !! Mandes's Avatar
    Join Date
    May 2005
    Location
    S.W. France
    Posts
    2,496
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by nico7799
    ........ i though that they could only inject code in the headers variables, not in body or message itself. But i guess i was wrong. .............
    As I understand it.

    Emails, are nothing more than a long line of bytes, strung together, the email servers parse this data (similar to regex) on the headers, therefore if you put a header inside another piece of info, the server will happily continue to parse this as if it was the original mail.
    A Little Knowledge Is A Very Dangerous Thing.......
    That Makes Me A Lethal Weapon !!!!!!!!

    Contract PHP Programming

  17. #17
    SitePoint Zealot harryzimm's Avatar
    Join Date
    May 2004
    Location
    Oxford England
    Posts
    140
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    My client was getting hit daily with form injection on 15 domains. They were using legacy sendmail.asp, formmail.pl (matt's cgi) and formmail.php as form handlers. I was able to drastically reduce being hit by just renaming the formmail files to less obvious names. Then I hardcoded the to address and removed bcc and cc functionality. So far all attacks have stopped (for now). I plan to implement some of the suggestions from above too.

    From what I have seen the "bots" try to add randomjunk@a_domain.com into all fields. I have been thinking about adding a hidden field to my forms with no value and have my script reject the form if any input is found in the empty field.

    I think a lot of people went to contact forms to avoid spam in the first place... it's a crazy world!

  18. #18
    SitePoint Member
    Join Date
    Oct 2005
    Posts
    1
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi,

    I have the same problem, and used some of the code from this page. Very helpful, thanks!
    I came across a different approach; I thought I share it with you all out there and get a second opinion if it would work. 

    Basically the idea is that all of these hijackers use a different domain name. So for example I have an email form on www.mysite.com and my form would be filled using a different domain name, for example: spammersite.com. The code I found and edited a bit:
    PHP Code:
    //Do the anti-hijacking check
    // Stop the form being used from an external URL   
     // Get the referring URL    
    $referer_uri $_SERVER['HTTP_REFERER'];    // Get the URL of this page    
    $this_url "http://".$_SERVER['HTTP_HOST'].$_SERVER["REQUEST_URI"];
            
    // If the referring URL and the URL of this page don't match then   
            // display a message and don't send the email.    
    if ($referer_uri!= $this_url) {        
        echo 
    "You do not have permission to use this script from another URL.";        
                    exit;    
                }
    //end of anti-hijacking check 
    Would this work?


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •