Page 2 of 3
Posted: Mon Oct 16, 2006 12:29 pm
by macdoc
Thanks. Very interesting.
Code: Select all
PHP Version: 4.3.10
PHP OS: Linux
Error Reporting: 2039 ((E_ALL | E_STRICT) ^ E_STRICT ^ E_NOTICE))
Register Globals: On
Short Tags: On
Display Errors: On
Magic Quotes GPC: On
Magic Quotes Runtime: Off
Magic Quotes Sybase: Off
Loaded Extensions:
yp xml wddx tokenizer
sysvshm sysvsem standard sockets
shmop session pspell posix
pcre overload ncurses iconv
gmp gettext gd ftp
exif dio dbx dba
curl ctype calendar bz2
bcmath zlib openssl imap
ldap mysql pgsql
Posted: Mon Oct 16, 2006 1:52 pm
by feyd
As suspected, they've turned off E_NOTICE. That's why you've never seen the error.
PHP Form Mailer
Posted: Mon Oct 23, 2006 5:11 pm
by macdoc
Found this script online. What do you all think? Is it fairly secure?
http://thedemosite.co.uk/phpformmailer/
thanks
mark
Posted: Mon Oct 23, 2006 5:22 pm
by RobertGonzalez
It does no checking of syntax (like email address being in the right format), it only makes sure that the email field was not empty (what is the point of that) and it relies on Javascript to redirect. I'd probably just spend some time writing my own.
Posted: Tue Oct 24, 2006 2:04 am
by matthijs
Writing your own script as Everah suggests is a good idea (and exercise). When you post the code here you'll get good feedback on the quality of it.
Central to a script like this (or any other) is: filter/validate all input and escape all output. Only let data go through based on a whitelist approach. If you expect someone to fill in an email address, make sure to check the filled in string looks like one, by using a good email regex.
Maybe something like below is a good starting point:
Code: Select all
<?php
// start by declaring empty arrays for the various sets of data
$clean = array();
$errors = array();
$errormessage = '';
// first setup some functions you'll use later
/* start with emailvalidation function, like this one
* from http://www.ilovejackdaniels.com/php/ema ... alidation/
* there are better ones then this, but I think this one is pretty good
----------------------------------------------------------------------*/
function check_email_address($email) {
// First, we check that there's one @ symbol, and that the lengths are right
if (!ereg("^[^@]{1,64}@[^@]{1,255}$", $email)) {
// Email invalid because wrong number of characters in one section, or wrong number of @ symbols.
return false;
}
// Split it into sections to make life easier
$email_array = explode("@", $email);
$local_array = explode(".", $email_array[0]);
for ($i = 0; $i < sizeof($local_array); $i++) {
if (!ereg("^(([A-Za-z0-9!#$%&'*+/=?^_`{|}~-][A-Za-z0-9!#$%&'*+/=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$", $local_array[$i])) {
return false;
}
}
if (!ereg("^\[?[0-9\.]+\]?$", $email_array[1])) { // Check if domain is IP. If not, it should be valid domain name
$domain_array = explode(".", $email_array[1]);
if (sizeof($domain_array) < 2) {
return false; // Not enough parts to domain
}
for ($i = 0; $i < sizeof($domain_array); $i++) {
if (!ereg("^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]+))$", $domain_array[$i])) {
return false;
}
}
}
return true;
}
/* Function: validatestring.
--------------------------------------------------*/
function isValidString($value) {
$stringpattern = '/^[a-z0-9()\/\'":\*+|,.\t\n\r; \- !?&#$@]{2,2000}$/i';
if (preg_match($stringpattern, $value)) {
return TRUE;
} else {
return FALSE;
}
}
/* if form is posted start processing
----------------------------------------------------------------------*/
if (isset($_POST['submit'])) {
// validate name field
if( strlen($_POST['name']) > 1
&& strlen($_POST['name']) < 100
&& isValidString($_POST['name'])
&& ctype_print($_POST['name']) )
{
$clean['name'] = $_POST['name'];
}
else
{
$errors[] = 'The data in the form field name are invalid.';
}
// validate subject field
if( strlen($_POST['subject']) > 3
&& strlen($_POST['subject']) < 100
&& isValidString($_POST['subject'])
&& ctype_print($_POST['subject']) )
{
$clean['subject'] = $_POST['subject'];
}
else
{
$errors[] = 'The data in the form field subject are invalid.';
}
// validate message field
if( strlen($_POST['message']) > 5
&& strlen($_POST['message']) < 1000
&& isValidString($_POST['message']) )
{
$clean['message'] = $_POST['message'];
}
else
{
$errors[] = 'The data in the form field message are invalid.';
}
// validate email field
if( check_email_address($_POST['email'])
&& ctype_print($_POST['email']) )
{
$clean['email'] = $_POST['email'];
}
else
{
$errors[] = 'The email adrress is invalid.';
}
if(count($errors) > 0) {
// some errors occured, show error messages
$errormessage = '<strong>Please correct the following errors:</strong><br />';
foreach ($errors as $key => $value)
{
$errormessage .= $value . "<br />";
}
}
else
{
// everything is ok, continue
$to = 'info@yourdomain.com';
$from = $clean['email'];
$subject = $clean['subject'];
$message = 'Filled in contactform' . "\n"
. 'by: ' . $clean['name'] . ':' . "\n\n" . $clean['message'];
mail("$to","$subject","$message","From: $from");
unset($_POST);
$errormessage = 'Your message has been sent.';
}
}
?>
<html>
<body>
<?php echo (isset($errormessage) && strlen($errormessage)>0 ) ? '<p class="error">' . $errormessage . '</p>' : "" ?>
<form id="contactform" action="/contact/" method="POST">
<fieldset>
<div>
<label for="name">Your name <em>*</em></label>
<input id="name" type="text" name="name" value="<?php echo (isset($_POST['name'])) ? htmlentities($_POST['name'], ENT_QUOTES, 'UTF-8') : ""; ?>" />
</div>
<div>
<label for="email">Email address <em>*</em></label>
<input id="email" type="text" name="email" value="<?php echo (isset($_POST['email'])) ? htmlentities($_POST['email'], ENT_QUOTES, 'UTF-8') : ""; ?>" />
</div>
<div>
<label for="subject">Subject <em>*</em></label>
<input id="subject" type="text" name="subject" value="<?php echo (isset($_POST['subject'])) ? htmlentities($_POST['subject'], ENT_QUOTES, 'UTF-8') : ""; ?>" />
</div>
<div>
<label for="message">Message </label>
<textarea name="message" id="message" cols="40" rows="6"><?php echo (isset($_POST['message'])) ? htmlentities($_POST['message'], ENT_QUOTES, 'UTF-8') : ""; ?></textarea>
</div>
<div id="fm-submit"><label for="submit">Send </label><input type="submit" name="submit" id="submit" value="Send" /></div>
</fieldset>
</form>
</body>
</html>
As a disclaimer, I'm sure this code can be improved and might not be 100% bulletproof (so any suggestions from others are welcome) but I think it can be a step in the right direction. One thing I see now is that I could declare another array $html = array(); and then put the escaping rules (with the htmlentities) in the top part of the script instead of within the html form. A bit cleaner.
There are many ways to code forms, so how you do it can be personal preference.
Posted: Tue Oct 24, 2006 11:40 am
by macdoc
Everah wrote:It does no checking of syntax (like email address being in the right format), it only makes sure that the email field was not empty (what is the point of that) and it relies on Javascript to redirect. I'd probably just spend some time writing my own.
I understand where you are coming from. That's why I asked

. I also understand the value of writing code yourself, but my thinking is, why re-invent the wheel? I like to believe that the reason that there are so many libraries chock full of scripts out there, is so that we don't have to re-write the basic stuff, and can concentrate on the more complex issues.
Thanks for responding.
Mark
Posted: Tue Oct 24, 2006 11:45 am
by macdoc
matthijs wrote:Writing your own script as Everah suggests is a good idea (and exercise). When you post the code here you'll get good feedback on the quality of it.
Central to a script like this (or any other) is: filter/validate all input and escape all output. Only let data go through based on a whitelist approach. If you expect someone to fill in an email address, make sure to check the filled in string looks like one, by using a good email regex.
Maybe something like below is a good starting point:
As a disclaimer, I'm sure this code can be improved and might not be 100% bulletproof (so any suggestions from others are welcome) but I think it can be a step in the right direction. One thing I see now is that I could declare another array $html = array(); and then put the escaping rules (with the htmlentities) in the top part of the script instead of within the html form. A bit cleaner.
There are many ways to code forms, so how you do it can be personal preference.
One reason I was asking about this script is, I AM using a regex suggested through some of the other topics here, one in a topic started by you, matthijs

. The one I am currently using is "validateEmailFormat", and I am still being hijacked. I am in the process of switching host providers so that I can enable captcha, as my current host doesn't allow it, and they are extremely inflexible. I like the script you included here, and will look through it.
Thanks for responding.
Mark
Posted: Tue Oct 24, 2006 11:52 am
by RobertGonzalez
macdoc wrote:... but my thinking is, why re-invent the wheel? I like to believe that the reason that there are so many libraries chock full of scripts out there, is so that we don't have to re-write the basic stuff, and can concentrate on the more complex issues.
You reinvent the wheel when the wheel doesn't work for your vehicle. There are a ton of scripts out there. A lot of them were born out of 'I don't need an address field, but I could really use a second phone number field' type of need. In reality, a simple mail handler is a small task. Complex mail handlers (like phpMailer or Swift) are a lot more involved.
Posted: Tue Oct 24, 2006 12:54 pm
by matthijs
macdoc wrote:One reason I was asking about this script is, I AM using a regex suggested through some of the other topics here, one in a topic started by you, matthijs
Are you talking about
this thread?
I really would like to know which regex you are using then? In the code you posted there is no input validation at all for $emailform:
$EmailFrom = Trim($_POST[EmailFrom]);
Posted: Tue Oct 24, 2006 1:16 pm
by macdoc
Everah wrote:
You reinvent the wheel when the wheel doesn't work for your vehicle.
Or, you could go to the wheel shop and have one put on instead of making one yourself? Hmmm. We could go on and on. Not here to make enemies. I did acknowlege your point, and hope that you could respect my point of view as well.
Everah wrote:In reality, a simple mail handler is a small task. Complex mail handlers (like phpMailer or Swift) are a lot more involved.
So true. Which is why I am wanting to find a solution that has already been created than re-creating it.
Thanks.
Mark
Posted: Tue Oct 24, 2006 1:25 pm
by macdoc
matthijs wrote:
Are you talking about
this thread?
I really would like to know which regex you are using then? In the code you posted there is no input validation at all for $emailform:
$EmailFrom = Trim($_POST[EmailFrom]);
Yes, that thread.
Here is the current script I am using. I never posted it after I edited to use the regex. I left a bunch of commenting as I need to know where I cam from to get to where I am going.
I imagine I need to make additional checks?
Thanks again.
Code: Select all
<?php
//require 'check_email_address.php';
require 'validateemailformat.php';
// Website Contact Form Generator
// http://www.tele-pro.co.uk/scripts/contact_form/
// This script is free to use as long as you
// retain the credit link
// get posted data into local variables
$EmailFrom = Trim($_POST[EmailFrom]);
$EmailTo = Trim($_POST[EmailTo]);
$Subject = Trim($_POST[Subject]);
$FirstName = Trim($_POST[FirstName]);
$LastName = Trim($_POST[LastName]);
$Address01 = Trim($_POST[Address01]);
$Address02 = Trim($_POST[Address02]);
$City = Trim($_POST[City]);
$State = Trim($_POST[State]);
$PostCode = Trim($_POST[PostCode]);
$Province = Trim($_POST[Province]);
$Country = Trim($_POST[Country]);
$Tel = Trim($_POST[Tel]);
$Email = Trim($_POST[Email]);
$Phone = Trim($_POST[Phone]);
$Fax = Trim($_POST[Fax]);
$PostalMail = Trim($_POST[PostalMail]);
$Facsimele = Trim($_POST[Facsimele]);
$message = Trim($_POST[message]);
// validation
$validationOK=true;
if (Trim($EmailFrom)=="") $validationOK=false;
if (Trim($EmailTo)=="") $validationOK=false;
if (Trim($Subject)=="") $validationOK=false;
if (Trim($message)=="") $validationOK=false;
if (Trim($Email)=="" and Trim($Phone)=="" and Trim($Fax)=="" and Trim($PostalMail)=="") $validationOK=false;
if (!$validationOK) {
print "<meta http-equiv="refresh" content="0;URL=error.php">";
exit;
}
if (Trim($Email)=="") $Email="No";
if (Trim($Phone)=="") $Phone="No";
if (Trim($Fax)=="") $Fax="No";
if (Trim($PostalMail)=="") $PostalMail="No";
$EmailToo = "markmiller@mitechsol.com";
$EmailFrom2 = explode("@", $EmailFrom);
// prepare email body text
$Body = "";
$Body .= "First Name: ";
$Body .= "$FirstName";
$Body .= "\n";
$Body .= " Last Name: ";
$Body .= "$LastName";
$Body .= "\n";
$Body .= "\n";
$Body .= "Message: ";
$Body .= "\n";
$Body .= "$message";
$Body .= "\n";
$Body .= "\n";
$Body .= "Telephone: ";
$Body .= "$Tel";
$Body .= "\n";
$Body .= " Fax: ";
$Body .= "$Facsimele";
$Body .= "\n";
$Body .= "\n";
$Body .= " Address: ";
$Body .= "$Address01";
$Body .= "\n";
$Body .= " : ";
$Body .= "$Address02";
$Body .= "\n";
$Body .= " City: ";
$Body .= "$City";
$Body .= "\n";
$Body .= " State: ";
$Body .= "$State";
$Body .= "\n";
$Body .= "Zip/PostCode: ";
$Body .= "$PostCode";
$Body .= "\n";
$Body .= " Province: ";
$Body .= "$Province";
$Body .= "\n";
$Body .= " Country: ";
$Body .= "$Country";
$Body .= "\n";
$Body .= "$EmailFrom\n";
$Body .= "\n";
$Body .= " Please Contact me by:";
$Body .= "\n";
$Body .= "Email: ";
$Body .= "Phone: ";
$Body .= "Postal Mail: ";
$Body .= "Fax: ";
$Body .= "\n";
$Body .= " $Email ";
$Body .= "$Phone ";
$Body .= "$PostalMail ";
$Body .= "$Fax";
//Check for HiJackers
if (!validateEmailFormat ($EmailFrom)){
//exit;
print "<meta http-equiv="refresh" content="0;URL=hijacker.php">";
exit;
}
else {
// send email
$success = mail($EmailTo, $Subject, $Body, "From: <$EmailFrom>");
// redirect to success page
if ($success){
print "<meta http-equiv="refresh" content="0;URL=ok.php">";
// mail(""markmiller@mitechsol.com"", $Subject, $Body, "From: <$EmailFrom>");
mail($EmailToo, $Subject, $Body, "From: <$EmailFrom>");
}
else{
print "<meta http-equiv="refresh" content="0;URL=error.php">";
}
}
/*
$headers = '';
if (isset($_POST['headers']))
{
$headers = $_POST['headers'];
echo 'Headers: ' . $headers . '<br> ';
if (!ctype_print($headers) )
{
echo '<p>Sorry, thats no good input!</p>';
}
if (!check_email_address($headers))
{
echo '<p>Sorry, thats no valid emailaddress!</p>';
}
}
exit;
if ($EmailFrom2[1]=='endo-nurses.org') {
/~ echo ($EmailFrom2[1]);
print "<br><br>";
echo ($EmailFrom2[2]);
exit;
~/
print "<meta http-equiv="refresh" content="0;URL=hijacker.php">";
exit;
}
if ($EmailFrom2[2]=='endo-nurses.org') {
print "<meta http-equiv="refresh" content="0;URL=hijacker.php">";
exit;
}
*/
// send email
//$success = mail($EmailTo, $Subject, $Body, "From: <$EmailFrom>");
// redirect to success page
/*
if ($success){
print "<meta http-equiv="refresh" content="0;URL=ok.php">";
// mail(""markmiller@mitechsol.com"", $Subject, $Body, "From: <$EmailFrom>");
mail($EmailToo, $Subject, $Body, "From: <$EmailFrom>");
}
else{
print "<meta http-equiv="refresh" content="0;URL=error.php">";
}
*/
?>
Posted: Tue Oct 24, 2006 1:47 pm
by matthijs
Well, the big question is of course, what's in validateEmailFormat()?
As the main problem with email injection is the headers of the mail() function, as you've read in the other thread.
One other very simple solution is to just not place any user input in the headers. So just place $EmailFrom in the body of the mail and use a constant string (like "From: my contactform") for the 4th var in the mail().
Posted: Tue Oct 24, 2006 3:51 pm
by RobertGonzalez
macdoc wrote:Not here to make enemies. I did acknowlege your point, and hope that you could respect my point of view as well.
Absolutely. If I came off as comfrontational, I apologize. That was not my intent.
Posted: Tue Oct 24, 2006 4:24 pm
by macdoc
matthijs wrote:Well, the big question is of course, what's in validateEmailFormat()?
As the main problem with email injection is the headers of the mail() function, as you've read in the other thread.
One other very simple solution is to just not place any user input in the headers. So just place $EmailFrom in the body of the mail and use a constant string (like "From: my contactform") for the 4th var in the mail().
Yes, that would definitly make things better. Thanks.
Here is validateEmailFormat
http://svn.gna.org/viewcvs/blacknova/tr ... iew=markup
I can't tell if the email I received was actually used to forward spam, or if it is a test to see if it actually can be used to forward spam.
This is an email that I recently received that is a hijack example. I also included the email headers here, which from what I could tell don't have anything in them that indicates it was used for spam. Of course, unfortuantely, Bcc: can't be viewed:
Code: Select all
Return-path: <endo@endo-nurses.org>
Envelope-to: markmiller@mitechsol.com
Delivery-date: Tue, 24 Oct 2006 03:24:42 -0400
Received: from [65.61.209.201] (port=53499 helo=dprhensimmta.doteasy.com)
by jupiter.afmu.com with esmtp (Exim 4.52)
id 1GcEeL-0001mR-5p
for markmiller@mitechsol.com; Tue, 24 Oct 2006 01:16:29 -0400
Received: from dprhensim40.doteasy.com (unverified [65.61.244.1])
by dprhensimmta.doteasy.com (DEO) with ESMTP id 1928102
for <markmiller@mitechsol.com>; Mon, 23 Oct 2006 22:40:35 -0700
Received: from endo-nurses.org (localhost.localdomain [127.0.0.1])
by dprhensim40.doteasy.com (8.12.11/8.12.11) with ESMTP id k9O5EuQG004663
for <markmiller@mitechsol.com>; Mon, 23 Oct 2006 22:14:56 -0700
Received: (from endo@localhost)
by endo-nurses.org (8.12.11/8.12.11/Submit) id k9O5EuEN015937;
Mon, 23 Oct 2006 22:14:56 -0700
Date: Mon, 23 Oct 2006 22:14:56 -0700
Message-Id: <200610240514.k9O5EuEN015937@endo-nurses.org>
To: markmiller@mitechsol.com
Subject: is9612@endo-nurses.org
From: <is9612@endo-nurses.org>
X-Server: High Performance Mail Server - http://surgemail.com r=34189668
X-ClamAntiVirus-Scanner: This mail is clean
Code: Select all
First Name: is9612@endo-nurses.org
Last Name: is9612@endo-nurses.org
Message:
fried
Content-Type: multipart/alternative;
boundary=96c0008897a16df1b8ffcd7e59d4425a
X-Mailer: Mozilla 4.79 (Macintosh; U; PPC)
Subject: directly into the
cc: timothytrembulak@yahoo.com,wayneflo@cableone.net,
rdnzl1@newriver.usmc.mil,sasha8190@usg.com,topcopl2@aol.com,
master_bates69@yahoo.com,eytanaka@yahoo.com,dcbaker@aol.cm,
cindie56@yahoo.com
--96c0008897a16df1b8ffcd7e59d4425a
Content-Transfer-Encoding: 7bit
Content-Type: text/plain
of uncooked streaky bacon . acon, raw utritional value per 100 g nergy 460
kcal
--96c0008897a16df1b8ffcd7e59d4425a
Content-Transfer-Encoding: 8bit
Content-Type: text/plain
bacon . acon, raw utritional value per 100 g
--96c0008897a16df1b8ffcd7e59d4425a--
.
Telephone: is9612@endo-nurses.org
Fax: is9612@endo-nurses.org
Address: is9612@endo-nurses.org
: is9612@endo-nurses.org
City: is9612@endo-nurses.org
State: is9612@endo-nurses.org
Zip/PostCode: is9612@endo-nurses.org
Province: is9612@endo-nurses.org
Country: is9612@endo-nurses.org
is9612@endo-nurses.org
Please Contact me by:
Email: Phone: Postal Mail: Fax:
is9612@endo-nurses.org is9612@endo-nurses.org is9612@endo-nurses.org is9612@endo-nurses.org
This a different one that has this as the subject line:
Code: Select all
categories Content-Type: multipart/alternative; boundary=45dbd8e14b51484cf6798881852467e7 X-Mailer: KMail [version 1.4] Subject: refers to very plain, unbleached bcc: carleneanderson@comcast.net,bbygry@yahoo.com,biggsturg@yahoo.com, dinotto2@aol.com,cstamper95@adelphia.net,cindystrout@emersonprocess.com --45dbd8e14b51484cf6798881852467e7 Content-Transfer-Encoding: base64 Content-Type: text/plain YSBwcm9kdWN0IGNhbGxlZCB1cmtleSBhY29uICwgd2hpY2gsIGRlc3BpdGUgaXRzIG1vbmlrZXIg aXMgbm90IHBvcmsgZnJlZSBhbmQgaXMgbWFya2V0ZWQgYXMgbG93ZXIgaW4gZmF0LiBhY29uIGlz IGdlbmVyYWxseSBjb25zaWRlcmVkIGEgYnJlYWtmYXN0IGRpc2gsIGN1dCBpbnRv --45dbd8e14b51484cf6798881852467e7-- .
Posted: Tue Oct 24, 2006 4:28 pm
by macdoc
Everah wrote:Absolutely. If I came off as comfrontational, I apologize. That was not my intent.
Thanks. Just hard to tell sometimes.
