Edward Posted March 21, 2007 Share Posted March 21, 2007 Hi, I'm creating a basic website which can only be viewed by users with a password. I need to make sure there is NO chance of unauthorised access. I'm using 4 php pages at the moment and I was wondering if someone can see if my code is fool proof, or if there is a better way? index.php <?php if (isset($_POST['submit'])) { if (strtolower($_POST['password']) == 'my_password') { session_start(); $_SESSION['active'] = 'TRUE'; header('Location: welcome.php'); } else { echo '<p>Error!</p>'; // HTML page with form goes here } } else { // HTML page with form goes here } ?> welcome.php <?php ob_start(); session_start(); if ($_SESSION['active'] != 'TRUE') { unset ($_SESSION); session_destroy(); header('Location: index.php'); } // HTML Welcome message goes here ?> log_out.php <?php session_start(); unset ($_SESSION); session_destroy(); header('Location: end.php'); ?> end.php: <?php // HTML exit message goes here ?> Thank you very much. Quote Link to comment Share on other sites More sharing options...
majocmatt Posted March 21, 2007 Share Posted March 21, 2007 There's a few things you could do. Firstly, you need to run $_POST['password'], and username if you have one, through $password = mysql_real_escape_string($_POST['password']) Since someone can spoof the session $_SESSION['active'], I would also add the password session upon login: $_SESSION['password'] = $password; and on each page put in the if statement add: if ($_SESSION['active'] != 'TRUE' && !isset($password)) { Also, instead of isset($_POST['submit']), you could add a unique token. On the form you could start a session like $token = mt_rand() and on the processor page, make sure that session is there and the value is the same and it was on the previous page. That's a few ideas Quote Link to comment Share on other sites More sharing options...
Edward Posted March 21, 2007 Author Share Posted March 21, 2007 Hey majocmatt, thanks for your comments, I'm going to work through them and see if I can add them in, however I've just noticed that you can click 'back' in the browser after logging out and you're still logged in! The only way around this I know is if I put a flash swf in the page, then for some reason it refreshes the page after 'back' is pressed and it logs you out, do you know if I can avoid this?? Quote Link to comment Share on other sites More sharing options...
Edward Posted March 21, 2007 Author Share Posted March 21, 2007 Hmm, I've noticed that if I put a Flash swf on my 'private' page, clicking 'back' in the browser doesn't keep you logged in, this is true for Safari, Firefox and IE. However without the Flash swf, clicking 'back' keeps you logged in in Safari and IE. Does anyone know a fix to keep the user logged out when they click 'back'? It's really urgent! Thank you. Quote Link to comment Share on other sites More sharing options...
sps Posted March 22, 2007 Share Posted March 22, 2007 Are you sure it isn't just displaying the page from the browsers cache? Quote Link to comment Share on other sites More sharing options...
Edward Posted March 22, 2007 Author Share Posted March 22, 2007 I'm not sure, is there a way to avoid it displaying it either way? I don't want people to be able to go 'back' because this could create a risk on shared machines. Quote Link to comment Share on other sites More sharing options...
sps Posted March 22, 2007 Share Posted March 22, 2007 Try placing - session_cache_limiter('nocache'); before your session_start() calls. This SHOULD send the proper headers so that neither proxy or browser caching will occur. If you need caching enabled then hopefully someone else can give you a more creative solution. Edit: You may want to try session_cache_limiter('must-revalidate'); too, as I remember having issues with IE and the nocache directive. Quote Link to comment Share on other sites More sharing options...
Edward Posted March 23, 2007 Author Share Posted March 23, 2007 Unfortunately they aren't working either :-\ I'm using OSX and Safari. Quote Link to comment Share on other sites More sharing options...
per1os Posted March 23, 2007 Share Posted March 23, 2007 Unfortunately they aren't working either :-\ I'm using OSX and Safari. lol thats your first mistake =) Quote Link to comment Share on other sites More sharing options...
sps Posted March 23, 2007 Share Posted March 23, 2007 Did you put the session_cache_limiter('nocache'); between ob_start(); and session_start(); on your welcome.php file? (It must be before session_start() calls and I believe AFTER ob_start() calls.) If that doesn't work try removing your ob_start() calls and see what happens. If that still doesn't work try searching for different cache limiter directives, nocache should work in Safari if no other cache related headers are being sent first, but there may be other options you could use that I am not familiar with. Quote Link to comment Share on other sites More sharing options...
Edward Posted March 27, 2007 Author Share Posted March 27, 2007 Hey, Thanks for your help but unfortunately none of them work :-\ I'll try looking for other session_cache_limiter ideas as you suggested, thanks again. Quote Link to comment Share on other sites More sharing options...
Edward Posted April 3, 2007 Author Share Posted April 3, 2007 Going back to the first post where $password = mysql_real_escape_string($_POST['password']) was recommended, can I simply do this: $username = mysql_real_escape_string($_POST['username']); $password = mysql_real_escape_string($_POST['password']); $sql = 'SELECT * FROM users WHERE username = "'.$username.'" AND password = "'.$password.'" ORDER BY username ASC;'; As I've seen people do the following, but I don't know what the advantage is as I don't understand what it's doing differently: $link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password'); query = sprintf("SELECT * FROM users ('username', password') VALUES ('%s', '%s'')", mysql_real_escape_string($product_name, $link), mysql_real_escape_string($product_description, $link); mysql_query($query, $link); Any help on differences/advantages would be great! Quote Link to comment Share on other sites More sharing options...
sps Posted April 3, 2007 Share Posted April 3, 2007 Use your first example and add 'LIMIT 1' to the end of the query. (After all, there can't be more than one username with that password in your setup, right?) That along with the escaping and single quote usage in your first example is fine for SELECT statements. Your second example appears to be partly from the php manual (as $product_name and $product_description don't fit your username/password variables.) The reason they do it that way in the manual for that example is to prevent SQL Injection on an INSERT statement. http://phpsec.org/projects/guide/3.html#3.2 Quote Link to comment Share on other sites More sharing options...
Edward Posted April 4, 2007 Author Share Posted April 4, 2007 Yes that was taken from the PHP maual. Thanks for your help, I will use that for INSERT queries. I have noticed however that I have already validated by $_POST['username'] and $_POST['password'] variables and upon successful validation, I have converted them to $username and $password. Can I do the same thing with them (like below), or do they need to be $_POST? $username = mysql_real_escape_string($username); $password = mysql_real_escape_string($password); $sql = 'SELECT * FROM users WHERE username = "'.$username.'" AND password = "'.$password.'" ORDER BY username ASC LIMIT 1;'; The guide you linked to says to always use single quotes, does it mean like this: $username = mysql_real_escape_string($username); $password = mysql_real_escape_string($password); $sql = 'SELECT * FROM users WHERE username = \''.$username.'\' AND password = '\'.$password.'\' ORDER BY username ASC LIMIT 1;'; Or should I put the statement inside double quotes, and use single quotes around the values, like this: $username = mysql_real_escape_string($username); $password = mysql_real_escape_string($password); $sql = "SELECT * FROM users WHERE username = '".$username."' AND password = '".$password.'" ORDER BY username ASC LIMIT 1;"; Lastly (sorry!...), if I'm going to do an INSITE query, should I always use this: $link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password'); query = sprintf("SELECT * FROM users ('username', 'password') VALUES ('%s', '%s') LIMIT 1", mysql_real_escape_string($username, $link), mysql_real_escape_string($password, $link); mysql_query($query, $link); Is it as straight forward as %s for a varchar, %d for an integer? THANK YOU very much! Quote Link to comment Share on other sites More sharing options...
sps Posted April 4, 2007 Share Posted April 4, 2007 Personally I would use - $sql = "SELECT * FROM users WHERE username = '".$username."' AND password = '".$password.'" ORDER BY username ASC LIMIT 1;"; simply for readability. But your example with all single quotes - $sql = 'SELECT * FROM users WHERE username = \''.$username.'\' AND password = '\'.$password.'\' ORDER BY username ASC LIMIT 1;'; may have a tiny performance benefit. (As php doesn't have to evaluate single quoted strings for variables.) And again, for readability I would use the $username and $password variables as you have them at the sacrifice of the tiny bit of overhead required to assign a new variable. (It also makes it easier to add further checks (i.e. regex, etc.) on them in the future.) And yes, you would use %d for integers and %s for strings. (and %f for float, etc.) There should be a list in the php manual under sprintf that shows the different place holders. The reasoning behind using that being (AFAIK) that sprintf will throw an error if something other than that type is injected in that field. (Though for all strings it seems useless IMHO.) Quote Link to comment Share on other sites More sharing options...
Edward Posted April 5, 2007 Author Share Posted April 5, 2007 Regarding the following code for the INSERT query: $link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password'); query = sprintf("INSERT INTO users ('username', 'password') VALUES ('%s', '%s') LIMIT 1", mysql_real_escape_string($username, $link), mysql_real_escape_string($password, $link); mysql_query($query, $link); Can I do it without the 'link' section as follows: query = sprintf("SELECT * FROM users ('username', 'password') VALUES ('%s', '%s') LIMIT 1", mysql_real_escape_string($username), mysql_real_escape_string($password); mysql_query($query); This is because I already have a function set up for my connection which I want to call. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.