Jump to content


How to code a secure PHP Contact Form


7 replies to this topic

#1 unstopabl3

    Young Padawan

  • Members
  • Pip
  • 48 posts

Posted 16 March 2006 - 02:54 PM

Hey i came across this interesting Advanced PHP Contact Form tutorial/script. I downloaded and tested it by adding
<head>lols</head> and <script>!@#$%^&</script> in the name and comments fields and when pressed submit it still sent me the email. Although as described in the tutorial its supposed to stop spaces/special/specialcharacters/and any html values submitted by the user. The author has tried to achieve this by adding these snippets of code in the script

if (!isset($_POST['submit'])) {
echo "<h1>Error</h1>\n
<p>Accessing this page directly is not allowed.</p>";
exit;
}

This works fine as it does stop the user from accessing the form directly.

function cleanUp($data) {
$data = trim(strip_tags(htmlspecialchars($data)));
return $data;
}
Doesn't work as mentioned previously

function cleanUp($data) {
$data = trim(strip_tags(htmlspecialchars($data)));
return $data;
}

$name = cleanUp($_POST['name']);
$email = cleanUp($_POST['email']);
$url = cleanUp($_POST['url']);
$comments = cleanUp($_POST['comments']);
Doesn't work as well as mentioned previously

And finally
$email = preg_replace("([\r\n])", "", $email);

$find = "[content-type|Content-Type|bcc:|cc:]";
if (preg_match($find, $name) || preg_match($find, $email) || preg_match($find, $url) || preg_match($find, $comments)) {
<p>No meta/header injections, please.</p>";
exit;
}
This also doesnt work as i am still able to manupilate my headers through the fields.

Full code for form.php

<form action="process.php" method="post"><p>
<input type="text" name="name" id="name" value="Name" /><br />
<input type="text" name="email" id="email" value="Email" /><br />
<input type="text" name="url" id="url" value="URL" /><br />
<textarea name="comments" id="comments"> Comments </textarea><br />
<input type="submit" name="submit" id="submit" value="Send" />
</p></form>

Full code for process.php
<?php
if (!isset($_POST['submit'])) {
echo "<h1>Error</h1>\n
<p>Accessing this page directly is not allowed.</p>";
exit;
}

function cleanUp($data) {
$data = trim(strip_tags(htmlspecialchars($data)));
return $data;
}

$name = cleanUp($_POST['name']);
$email = cleanUp($_POST['email']);
$url = cleanUp($_POST['url']);
$comments = cleanUp($_POST['comments']);

if ((empty($name)) || (empty($email)) || (empty($comments))) {
echo "<h2>Input Error</h2>\n
<p><strong>Name</strong>, <strong>e-mail</strong> and <strong>comments</strong> are required fields. Please fill them in and try again:</p>";

echo "<form action=\"process.php\" method=\"post\"><p>";
echo "<input type=\"text\" name=\"name\" id=\"name\" value=\"$name\" /> Name<br />";
echo "<input type=\"text\" name=\"email\" id=\"email\" value=\"$email\" /> E-mail<br />";
echo "<input type=\"text\" name=\"url\" id=\"url\" value=\"$url\" /> Site URL<br />";
echo "<textarea name=\"comments\" id=\"comments\">$comments</textarea> Comments<br />";
echo "<input type=\"submit\" name=\"submit\" id=\"submit\" value=\"Send\" />";
echo "</p></form>";

exit;
}

if (!ereg("^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*$",$email)) {
echo "<h2>Input Error</h2>\n
<p>The e-mail address \"$email\" isn't valid. Please edit it and try again:</p>";

echo "<form action=\"process.php\" method=\"post\"><p>";
echo "<input type=\"text\" name=\"name\" id=\"name\" value=\"$name\" /> Name<br />";
echo "<input type=\"text\" name=\"email\" id=\"email\" value=\"$email\" /> E-mail<br />";
echo "<input type=\"text\" name=\"url\" id=\"url\" value=\"$url\" /> Site URL<br />";
echo "<textarea name=\"comments\" id=\"comments\">$comments</textarea> Comments<br />";
echo "<input type=\"submit\" name=\"submit\" id=\"submit\" value=\"Send\" />";
echo "</p></form>";

exit;
}

$email = preg_replace("([\r\n])", "", $email);

$find = "[content-type|Content-Type|bcc:|cc:]";
if (preg_match($find, $name) || preg_match($find, $email) || preg_match($find, $url) || preg_match($find, $comments)) {
echo "<h1>Error</h1>\n
<p>No meta/header injections, please.</p>";
exit;
}

$recipient = "youremail@url.com";
$subject = "personal website submission form";

$message = "Name: $name \n";
$message .= "E-mail: $email \n";
$message .= "URL: $url \n";
$message .= "Comments: $comments";

$headers = "From: My Form \r\n";
$headers .= "Reply-To: $email";

if (mail($recipient,$subject,$message,$headers)) {
echo "<p>Mail sent successfully.</p>";
} else {
echo "<p>Mail not sent this time.</p>";
}
?>

Now my question is as to what is wrong with this code that its not doing what it's supposed to do ? Any corrections or suggestions will be appreciated.
Also can you people explain methods your using yourself to prevent header/mysql injections and making your contact/feedback forms more secure ??? Any good tutorials out there which give a step to step guide for creating a secure php contact form ??? I have tried tons of search engines and tutorial engines but the tutorials they have are either outdated or arn't what i am looking for. Thx in advance

Edited by unstopabl3, 16 March 2006 - 02:55 PM.


#2 rc69

    PHP Master PD

  • P2L Staff
  • PipPipPipPip
  • 3,827 posts
  • Gender:Male
  • Location:Here
  • Interests:Web Development

Posted 17 March 2006 - 05:37 PM

$find = "[content-type|Content-Type|bcc:|cc:]";
if (preg_match($find, $name) || preg_match($find, $email) || preg_match($find, $url) || preg_match($find, $comments)) {
echo "<h1>Error</h1>\n
<p>No meta/header injections, please.</p>";
exit;
}
To me, that is pointless, and won't prevent anything.

php.net said:

Multiple extra headers should be separated with a CRLF (\r\n).
So, they can inject anything, so as long as you use a text field (as opposed to text area), trim, and don't add \r\n to the end of your headers, nothing should happen.
Although, i'm not an expert hacker, if anybody wants to open this for argument, feel free, i'm always willing to find out new things.

function cleanUp($data) {
$data = trim(strip_tags(htmlspecialchars($data)));
return $data;
}
I believe that's backwards, when you say:

Quote

I downloaded and tested it by adding
<head>lols</head> and <script>!@#$%^&</script> in the name and comments fields and when pressed submit it still sent me the email
Does that mean you see it as it appears right now, or it's actual html and you don't see it unless you view the e-mails source?

Either way, the cleanUp function as is will convert the < and > signs to &lt; and &gt; so strip_tags would never remove anything, nor would anything left have any negative effects.
But, if you want, you can try switching the functions and seeing if it will remove the html altogether.
$data = trim(htmlspecialchars(strip_tags($data)));

p.s. http://www.pixel2lif...showtopic=19225 <-- MySQL injection attacks

Edited by rc69, 17 March 2006 - 05:39 PM.


#3 dEcade

    P2L Staff

  • P2L Staff
  • PipPipPipPip
  • 1,850 posts
  • Gender:Male
  • Location:Saskatoon, Saskatchewan
  • Interests:Guitar, Programming, Storm Chasing, Games (Designing and playing), Hockey, Photography

Posted 18 March 2006 - 07:24 PM

You could also try looking at this: http://www.pixel2lif...oding/Security/

dEcade

#4 tiki

    Young Padawan

  • Members
  • Pip
  • 259 posts
  • Gender:Male
  • Location:California

Posted 19 March 2006 - 04:45 PM

Why do you need to stop mysql injections for a contact? Isnt it just going straight to your email and no db whatsoever.

Pointless much? They arent going to mess up your email or something.

#5 HaloprO

    Requires Armed Escort

  • Members
  • PipPip
  • 310 posts
  • Gender:Male
  • Location:California, USA

Posted 22 March 2006 - 03:59 AM

Sometimes people like to log how certain people contact other people.. :)

#6 Jem

    Young Padawan

  • Members
  • Pip
  • 93 posts
  • Location:England
  • Interests:Photography, design &amp; developing, walking, cycling, reading.

Posted 23 March 2006 - 09:11 AM

This issue was resolved here: http://board.obidasi...8/7866/0/#57016
(..in case anyone is interested?)

The problem wasn't with the tutorial, rather that the person who created this thread didn't actually bother to read the text accompanying the code and assumed it did things that it doesn't.

rc69 said:

So, they can inject anything, so as long as you use a text field (as opposed to text area), trim, and don't add \r\n to the end of your headers, nothing should happen.
That's not true. Simply using trim() doesn't solve the meta injection issues - those methods (using trim, ltrim, rtrim, etc) were tried and tested before the final tutorial went live and none worked as well as this method. You have my personal guarantee as the writer of the tutorial. :(

Edited by Jem, 23 March 2006 - 11:08 AM.


#7 rc69

    PHP Master PD

  • P2L Staff
  • PipPipPipPip
  • 3,827 posts
  • Gender:Male
  • Location:Here
  • Interests:Web Development

Posted 23 March 2006 - 05:45 PM

$headers = "From: My Form \r\n";
$headers .= "Reply-To: $email";
Well, if you could show me a way to inject something into the headers variable via anything (most likely the $email variable), and get it to work when they're not properly seperated (due to the lack of a \r\n between each), i would love to see it.

Send me a pm, we can discuss more that way.
And please don't confuse my statement with cockyness, i honestly don't know any other way to inject something into the headers (use of a <meta> tag in the body is something else, solved by htmlspecialchars or strip_tags).

#8 Jem

    Young Padawan

  • Members
  • Pip
  • 93 posts
  • Location:England
  • Interests:Photography, design &amp; developing, walking, cycling, reading.

Posted 24 March 2006 - 02:24 PM

Ah, I just said it was tested, I didn't do the testing myself. :D I'm a bit "shaky" when it comes to injections myself (although wikipedia and nyphp.org have something on header injections that I've looked/tried at before - neither of them suggest just trim() either). I'll find out if my little expert mates do it any differently and will PM you then. :huh:

..and I know that the meta tag is something else, heh.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users