NYCPHP Meetup

NYPHP.org

[nycphp-talk] Forms & Refresh Question & General Form Security

Erik Baker GypsyFella at eartlink.net
Wed May 14 23:23:55 EDT 2003


Thanks everyone.  I used a combination of things suggested, some other
online suggestions,  and added to it my further tinkering.

Here's what I found (and all seems to be working well):
Just using another file on success doesn't solve the security problem.
A malicious user needs to merely hit the BACK button & then REFRESH to
get the form to resubmit.  Doing that combo rapidly and you can resubmit
the form (query database & send another success email) dozens of times
in a couple of seconds.  I added a session variable--turns out to be
very easy--to track a successful submission.  On success a plain HTML
page is loaded.

I hadn't found a full satisfactory solution online, so I've pasted all
of the code below for anyone interested.  If anyone has suggestions for
improvement, please send them along; especially if they improve the
security of the form.  (I know, I shouldn't have used global variables,
but they were convenient.)

P.S. I also ran across an interesting Javascript solution where you can
remove the previous page from the browser's cache history.  There may be
another PHP header() command that could accomplish the same thing.
Anyone know?

****CODE TO FOLLOW****

<?PHP
	//INCLUDES
	$doc_root = $_SERVER['DOCUMENT_ROOT']; //gets root folder of the
website
	include_once($doc_root . "/php_scripts/db_stuff.php"); //general
database connectivity commands

	//HARVEST VARIABLES
	$login = $_POST['login'];
	$email = $_POST['email'];

	session_start();

	global $query_msg;
	!empty($_SESSION['query_msg'])  //or use PHPSESSID
		? $query_msg = $_SESSION['query_msg']
		: $query_msg = 'First Pass';
	
	if ( $query_msg != 'First Pass' && $query_msg != 'Email Already
Sent') { #Skip MySQL query first time form is called & after password
found
		GetData('/html/success.html'); #root is assumed in
GetData($url)
	}
	
	ShowForm(); # Display the form
	$_SESSION['query_msg'] = $query_msg;	

	exit();
?>
<?PHP #FUNCTIONS
function GetData($success_url) {
	global $query_msg;
	global $login;
	global $email;
	$dbTable = 'tablename';
	
	if ( !($email == "" && $login == "") ) {//Guard against a blank
form
		//Connect to Database & Select Table
		$link = connect_to_db();  //function in db_stuff.php
file
						//also kills script on
error connecting
		empty($email) #set correct query based on user input
			? $query="SELECT emailaddr,loginname,password
FROM $dbTable WHERE loginname='$login' LIMIT 1"
			: $query="SELECT loginname,emailaddr,password
FROM $dbTable WHERE emailaddr='$email' LIMIT 1";
	
		$result = @mysql_query($query);
	
		if($result) { //Database connection was successful
			if (@mysql_num_rows($result) == 1) { //User
login or email exists
				$email =
mysql_result($result,0,"emailaddr");
				$login =
mysql_result($result,0,"loginname");
				$pwd =
mysql_result($result,0,"password");

				// send email with details
				$sendto = "$email";
				$subject = "YOUR LOGIN INFORMATION";   
				$message = "LOGIN NAME:
$login\
PASSWORD: $pwd\
EMAIL ADDRESS:$email";
				$from = "From: yoururl.com
<webmaster at yoururl.com>";

				if (mail($sendto, $subject, $message,
$from)) {
					$query_msg = 'Email Already
Sent';
					header('Location:
http://'.$_SERVER['HTTP_HOST'].$success_url);
					$_SESSION['query_msg'] =
$query_msg; #Setting this right away, command also in main level
				} else {
					$query_msg = 'Email was not
successful';
				}
			} else {
				$query_msg = 'No such account exists';
			}
			
		} else {
			$query_msg = 'A CONNECTION TO THE DATABASE COULD
NOT BE ESTABLISHED.  <BR>Please try again later.';
		}
	} else {#END Guard against a blank form
		$query_msg = 'Fill in your login name or registered
email address';
	}
	$_SESSION['query_msg'] = $query_msg; #Set session variable
}

function ShowForm() {
#Sets up form & will email result upon success
global $query_msg;
global $login;
global $email;
global $PHP_SELF; # The path and name of this file

# Add row with error message if a message exists #
if ($query_msg != 'First Pass') {
	$form_middle = "<tr><td align='center' valign='middle'
border='2' bordercolor='red'><font
color='#FF0000'>$query_msg</font></td></tr>";
} else {
	$query_msg = $SESSION['query_msg'] = 'Second Pass';
}

$form_top=<<<form_top
<html>
<HEAD>
  <TITLE>WELCOME TO A GREAT SITE!</TITLE>
</HEAD>

<BODY marginwidth="0" marginheight="0" leftmargin="0" topmargin="0"
background="/images/bkgnd.gif">
	<BR>
	<TABLE width="500" border="1" align="center" cellpadding="1"
cellspacing="1" bgcolor="#FFFFFF">
	<tr>
		<th align="center" valign="middle"
bordercolor="#330099"><font size="5" color="#330099">
			<h1>RETRIEVE YOUR LOGIN INFO</h1></font></th>
	</tr>
	<tr>
		<td valign="middle" align="center">You can get your
login information by entering either your login name or your email
address below.  Your password will be sent to the email address that we
currently have on file for you.</td>
	</tr>
form_top;

$form_bottom=<<<form_bottom
	<tr>
		<td>
			<TABLE border="0" align="center" cellpadding="0"
cellspacing="0">
			<tr>
				<FORM NAME="SubmitLogin" METHOD="post"
ACTION="$PHP_SELF">
				<td>Enter Your Login Name:</td>
				<td><INPUT NAME="login" TYPE="Text"
VALUE="" maxlength="20"></td>
				<td width="3%">&nbsp;</td>
				<td><INPUT TYPE="Submit" VALUE="Submit
Login"></td>
				</FORM>
			</tr>
			<tr align="center"><td
colspan="3"><b>-OR-</b></td>
			<td width="30%">&nbsp;</td>
			</tr>
			<tr>
				<FORM NAME="SubmitEmail" METHOD="post"
ACTION="$PHP_SELF">
				<td>Enter Your Email Address:</td>
				<td><INPUT NAME="email" TYPE="Text"
VALUE="" maxlength="40"></td>
				<td width="3%">&nbsp;</td>
				<td><INPUT TYPE="Submit" VALUE="Submit
Email"></td>
				</FORM>
			</tr>
			</TABLE>
		</td>
	</tr>
	</TABLE>
</BODY></HTML>
form_bottom;
	
echo "$form_top";
echo "$form_middle";
echo "$form_bottom";
} # End of function ShowForm

############ END OF FUNCTIONS ###############


-----Original Message-----
From: Wellington Fan [mailto:wfan at encogent.com] 
Sent: Wednesday, May 14, 2003 1:48 PM
To: NYPHP Talk
Subject: RE: [nycphp-talk] Forms & Refresh Question & General Form
Security


absolutely. do this where it makes sense.

> -----Original Message-----
> From: Chris Shiflett [mailto:shiflett at php.net]
> Sent: Wednesday, May 14, 2003 12:23 PM
> To: NYPHP Talk
> Subject: RE: [nycphp-talk] Forms & Refresh Question & General Form 
> Security
> 
> 
> --- Wellington Fan <wfan at encogent.com> wrote:
> > "page_with_form.php"
> > 
> > submits to
> > 
> > "form_processor.php"
> > 
> > which redirects to
> > 
> > "page_with_form.php?status=(success|failure)"
> 
> You do realize you're basically trusting the user with the value
> of status,
> right? I hope you're not using that for anything important.
> 
> Chris
> 
> 
> 
> 
> 
> 


--- Unsubscribe at http://nyphp.org/list/ ---






More information about the talk mailing list