PDA

View Full Version : Tightening PHP & mySQL Logon Security


aCcodeMonkey
09-26-2002, 07:40 AM
I wrote a quick validation service for websites using Apache, mySQL and PHP and need to tighen the security.

I am using MD5 Hashing to encrypt the User ID and Password in the mySQL Db. Since I cannot guarantee that the website that the servies is installed on will be using MODSSL or OpenSSL.
I want to make code as secure as I can.

So could someone take a look and see if there is anything I can do to tighten the code's security.

Logon Code:

<?php
/*
This code is for self referencing web pages.
The code will check to see if it is being loaded for the first time and display the appropriate logon screen.
*/
require 'connections.inc';
//Logon Form HTML Text
$sHTML = '<!-- Replace the following style code with a pointer to a production *.css file --><style type="text/css"><!--';
$sHTML = $sHTML . '.PageTitle { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; font-style: normal; font-weight: bolder; text-transform: capitalize; color: #000066; text-decoration: none}';
$sHTML = $sHTML . '.FieldNames { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; font-weight: bold; text-transform: capitalize; color: #000000}';
$sHTML = $sHTML . '.DataEntryFieldsEnabled { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 9px; font-weight: normal; color: #000000; background-color: #FFFFFF; border: #000033; border-style: outset; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px}';
$sHTML = $sHTML . '.Buttons { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 9px; font-weight: normal; text-transform: capitalize; color: #000000; background-color: #CAC8C8; border: #000033; border-style: outset; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px}';
$sHTML = $sHTML . '.Divider0 { border-color: black black #666666; border-style: groove; border-bottom-width: 3px} --></style></head>';
$sHTML = $sHTML . '<body bgcolor="#FFFFFF" text="#000000" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0"><table width="80%" border="0" cellspacing="0" cellpadding="0" align="center">';
$sHTML = $sHTML . '<tr><td colspan="2" class="PageTitle"><b>Logon to mySQL</b></td></tr><tr><td colspan="2"><hr noshade align="center" width="100%" class="Divider0"></td></tr><tr><td colspan="2">&nbsp;</td></tr>';
$sHTML = $sHTML . '<tr><td colspan="2" align="center" valign="top"><br><form name="frmLogon" method="post" action="logon.php"><input type="hidden" name="context" value="1"><table border="0" cellspacing="0" cellpadding="0" align="center" width="160">';
$sHTML = $sHTML . '<tr><td nowrap class="FieldNames">User Name:&nbsp;&nbsp;</td><td width="100%"><input type="text" name="UserName" class="DataEntryFieldsEnabled" maxlength="15"></td></tr>';
$sHTML = $sHTML . '<tr><td nowrap class="FieldNames">Password</td><td><input type="password" name="Password" class="DataEntryFieldsEnabled" maxlength="15"></td></tr><tr><td colspan="2">&nbsp;</td></tr>';
$sHTML = $sHTML . '<tr><td colspan="2" align="center"><input type="submit" name="btnSubmit" value="Logon" class="Buttons">&nbsp;&nbsp;&nbsp;<input type="reset" name="bntReset" value="Reset" class="Buttons"></td></tr>';
$sHTML = $sHTML . '</table></form></td></tr></table>';
// If this is the first time loading the web page, then load logon form
if ($_POST['context']<>1){
echo $sHTML;
die;
}else{
// Connect to local mySQL database Note: this account is select only
$localdb = mysql_connect($DbServer, $DbUID, $DbPWD) or die ("Problem Connecting To Server.<br> Please reload the page");
// Get Logon information
mysql_select_db($DbName,$localdb);
//Hash userid and password before appending to sql string;
$sHashSQL="Select MD5('".$_POST['UserName']."'), MD5('".$_POST['Password']."')";
$Hash=mysql_query($sHashSQL,$localdb);
$rHash=mysql_fetch_row($Hash);
$sSQL = "select FNAME,LNAME,Salutation,Phone,Ext,Email,Pager from users where UID='".$rHash[0]."' and PWD='".$rHash[1]."' and Start <= CurDate() and Stop > CurDate() and Active=1 limit 1";
mysql_free_result($Hash);
// logon
$logonresult=mysql_query($sSQL,$localdb);
//If no record was returned prompt logon again with error message
if(mysql_num_rows($logonresult)==0){
//Invalidate previous logon
setcookie ("isValid", "False");
echo '<p><font color="990000" size=2><b>Invalid Credentials, Please logon again.</b></font></p>';
echo $sHTML;
mysql_free_result($logonresult);
mysql_close($localdb);
die;
}
// Create Cookies and validate access
$NextMonth=mktime (0,0,0,date("m")+1, date("d"), date("Y"));
while ($myrow=mysql_fetch_row($logonresult)){
// Set Vaidation and User Cookies
setcookie ("isValid", "True",time()+3600); // Validation cookie expires in 1 hour
setcookie ("FName", $myrow[0],$NextMonth);
setcookie ("LName", $myrow[1],$NextMonth);
setcookie ("Salutation", $myrow[2],$NextMonth);
setcookie ("Phone", $myrow[3],$NextMonth);
setcookie ("Ext", $myrow[4],$NextMonth);
setcookie ("Email", $myrow[5],$NextMonth);
setcookie ("Pager", $myrow[6],$NextMonth);
//Cleanup recordset & connection
mysql_free_result($logonresult);
mysql_close($localdb);
// Rediredct to a welcome page
header('Location:welcome.php');
}
}
?>

Alekz
09-26-2002, 06:20 PM
Hi,
Two things that I see after a fast read:

1. Do not use .inc extention for Your include files... connections.inc, common.inc, etc... there's large lists with commonly used filenames for include files, so it's matter of time someone to download Your include with mySQL connection parameters...
Make it .inc.php so that the file will be interpreted by the server and make sure it will never output anything if requested directly.

2. Do not use cookies for validation, use sessions instead. In fact sessions are based on a single cookie which is randomly generated for each new client which makes it acceptably difficult to forge. All other information related to session is maintained server side...
Sending to client a cookie called: isValid and basing Your security on it is the same as passing this through query string. Anyone could forge such a cookie...

Hope this helps,

Alex

aCcodeMonkey
09-26-2002, 09:05 PM
Alex,
Thnx for the tip on the include. I forgot. :(
I wanted to use a session variable for the validation, but the customer "specifically" <groan> wanted a logon for their technicians <it's a helpdesk> that would last the whole day. Since I know form expirience as a former Operations Lead for a helpdesk, i know that the techs will close their browsers and usually open them again when the phone rings, :D a session variable was not an option.

In this sample I limited it to 1hour. <still trying to convince them otherwise>.

Guess I could change it to something more iniquitous....