include and login securites

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

Post Reply
pella.d
Forum Newbie
Posts: 11
Joined: Mon Apr 11, 2005 3:05 am

include and login securites

Post by pella.d »

ok, i've got two questions
I've got a small web app setup, but I don't know a whole lot about the finer details in security
A friend gave this to me when I asked him for a login/password checking script:

Code: Select all

<?
if(isset($HTTP_COOKIE_VARS['username']) && isset($HTTP_COOKIE_VARS['password'])){
	$username = safeString($HTTP_COOKIE_VARS['username']);
	$password = safeString($HTTP_COOKIE_VARS['password']);
}
else if(isset($HTTP_POST_VARS['username']) && isset($HTTP_POST_VARS['password'])){
	$username = safeString($_POST['username']);
	$password = safeString($_POST['password']);
} else {
	include 'login.php';
	exit();
}
include 'dbconnect.inc.php';
$qstr = "SELECT username, password FROM members WHERE username = '".$username."' and password = '".$password."'";
$result = mysql_query($qstr);
if (mysql_num_rows($result)) {
	setcookie("username", $username,0,"/");
	setcookie("password", $password,0,"/");
} else { 
	include 'login.php';
	exit();
}
function safeString($targetVariable) {
  $targetVariable = addslashes(trim($targetVariable));
  return $targetVariable;
}
?>
Now I'm wondering if this is secure at all, I got it working and all, it's included to the top of all the pages that require a logged in user. Which is another point, is it secure to just include that into the top of a page?


and my second question is to deal with a database connection include.
If all the details for the database are in the include, like $host, $db, $dbuser, etc, is that a security issue in itself?
Is it possible to exploit that include somehow and modify the database contents?


If my questions are lacking detail just let me know, and I'll pull up some examples or something.
thanks for any help
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

It's using antiquated variables mixed with the new ones ( $HTTP_COOKIE_VARS = $_COOKIE ). It also appears that your passwords are not encrypted in any way when inserted into the database. Most people would want to have it hashed and then store the hash. What's worse is that the password is stored, in plaintext, in the Cookie. That's an nightmare.

Personally, I would use a function or login class instead of relying totally on an include. Furthermore, this code doesn't offer optional password remembering (it relies totally on cookies), it doesn't use Sessions, and it doesn't offer a logout function.
pella.d
Forum Newbie
Posts: 11
Joined: Mon Apr 11, 2005 3:05 am

Post by pella.d »

Wow damn, lots of problems.
So I did a bit of searching, and to encrypt the password should I be using the md5 thing?
Or is there another method?
Should it also be stored encrypted in the cookie?

do you think you could elaborate on a function or login class?

I searched for some tutorials and examples but every single one used a different method so I wasn't so sure as to which one to use.
Do you think you can help point me in the right direction?
thanks
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

You need to grab some examples...

Using sessions, you can authenticate the player and set a checking variable like $_SESSION['authenticated'] = 1. There is no need to store passwords or anything else in a cookie.

In your app - to ensure a user is logged in, just check that $_SESSION['authenticated'] is a) set, b) equal to 1.

There's a lot more obviously, but this is the basic idea.
pella.d
Forum Newbie
Posts: 11
Joined: Mon Apr 11, 2005 3:05 am

Post by pella.d »

http://www.devshed.com/c/a/PHP/Creating ... in-Script/

So from reading, this one sounds secure, and seems to do what you guys have pointed out
but i have a question about some of the code.

Code: Select all

PEAR::setErrorHandling(PEAR_ERROR_DIE);
Now It says its pointing to a PEAR object, but what is a pear object? Will this work be default or while I need to somehow install some 3rd party pear object thing.
Theres a few other things I'm not too familiar with, like these:

Code: Select all

$dsn = "mysql://$db_user:$db_pass@unix+$db_host/$db_name";
$db = DB::connect($dsn);
im guessing that this is just some other way to connect to the database? Will this work by default also, I'm not sure how much access I have to manipulate the server.
If anyone knows of a better script, by all means.
User avatar
nickclarkson
Forum Newbie
Posts: 1
Joined: Tue Apr 19, 2005 4:15 pm

Post by nickclarkson »

PEAR is a "framework and distribution system for reusable PHP components." (from http://pear.php.net). It's basically a framework consisting of various classes of functions that perform different tasks, e.g. database-related, forms-related etc..I'm no expert, but take a look at the official site if you have the time.

The code you posted is just the PEAR method of connecting to a mysql database. The same can be performed in 'regular' php;

e.g. $link=mysql_connect($db_host, $db_user, $db_pass);

It will mean that you will have to have PEAR on your web server of course, something that I've almost always had problems getting to work myself, but that's probably cos I'm stupid :) but again, see the official page for how to do that (assuming you have access to your server).

Good luck,

Nick
kantissa
Forum Newbie
Posts: 3
Joined: Tue Apr 19, 2005 9:40 pm

Post by kantissa »

Maugrim_The_Reaper wrote:
Using sessions, you can authenticate the player and set a checking variable like $_SESSION['authenticated'] = 1. There is no need to store passwords or anything else in a cookie.

In your app - to ensure a user is logged in, just check that $_SESSION['authenticated'] is a) set, b) equal to 1.
Correct me if I'm wrong but isn't is possible to start a session in other website and set $_SESSION['authenticated'] = 1 and now enter to this website and what you know, you are already authenticated. This of course would need that someone already knows a part of the original code in order to set this $_SESSION['authenticated'].

This leads to another question, considering that the above is correct. If I have username and password to the website which uses sessions for authentication/identification and I successfully log in (so $_SESSION['authenticated'] = 1 is set) and then directly enter to some other website and use print_r($_SESSION) to find out everything about the session varibles. Now I will have the information about this $_SESSION['authenticated'] and maybe some other information too ($_SESSION['userlevel'] = 3 or something similar).

So the question finally. What could I do to avoid this to happen?

The chances for this to happen is probably low (especially on private websites) but I am interested to know if there is something that can be done for this. Or should I not rely on sessions and use some other techniques for authentication?
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

session variables are stored on the server. Not in the browser. Only the client's session ID is (partly) kept in the browser.
kantissa
Forum Newbie
Posts: 3
Joined: Tue Apr 19, 2005 9:40 pm

Post by kantissa »

Seems i have got something wrong, which in this case is good. Now I tried two things.

1. example1.com, login and then click on to a page in example1.com which has print_r($_SESSION) which gives out something like following

Array ( [username] => kantissa [user_level] => 1 )

This is the situation I was referring earlier. But now i tried this

2. example1.com, login and then click to a page in example2.com to see if I could print out the information again but result was just empty.

Array ( )

And this relieves me. I got it wrong in the first place but now I undertand it better. So I guess session is pretty safe way anyway to save the information, right? But how about this situation in shared hosting places? If I got it right, then the session data is saved in /tmp, so is it same /tmp for all users in the shared hosting place or is there somekind of separation between the users. I don't two have domains in one shared place so I can't try it...

Anyway, thanks for clearing me up.
bobsta63
Forum Commoner
Posts: 28
Joined: Thu Apr 21, 2005 7:03 pm
Location: Ipswich, UK

Post by bobsta63 »

Session variables are stored on the server mate.
User avatar
hanji
Forum Commoner
Posts: 46
Joined: Fri Apr 29, 2005 3:23 pm

Post by hanji »

Hello

I know I'm jumping late into this thread.. but would like to see some more 'chatter' in the security forum.

Code: Select all

$qstr = "SELECT username, password FROM members WHERE username = '".$username."' and password = '".$password."'";
$result = mysql_query($qstr);
if (mysql_num_rows($result)) {
    setcookie("username", $username,0,"/");
    setcookie("password", $password,0,"/");
} else { 
    include 'login.php';
    exit();
}
I have a couple of problems with this bit a code.

Problem #1
Using clear passwords.. this is already mentioned above. Use a md5 crypt.. and compare the crypt value.

Problem #2

Code: Select all

if (mysql_num_rows($result)) {
I see that we're wrapping our input values with a safeString() function.. and doing a 'addslashes()'. I'm glad that there is some input sanitation.. but is it enough to stop SQLInjection? Maybe.. maybe not. The problem to me is that we're just checking for a recordcount for a pass or fail action. All you need to do is trick the query (trick is unknown) to give a record or records back to the condition. I would add another layer of security.. basically comparing values... This example uses the 'clear' password example for simplicity.

Code: Select all

$qstr = "SELECT username, password FROM members WHERE username = '".$username."' and password = '".$password."'";
$result = mysql_query($qstr);
$passFlag = false;
if (mysql_num_rows($result)) {
	$db_username	= mysql_result($result,0,'username');
	$db_password	= mysql_result($result,0,'password');	
	if($db_password == trim($password) && $db_username == trim($username)){
		$passFlag	= true;
	}
}
mysql_free_result($result)

if($passFlag){
	// set up authentication
}else{
	include 'login.php';
	exit();
}
Problem #3

Code: Select all

setcookie("username", $username,0,"/");
setcookie("password", $password,0,"/");
Why are you storing username and password in the cookie? I would go with session and set a 'isAuthenticated' boolean or value.. and check that. Putting those values in a cookie is potentially dangerous with XSS (Cross Site Scripting). If someone is able to steal your cookies.. they would have:
1. The Domain of where the cookie was written
2. The Username
3. The Password

Granted if someone stole your cookie and you were using Sessions. they would be able to hijack your session, but you could put checks to help prevent that (ie: check useragent, IP, etc).

You could store information in the cookie.. and encrypt it using PHP's mcrypt functions as well to tighten things up.

I think a thread like this is great to open up conversations of securing our code. I would like to hear other's ideas on how to implement a 'tighter' grip on logins, etc.

hanji
Post Reply