Is this php mailer file secure from injection attacks? - php

My PHP contact form was recently being used to send spam. Some security measures have since been put in place (please refer to the comments below) and I'm seeking the collective wisdom of others to review the code and to check to make sure it is secure from injection attacks.
Thank you in advance for taking the time to review.
<?php
/* method for validate each input values in case any injection scripts it will ignore */
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
/* honeypot - if hidden field is completed discard form content */
if(!isset($_POST['honeypot']) || $_POST['honeypot'] != '')
{
die("You spammer!\n");
}
else
{
// define variables and set to empty values
$subject = $id = $subcategory = $subcategory = $subcategory_email = $to = $descError = $error =
$remarks = $response= $message= $name = $from = $phone ="";
if(isset($_REQUEST['category']) && $_REQUEST['category']!="")
{
//validate each input values for any injection attacks
$id = test_input($_REQUEST['category']);
$subcategory = test_input($_REQUEST['subcategory']);
$emails = array
(
array("0",""),
array("1","email1#yahoo.com","email2#yahoo.com"),
array("2","email1#yahoo.com","email2#yahoo.com"),
array("3","email1#yahoo.com","email2#yahoo.com"),
array("4","email1#yahoo.com","email2#yahoo.com"),
array("5","email1#yahoo.com","email2#yahoo.com")
);
$value = explode(",", $subcategory);
$subcategory_email = $emails[$id][$value[0]];
$remarks = test_input($_REQUEST['remarks']);
$message = '<html><body>';
$message .= '<table rules="all" style="border-color: #666;" border="1" cellpadding="10">';
$message .= "<tr style='background-color:#F5F5F5;'><th width=25%>Heading </th><th width=75%>Content</th></tr>";
$message .= "<tr><td><b>Category </b></td><td>".$category[$id-1]."</td></tr>";
$message .= "<tr><td><b>SubCategory </b></td><td>".$value[1]."</td></tr>";
$message .= "<tr><td><b>Comments</b></td><td><pre>".$remarks."</pre></td></tr>";
if($response==0)
{
$name = test_input($_REQUEST['name']);
$from = test_input($_REQUEST['email']);
if (!preg_match("/([\w\-]+\#[\w\-]+\.[\w\-]+)/",$from))
{
$emailErr = "Invalid email format";
}
$phone = test_input($_REQUEST['phone']);
$message .= "<tr><td><b>Would you like a response? </b></td><td>Yes</td></tr>";
$message .= "<tr><td><b>Name</b></td><td>".$name."</td></tr>";
$message .= "<tr><td><b>E-Mail</b></td><td>".$from."</td></tr>";
$message .= "<tr><td><b>Telephone</b></td><td>".$phone."</td></tr>";
}
else
{
$from = "noreply#test.com";
$message .= "<tr><td><b>Would you like a response? </b></td><td>No</td></tr>";
}
$subject = "SubCategory ".$value[1];
//Normal headers
$headers = "From: " . strip_tags($from) . "\r\n";
$headers .= "Reply-To: ". strip_tags($subcategory_email) . "\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
$message .= "</table>";
if(mail($subcategory_email, $subject, $message, $headers))
{
include("thanks.php");
$error=6;
}
else
{
echo "mail not sent";
}
}
else
{
echo "<br/>";
$subject = "Sub Category";
$to = "Email1#yahoo.com";
if(empty($_REQUEST['remarks']))
{
$descError = "Enter Description";
$error = 5;
}
else
{
$remarks = test_input($_REQUEST['remarks']);
}
if(test_input($_REQUEST['response'])=="0")
{
$yesDIV = "checked";
$response = "Yes";
if(empty($_REQUEST['name']))
{
$nameError = "Name Required";
$error = 5;
}
else
{
$name = test_input($_REQUEST['name']);
}
$from = $_REQUEST['email'];
if(empty($_REQUEST['email']))
{
$emailError = "Email Required";
$error = 5;
}
else if (!filter_var($from, FILTER_VALIDATE_EMAIL)) {
$emailError = "Valid Email Required";
$error = 5;
}
}
else
{
$noDIV = "checked";
$response = "No";
$bodyDIV = "style='display:none;'";
}
if($error!=5)
{
$phone = test_input($_REQUEST['phone']);
$message = '<html><body>';
$message .= '<table rules="all" style="border-color: #666;" border="1" cellpadding="10">';
$message .= "<tr style='background-color:#F5F5F5;'><th width=25%>Heading </th><th width=75%>Content</th></tr>";
$message .= "<tr><td><b> Comments</b></td><td ><pre>".$remarks."</pre></td></tr>";
$message .= "<tr><td><b>Would you like a response? </b></td><td>".$response."</td></tr>";
$message .= "<tr><td><b>Name</b></td><td>".$name."</td></tr>";
$message .= "<tr><td><b>E-Mail</b></td><td>".$from."</td></tr>";
$message .= "<tr><td><b>Telephone</b></td><td>".$phone."</td></tr>";
$message .= "</table>";
//Normal headers
$headers = "From: noreply#test.com \r\n";
$headers .= "Reply-To: ". strip_tags($from) . "\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
if(mail($to, $subject, $message, $headers))
{
include("thanks.php");
$error=6;
}
else
{
echo "mail not sent";
}
}
}
}
?>

The term "injection" refers to code injection, with code referring to any computer language. Since every computer language is different, the problems and solutions are also different and need to be addressed in a per-language basis. However, you have a generic function that tries to prevent all kind of injections at once and, often, using the worst technique: removing user data.
For instance:
$headers = "From: " . strip_tags($from) . "\r\n";
What sense does it make to take an e-mail address and remove HTML tags from it to compose an e-mail header?
$data = htmlspecialchars($data);
You apply this to e.g. $_REQUEST['email']. Why would you want to insert HTML entities in an e-mail address?
In your code I see two potential sources for injection:
HTML - When you inject user data into HTML you need to ensure that user data is handled as plain text (i.e. whatever the user typed is not rendered as HTML). You can use htmlspecialchars(). You kind of do that but it's really hard to be sure.
E-mail headers - mail()'s fourth argument allows to define mail headers. Injecting raw user input there (which is possibly what's happening now) allows to hide the complete message body, replace it with anything else and even select new recipients. You basically have to strip new lines (again, it's hard to say whether you're doing it right...).
Sending e-mail with PHP is hard. It's better to skip good old mail() and use a third-party library like PHPMailer or Swift Mailer.

Related

execute mail once all item have been iterated

I have the following issues.
I receive separate emails for each iteration of the loop. I want mail to be only sent once with all of the items iterated.
<?php
// Honey pot trap
// Create a hidden input that is only visible to bots. If it's empty than proceed.
if (empty($_POST['humancheck'])){
// Proceeed if submit button have been pressed
$fullName = $_POST['fname'];
$email = $_POST['email'];
$stage = $_POST['stage'];
include("db.php");
$resources = "select * from resources where stage LIKE '%".$stage."%'";
$run_query = mysqli_query($con, $resources);
while($row = mysqli_fetch_array($run_query)) {
$data[] = array(
'format' => $row['format'],
'title' => $row['title'],
'costs' => $row['cost'],
'stage' => $row['stage'],
'topic' => $row['topic'],
'link' => $row['link']
);
}
foreach($data as $item) {
// Sanitize input data
$clean_fullName = htmlspecialchars($fullName);
$clean_email = htmlspecialchars($email);
// Mail Set up
$to = $clean_email;
$to_us = "info#email.com";
// Email subject
$subject = "Your custom resource pack has arrived!";
$subject_us = "New custom resource delivered to: $clean_email";
$message = '<html><body>';
$message .= "<p>";
$message .= "Hi $clean_fullName, <br><br>";
$message .= " Based on your responses, we have created a custom resource pack tailored to your needs. <br><br>";
$message .= "<b>{$item['title']}</b><br>";
$message .= "{$item['format']} <br>";
$message .= "{$item['costs']} <br>";
$message .= "{$item['link']} <br><br>";
$message .= " If you have any questions, do not hesitate to reach out to us. <br><br>";
$message .= "</p>";
$message .= '</body></html>';
$message_us = "The below message was sent to $clean_fullName <br>
<i> Hi $clean_fullName <br>";
$message_us .= "\r\n Based on your responses, we have created a custom resource pack tailored to your needs: \r\n";
$message_us .= "\r\n If you have any questions, do not hesitate to reach out to us. \r\n";
// Headers
// Always set content-type when sending HTML email
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";
$headers .= 'From: <info#email.com>' . "\r\n";
}
mail($to,$subject,$message,$headers);
mail($to_us,$subject_us,$message_us,$headers);
}
?>
what happens is the while loops to the data that is stored in an array. That array is used in foreach. and outside of the loops, the mail is suppose to mail the result.
In theory this should of worked but its not working.
Try this. Edit last part of your code in this way. Take one time parameters of mail content outside the loop, and let loop make only the message content.
$clean_fullName = htmlspecialchars($fullName);
$clean_email = htmlspecialchars($email);
$to = $clean_email;
$to_us = "info#email.com";
$subject = "Your custom resource pack has arrived!";
$subject_us = "New custom resource delivered to: $clean_email";
$message = '<html><body>';
$message .= "<p>";
$message .= "Hi $clean_fullName, <br><br>";
$message .= " Based on your responses, we have created a custom resource pack tailored to your needs. <br><br>";
foreach($data as $item) {
$message .= "<b>{$item['title']}</b><br>";
$message .= "{$item['format']} <br>";
$message .= "{$item['costs']} <br>";
$message .= "{$item['link']} <br><br>";
}
$message .= " If you have any questions, do not hesitate to reach out to us. <br><br>";
$message .= "</p>";
$message .= '</body></html>';
$message_us = "The below message was sent to $clean_fullName <br><i> Hi $clean_fullName <br>";
$message_us .= "\r\n Based on your responses, we have created a custom resource pack tailored to your needs: \r\n";
$message_us .= "\r\n If you have any questions, do not hesitate to reach out to us. \r\n";
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";
$headers .= 'From: <info#email.com>' . "\r\n";
mail($to,$subject,$message,$headers);
mail($to_us,$subject_us,$message_us,$headers);

include $_POST variables only if exists and send mail in PHP

i'm working on a small project in which i need to send email about incorrect information in a listing. so, i need to send only the incorrect data from form. All works fine but not receiving mail. Is there anything i did wrong.Please help...
if(isset($_POST['report'])){
$name = $_POST['business'];
$address = $_POST['address'];
$phone =$_POST['phone'];
$email = $_POST['email'];
$website = $_POST['website'];
$toemail = "jafar.sain#gmail.com";
$fromwebsite = "www.biz15.co.in";
$error_listing = "business name";
$error_listing_link = $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
$subject = "Biz15 - Report an Error in a Listing from ".$fromwebsite;
$body = "You have been requested to go through the following errors from the listing - ".$error_listing."\n\n";
$body .= "Listing Details:\n";
$body .= "Listing Name - ".$error_listing."\n";
$body .= "Listing Url - ".$error_listing_link."\n\n";
$body .= "Error Details:\n";
if($name){$body .= "Business Name - ".$name."\n";}
if($address){$body .= "Address - ".$address."\n";}
if($phone){$body .= "Phone Number - ".$phone."\n";}
if($email){$body .= "Email - ".$email."\n";}
if($website){$body .= "Website - ".$website."\n\n";}
$body .= "---------------------------------------------------------------------------\n\n";
$headers = "MIME-Version: 1.0\n"."From: ".$toemail."\n"."Content-type: text/plain; charset=iso-8859-1\n";
if(#mail($toemail,$subject,$body,$headers)){
echo "<script type='text/javascript'>alert('Success');</script>";
}
else{
echo "<script type='text/javascript'>alert('Failed');</script>";
}
}

access denied. PHP script

I have a contact form, when submitting on my page says 'Access denied.' There is nothing else, so I can't seem to figure out how to debug.
Here is the code :
<?php
$EmailFrom = "username#email.com";
$EmailTo = "username#email.com, username2#email.com";
$Subject = "Subject";
$Name = Trim(stripslashes($_POST['Name']));
$Company = Trim(stripslashes($_POST['Company']));
$Email = Trim(stripslashes($_POST['Email']));
$Tel = Trim(stripslashes($_POST['Tel']));
$Message = Trim(stripslashes($_POST['Message']));
// Validation
$validationOK = true;
if (! $validationOK)
{
print "<meta http-equiv=\"refresh\" content=\"0;URL=error.htm\">";
exit;
}
// Prepare Email Body Text
$Body = "";
$Body .= "Name: ";
$Body .= $Name;
$Body .= "\n";
$Body .= "Company: ";
$Body .= $Company;
$Body .= "\n";
$Body .= "Tel: ";
$Body .= $Tel;
$Body .= "\n";
$Body .= "Further comments: ";
$Body .= $Message;
$Body .= "\n";
// Send Email
$success = mail($EmailTo, $Subject, $Body, "From: <$Email>");
// Redirect To Success Page
if ($success)
{
echo '<script>alert("Thanks for your message, somebody will get in touch with your shortly.");</script>';
echo "<meta http-equiv=\"refresh\" content=\"0;URL=../contact\">";
}
else
{
echo '<script>alert("There has been an error, please try again later.");</script>';
echo '<script>history.back(1);</script>';
exit;
}
?>
I'm not sure why it's not working, could someone shed some light on this?
The headers of the page you're submitting the form to are actually returning a HTTP 403 Forbidden error.
I'd suggest checking the file permissions & ownership of the contactengine.php file are correct as a first step.

PHP/MYSQL - Can't find why this code sends mail more than twice

Alright, I'm starting to pull my hair and I need some help :)
Here is my file which is used to select activated emails from users and send them some sort of newsletter.
Content of the newsletter.php
<?php
//Include configuration file
include 'config/config.php';
$pdo = new PDO("mysql:host=localhost;dbname=$db", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//Define messages
//Error messages
define('ERROR_MESSAGE_SUBJECT', 'Enter subject');
define('ERROR_MESSAGE_CONTENT', 'Enter some content');
//Define variables
$errorFlag = false;
$to = array();
//Grab variables
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$newsletterSubject = check_input($_POST['newsletterSubject']);
$newsletterContent = $_POST['newsletterContent'];
if(!$newsletterSubject) {
$errorSubject = ERROR_MESSAGE_SUBJECT;
$errorFlag = true;
}
if(!$newsletterContent) {
$errorContent = ERROR_MESSAGE_CONTENT;
$errorFlag = true;
}
}
?>
<form action="newsletter.php" method="post">
<label>Naslov newsletter-a: <?php echo '<span class="error">'.$errorSubject.'</span>';?></label>
<input type="text" class="linput rounded" name="newsletterSubject">
<label>Sadržaj newsletter-a: <?php echo '<span class="error">'.$errorContent.'</span>';?></label>
<textarea name="newsletterContent" class="rounded"></textarea><br>
<input type="submit" class="submit button rounded" name="newsletterSend" value="Pošalji newsletter korisnicima">
</form>
<?php
if (!$errorFlag) {
echo '
<div class="heading">
<h1>Sending statistic</h1>
</div>';
$query = $pdo->prepare('SELECT email FROM users WHERE active=:active');
$query->bindValue(':active', '1');
$query->execute();
$query->setFetchMode(PDO::FETCH_ASSOC);
$i=1;
while($row = $query->fetch()) {
$to[] = $row['email'];
}
print_r($to);
if(!empty($to)) {
foreach($to as $mail) {
$headers = "From: " . $fromEmail . "\r\n";
$headers .= "Reply-To: ". $fromEmail . "\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
$message = '<html><body>';
$message .= $newsletterContent;
$message .= '</body></html>';
mail($mail, $newsletterSubject, $message, $headers);
$i++;
}
}
}
?>
After selecting active emails from database, array $to contains:
Array ( [0] => somemail1#domain.com [1] => somemail2#domain.com )
And that is correct, but both emails will receive 2 emails, so 4 in total. Normally one email should receive one newsletter.
And there is also something else strange, when first newsletter is received, it contains subject and message. However second newsletter doesnt contain anything except 'to' field.
So to sum up, this file sends two emails per one email in database.
I tried to create test file with same array and this is content of it:
test.php
<?php
$fromEmail = 'from#mydomain.com';
$to = array('somemail1#domain.com', 'somemail2#domain.com');
print_r($to);
foreach($to as $mail) {
$headers = "From: " . $fromEmail . "\r\n";
$headers .= "Reply-To: ". $fromEmail . "\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
$message = '<html><body>';
$message .= $newsletterContent;
$message .= '</body></html>';
mail($mail, $newsletterSubject, $message, $headers);
$i++;
}
?>
This test file sends normal email - one email per one email. So server configuration should be okay.
It looks like it's because your send code isn't inside the code block which checks that it is POST, so it sends once when you load the page and again when you fill in the form and submit it.
Move the whole if (!$errorFlag) block into the if ($_SERVER['REQUEST_METHOD'] == 'POST') block.

PHP Form Review - Cc and Bcc not working

I have an html form the links to a PHP email. The form works well, but I am having trouble with the Cc and Bcc not coming through.
Here is the entire code. Please review and help me understand what I am getting wrong on the Cc and Bcc parts in the headers.
Thanks:
<?php
$emailFromName = $_POST['name'];
$emailFrom = $_POST['email'];
$emailFromPhone = $_POST['phone'];
$email9_11 = $_POST['9-10'];
$email10_11 = $_POST['10-11'];
$email11_12 = $_POST['11-12'];
$email12_1 = $_POST['12-1'];
if (empty($emailFromName)) {
echo 'Please enter your name.';
} elseif (!preg_match('/^([A-Z0-9\.\-_]+)#([A-Z0-9\.\-_]+)?([\.]{1})([A-Z]{2,6})$/i', $emailFrom) || empty($emailFrom)) {
echo 'The email address entered is invalid.';
} else {
$emailTo = "main#gmail.com" ;
$subject = "Family History Conference Registration";
if (!empty($emailFrom)) {
$headers = 'From: "' . $emailFromName . '" <' . $emailFrom . '>';
} else {
$headers = 'From: Family History Conference <noreply#domain.org>' . "\r\n";
$headers .= 'Cc: $emailFrom' . "\r\n";
$headers .= 'Bcc: myemail#domain.com' . "\r\n";
}
$body = "From: ".$emailFromName."\n";
$body .= "Email: ".$emailFrom."\n";
$body .= "Phone: ".$emailFromPhone."\n\n";
$body .= "I would like to attend the following classes.\n";
$body .= "9:10 to 10:00: ".$email9_11."\n";
$body .= "10:10 to 11:00: ".$email10_11."\n";
$body .= "11:10 to 12:00: ".$email11_12."\n";
$body .= "12:10 to 1:00: ".$email12_1."\n";
/* Send Email */
if (mail($emailTo, $subject, $body, $headers)) {
echo "<h2>Thank you for Registering</h2>
<h3>You have registered for the following classes</h3>
<p>9:10 to 10:00am: \"$email9_11\" <br />
10:10 to 11:00am: \"$email10_11\"<br />
11:10 to 12:00: \"$email11_12\"<br />
12:10 to 1:00: \"$email12_1\"</p>
<p>We look forward to seeing you October 31, 2010</p>";
} else {
echo 'There was an internal error while sending your email.<br>';
echo 'Please try again later.';
}
}
?>
You're using single quotes
$headers .= 'Cc: $emailFrom' . "\r\n";
PHP won't interpret variables inside single quotes, you must use double quotes
$headers .= "Cc: $emailFrom\r\n";

Categories