views:

433

answers:

5

I have a simple PHP mailer script that takes values from a form submitted via POST and mails them to me:

<?php
$to = "[email protected]";

$name = $_POST['name'];
$message = $_POST['message'];
$email = $_POST['email'];

$body  =  "Person $name submitted a message: $message";
$subject = "A message has been submitted";

$headers = 'From: ' . $email;

mail($to, $subject, $body, $headers);

header("Location: http://example.com/thanks");
?>

How can I sanitize the input in a way that's readable for me (eg, so I don't need to convert HTML character entities in my head)?

+4  A: 

sanitize the the post

with

filter_var

example here :

http://net.tutsplus.com/tutorials/php/sanitize-and-validate-data-with-php-filters/

like :

echo filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
Haim Evgi
I like filter_var for this, sadly, not all hosting setups have 5.2 yet, but it appears to be a well-thought-out function.
artlung
php 5 is quite good filter_var (PHP 5 >= 5.2.0)
Haim Evgi
+3  A: 

Since you're not building an SQL query or anything here, the only relevant validation that I can see for those inputs is an email validation for $_POST["email"], and maybe an alphanumeric filter on the other fields if you really want to limit the scope of what the message can contain.

To filter the email address, simply use filter_var:

$email = filter_var($email, FILTER_SANITIZE_EMAIL);

As per Frank Farmer's suggestion, you can also filter out newlines in the email subject:

$subject = str_replace(array("\r","\n"),array(" "," "),$subject);
Wadih M.
Newline characters in email subject lines are somewhat problematic.
Frank Farmer
Hi Frank, I've edited my answer to reflect your suggestion.
Wadih M.
Depending on exaclty how the email is constructed,newline characters can be injected into any email-header allowing the attacker to add any new or replacement email headers he likes. In addition to this, injecting a whole blank line (two newlines) then allows the attacker to insert an email body of his choice, completely overriding the generated email.
Cheekysoft
+1  A: 

As others have noted, filter_var is great. If it's not available, add this to your toolchest.

The $headers variable is particularly bad security-wise. It can be appended to and cause spoofed headers to be added. This post called Email Injection discusses it pretty well.

filter_var is great, but another way to assure that something is an email address and not something bad is to use an isMail() function. Here's one:

function isEmail($email) {
    return preg_match('|^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]{2,})+$|i', $email);
};

So to use this, you could do:

if (isset($_POST['email']) && isEmail($_POST['email'])) {
    $email = $_POST['email'] ;
} else {
    // you could halt execution here, set $email to a default email address
    // display an error, redirect, or some combination here,
}

In terms of manual validation, limiting the length using substr(), running strip_tags() and otherwise limiting what can be put in.

artlung
A: 

Not sure if that's something you should be worried about, just throwing ideas.

Would it be an issue if the email message contained <script> tags? Maybe <img> or any other tag accessing an external server?

I know most mail clients nowadays don't allow those to run, but anyway, just making sure you're taking it in consideration.

If you don't expect anything fancy on the message stripping tags is an easy way out.

Carlos Lima
Depending on exaclty how the email is constructed,newline characters can be injected into any email-header allowing the attacker to add any new or replacement email headers he likes. In addition to this, injecting a whole blank line (two newlines) then allows the attacker to insert an email body of his choice, completely overriding the generated email.
Cheekysoft
@Cheekysoft: well pointed.
Carlos Lima
A: 

You need to remove any newlines from input provided by users in $headers, which gets passed to mail() ($email in your case)! See Email injection.

PHP should take care of sanitizing $to and $subject, but there are versions of PHP with bugs (Affected are PHP 4 <= 4.4.6 and PHP 5 <= 5.2.1, see MOPB-34-2007).

blueyed