Security Question

I have written a security script for a contact page that does not have a database associated with it.

Here it is:

$tokens = file('./tokens.txt', FILE_IGNORE_NEW_LINES);
if (in_array($_POST['token'], $tokens))
		$name = $_POST['name'];
		if (!preg_match("/[\\w]+/", $name)) //verify $name contains only letters and spaces
				echo htmlspecialchars('Name field is invalid, letters and spaces only please correct and re-submit.');
		$email = $_POST['email'];
		if (!preg_match('/^[^0-9][A-z0-9_]+([.][A-z0-9_]+)*[@][A-z0-9_]+([.][A-z0-9_]+)*[.][A-z]{2,4}$/', $email)) //verifies that $email syntax is correct
				echo htmlspecialchars('Email field is invalid, please correct and re-submit.');
		$reason = $_POST['reason'];
		if (!preg_match("/[A-Z|a-z]/", $reason)) //verfies that $reason contains only letters
				echo htmlspecialchars('Reason field is invalid, letters only please correct and re-submit.');
		$comment = $_POST['comment'];
		$comment = strip_tags($comment, ENT_QUOTES); //strips out all html tags
		$comment = wordwrap($comment, 70, "\\r\
"); ///wraps text to new line after seventy characters
		$headers = "Reply-To: $email" . "\\r\
" . "Reason: $reason" . "\\r\
" . "$comment"; //defines headers to be passed to browser
		mail( "", "A Message has been received", "$headers"); //sends out the email 
		echo htmlspecialchars("Your message has been sent", ENT_QUOTES, 'utf-8');
else  //executed if  $_POST['token'] is not in the array $tokens
		echo htmlspecialchars("Invalid Submission Method", ENT_QUOTES, 'utf-8');

Here is an example of an email I have been receiving lately:

Reply-To: [email][/email]
Reason: comment
XoeP3m  lstcmncgcaeu,

I am assuming that someone is trying to use it for spamming purposes and I was wondering if you think that the security is good enough or should I harden it in some way…

I appreciate the reply, but I don’t think that would change anything because I believe they are entering the information directly on the page…

If they didn’t then they wouldn’t have the token necessary to submit the message and therefore get an invalid submission attempt error…


Not sure what you’re doing with the token file…but I like to do something like this with all of my forms…I found it in a PHP security book. Not sure if Shifflet wrote it or if it was someone else…

<table frame="box" cellpadding="2" cellspacing="2" width="300">
	<td align="center" colspan="2">A&amp;S Election Login</td>
	<td align="right">Username:</td><td align="left"><input type="text" name="username" /></td>
	<td align="right">Password:</td><td align="left"><input type="password" name="password" /></td>
	<td align="center" colspan="2">
		$uniqueID = md5(uniqid(rand(),true));
		$_SESSION['uniqueID'] = $uniqueID;
	<input type="hidden" name="uniqueid" value="<?php print $uniqueID; ?>" />
	<input type="submit" name="submit" value="Login" /></td>
	<td align="center" colspan="2">User your MyBGSU login credintials.</td>

In your code that handles the submission, make sure the hidden field matches the $_SESSION[‘uniqueID’] variable. This will verify the form was actually the source of the POST data.

Just my 2 cents,

Thanks for the help… I appreciate the feedback

I noticed you are doing no filtering or checking with the comment value…stripping HTML is not enough.

Red flags:

Regexes, use PHP’s filter_var function instead.
I’m not sure what tokens.txt is, but you need to guarantee that there’s a user actually interacting with the page, or you’ll turn into an open relay. Captcha is usually the preferred way to do this.
Your check on the tokens key in the POST array seems to be a bit of security through obscurity, which is a big no-no.
Striptags; old an busted. Again, filter_var is the new hotness.
Wordwrapping your comment could have unexpected consequences when using SMTP, as \r
is a control character for SMTP servers.

Just some initial reactions.

You could simply use a captcha image or a simple input with an image saying 2+6 which seems to work quiet well for others