sendmail() security question

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

Post Reply
User avatar
trukfixer
Forum Contributor
Posts: 174
Joined: Fri May 21, 2004 3:14 pm
Location: Miami, Florida, USA

sendmail() security question

Post by trukfixer »

Because there's been so many mailer or contact feedback form exploits (cgi mailers, form mail, etc) I wrote my own basic feedback form.. Recently in a security discussion, someone mentioned the potential to inject spam by sticking

\\r\nBcc:email1@somewhere.com,email2@somewhere.com\r\nCc:email3@elsewhere.com

into my "reply to" input field (I do some basic checks on that field, but nothing overboard) However, in my own testing of my script I was unable to get this idea to work.. however it does seem possible, and I wonder under what conditions can such an attack actually work??

My feedback form is here: http://www.crazybri.net/feedback.php

my code: (note all instances of @ have been replaced with AT for purposes of this post... Im not interested in being picked up by more spamspiders :)

Code: Select all

<?php
//code is free to use such as it is 
include('config.php');

$email = "";
$src = $_GET['from'];
$user = $_GET['user'];
if(!empty($_POST))
{
    $action = $_POST['action'];
    $uid = $_POST['id'];
    $uid = intval($uid);
    $reply_to = $_POST['sender'];
    $raw_input = $_POST['message'];
    //trim message to 450 check reply_to for an @ if none put noreply AT crazybri.net
    if(!strpos($reply_to,"@"))
    {
        $reply_to = 'noreplyATcrazybri.net';
    }
    $message = substr("$raw_input",0,450);
    $message = str_replace("chr(","",$message);//keeps idiots from sending chr(0), etc- it just breaks it
    $reply = str_replace("chr(","",$reply_to);

    if($action == "news")
    {
       //note this section is only because I link my news feedback page to this feedback form 
      //just a rough hack  
        $nlink = mysql_connect('localhost','tuser','pass');
        mysql_select_db('dbname');
        $query = mysql_query("SELECT email FROM unp_user WHERE userid = '$uid' LIMIT 1",$nlink);
        $data = mysql_fetch_array($query);
        $email = $data['email'];
        send_email($action,$email,$reply,$message);
    }
    else
    {
        send_email("basic","bri AT crazybri.net",$reply,$message);
    }
    header("Location: index.php");
}



$smarty->assign('src',$src);
$smarty->assign('id',$user);
$smarty->assign('title',$title);
$title2 = "CrazyBri Feedback Form- Send feedback or email to selected users";
$smarty->assign("title2",$title2);
include_once("header.php");
$smarty->display('feedback.tpl');
$file=('Feedback');
include_once('footer.php');
$email = "";
function send_email($action,$email,$reply,$message)
{
    mail( $email, "$action Feedback Form Results", $message, "From: $reply<$reply>" );
}
?>
The code is free to use.. I threw it together in a couple minutes of work.. didnt need anything fancy..

My own attempt to inject email results in a feedback email *to* me (I hard code the send to, mind you, it isnt a variable)

Code: Select all

From - Wed Nov 23 09:04:03 2005
X-Account-Key: account3
X-UIDL: 914d4d4736204d7c0b12d9b3642a725c
X-Mozilla-Status: 0201
X-Mozilla-Status2: 00000000
Return-path: <nobody AT server1.controlhosting.net>
Envelope-to: bri AT crazybri.net
Delivery-date: Wed, 23 Nov 2005 09:03:49 -0500
Received: from nobody by server1.controlhosting.net with local (Exim 4.52)
	id 1EevDx-0002uH-D0
	for briATcrazybri.net; Wed, 23 Nov 2005 09:03:49 -0500
To: bri AT crazybri.net
Subject: basic Feedback Form Results
From: helloATcrazybri.net\\r\\nBcc:salesATcrazybri.net,rubberATcrazybri.net<helloATcrazybri.net\\r\\nBcc:salesATcrazybri.net,rubberATcrazybri.net>
Message-Id: <E1EevDx-0002uH-D0ATserver1.controlhosting.net>
Date: Wed, 23 Nov 2005 09:03:49 -0500

Hacker testing see if I can \\r\\nBcc:bodyATcrazybri.net\\r\\n inject some spam into the feedback form
The challenge: under what conditions, and what code, can you inject a string that, when it is ultimately passed to mail() function, it will cause a *line break* and start a new header line as in Cc: and Bcc: etc, in order to exploit the code and use it to send out UCE to 3 or more email addresses?
Charles256
DevNet Resident
Posts: 1375
Joined: Fri Sep 16, 2005 9:06 pm

Post by Charles256 »

i've noticed a lot of supposed security risks I can't get to work even when I don't do the craziest purification..no matter what people say...which is why in SOME (read SOME SOME SOME ) cases I ignore any screams of to arms in security...only thing I can see in your code is you may want to do some checks for the tell tale code signs, i.e. <?php <?, and the like...
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Post by Jenk »

Would it not be better to just remove the newline char's, then regex the email addresses to see if they are valid format?


I'm speculating, never had the need to do this myself yet.

e.g.:

Code: Select all

<?php

function CheckMail ($addy)
{
    $addy = str_replace("\r\n", "", $addy);
    if (preg_match("/^[a-zA-Z0-9_\-.]+@[a-zA-Z0-9_\-.]+(\.[a-zA-Z0-9]{2,3})+$/", $addy)) {
        return $addy;
    } else {
        return false;
    }
}
if ($to = CheckMail($_POST['To'])) {
    $to = "To: {$to}\r\n";
}
?>
User avatar
trukfixer
Forum Contributor
Posts: 174
Joined: Fri May 21, 2004 3:14 pm
Location: Miami, Florida, USA

Post by trukfixer »

Jenk wrote:Would it not be better to just remove the newline char's, then regex the email addresses to see if they are valid format?


I'm speculating, never had the need to do this myself yet.

e.g.:

Code: Select all

<?php

function CheckMail ($addy)
{
    $addy = str_replace("\r\n", "", $addy);
    if (preg_match("/^[a-zA-Z0-9_\-.]+@[a-zA-Z0-9_\-.]+(\.[a-zA-Z0-9]{2,3})+$/", $addy)) {
        return $addy;
    } else {
        return false;
    }
}

?>
I considered it. I wanted to offer the option to *not* provide a reply to.. It'd be simple enough to just regex, and if it fails, use the default and throw away the rest.... not a big problem there.. as I said, the above code was just slapped together in a few minutes' work .. I didnt put a lot of deep thought into it :)

My main question is: can such an exploit be made to really work via that feedback form.. that's what I wondered..

Thing is, if I wanted to expand this out to a more robust feedback/contact script, I'd want to be able to know *what* works to exploit such things .. so I can account for such exploits.. :) Ive had some of our customers ask me to build out on this basic form script to do more of what they would like to see, because they all have tried , at last count, over 47 different form mail/submit scripts and so far every one of them was causing problems of one sort or another (exploits, submit floods, etc) and other scripts just didnt have the features they wanted out of it, so... that's why this post/question ..

I'd prefer to keep my code to an absolute minimum (I hate code bloat .. Horde still gives me nightmares!) so I figured a post here might come up with some more elegant solutions and possibilities or ideas I havent considered or heard of :)
User avatar
trukfixer
Forum Contributor
Posts: 174
Joined: Fri May 21, 2004 3:14 pm
Location: Miami, Florida, USA

Post by trukfixer »

OK.. it wasnt working on that particular install because magic_quotes_gpc was on (I forgot about that) , however if magic_quotes_gpc were off, or you in some way got past that ---

the important thing is that the $from variable is just dumping whatever is in the string into the sendmail() headers..
which is the precise problem.. I did a little more google searching for more more specific stuff - namely "email injection" and came up with this:

http://securephp.damonkohler.com/index. ... _Injection

so while that script isnt too terrible at the moment, the important thing is to clean up and validate on anything that may go into the headers..

Thanks to teh guys that ran some tests- the header info from the emails was quite informative as well ..

(gmail bounced one because of the $reply_to<$reply_to> and the <> stuff is just to make it "pretty" for the recipient.. so Im gonna drop its usage from practice..)

The solution is going to be: regex on anything that gets passed to message headers , and on error, either set a default, or toss them back to the form (or redirect them to another page , in the event it is an automated bot, perhaps, would be better)

Thanks for the input, I definitely would be interested in further comments from the gurus (shifflett, Roja, etc)
Charles256
DevNet Resident
Posts: 1375
Joined: Fri Sep 16, 2005 9:06 pm

Post by Charles256 »

main thing that frustrates me about mail is that sometimes the host will take it, somthimes they won't..it's a horrible game of russian roulette.
gearb0x
Forum Newbie
Posts: 4
Joined: Tue Dec 06, 2005 11:20 pm

Post by gearb0x »

Hey

Just doing some playing around on this topic my self. I cant for the life of me get it to work. I tried IE and firefox, \r\n, and the delimiter that security article speaks of

Magic GPC quotes is off on my server as well

argh this is anoying, trying to fix something i cant even replicate
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

let me suggest PHPMailer.. from my experience it gets the job done extremely well
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

If i remember well, when i was testing this problem, i think that the win32 build of php actually inspected the headers...
sheila
Forum Commoner
Posts: 98
Joined: Mon Sep 05, 2005 9:52 pm
Location: Texas

Post by sheila »

gearb0x wrote: Just doing some playing around on this topic my self. I cant for the life of me get it to work. I tried IE and firefox, \r\n, and the delimiter that security article speaks of

Magic GPC quotes is off on my server as well

argh this is anoying, trying to fix something i cant even replicate
Are you trying to prove that your script is vunerable? You can't do it with an ordinary HTML form. The \r\n just get turned into character data and their meaning is lost. You need something running from the command line that POSTs directly to the target URL. I have a Perl script that I use but it could be done with PHP too.
gearb0x
Forum Newbie
Posts: 4
Joined: Tue Dec 06, 2005 11:20 pm

Post by gearb0x »

:oops: never though of that :D

thanks very much will have a play later

Phill
gearb0x
Forum Newbie
Posts: 4
Joined: Tue Dec 06, 2005 11:20 pm

Post by gearb0x »

Just a little update, i got it all working and managed to inject stuff into my systems mailing system (after i /* */ the validation :D)

just something i found on the way, http://tamperdata.mozdev.org/ little plugin for firefox, lets you change stuff at post/get time before the request gets sent. Makes it easier to test these sorts of things ;D
Post Reply