0

I have a website which I have users input their username/pass to login and stores this information in a file. Here is my current code:

function getPassword( $user )
{
  $passwords= array 
       (
        'Admin' => '123456',
        'Moderator' => 'abcde'
       );
 eval(file_get_contents('./login.info'));  //<--- THIS is where usernames/passwords are stored  

    $password = $passwords[ $user ];
    if ( NULL == $password )
        return NULL;

    return array( $user, $password );
}

This is the code I have for users creating new accounts:

<?php
if((isset($_POST['username']))and(isset($_POST['password']))){
 $file = "login.info";
 $fh = fopen($file, 'a');
//prevent sql injection
function check_field($fh)
{
  if(!preg_match("/[^a-zA-Z0-9\.\-\_\@\.\+\~]/",$fh))
  return TRUE;
  else
  return FALSE;
}
if(!check_field($_POST[username]))
{
  header("Location:illegalchars.html");
  break;
}
if(!check_field($_POST[password]))
{
  header("Location:illegalchars.html");
  break;
}
 fwrite($fh, '$passwords["'.$_POST['username'].'"]="'.$_POST['password'].'";');
 fclose($fh);
 header("Location:success.html");
 break;
}
?>

I know my code isn't pretty.. and has major issues.
One of which is: If someone creates an account with username x, anyone can still create x with a new password to gain control.
The easy solution I had was to move the eval(file_get_contents('./login.info')); on top of the admin accounts and make new accounts append on THE TOP of the list of new user/passes. However, I can't figure out why putting eval on top of the array doesn't work. Also, how I can get the code to append on the top of the list. Any help is greatly appreciated.

==EDIT== I know there is MUCH criticism on this code, but could someone please just answer the question? I'm not trying to improve security/performance at the moment (this is for a proof-of-concept game, eventually, this whole thing will have to be rewritten anyways). I just want a functional script, please answer the question? :]

dukevin
  • 22,384
  • 36
  • 82
  • 111
  • 3
    This really feels like you are attempting to patch a sinking ship that has been attacked by pirates... I really hope this is some kind of internal app with no hope of being hacked. – Jakub Jan 18 '11 at 05:26
  • Yes, the purpose of this website is to create simple authorization for an online game, nothing important. – dukevin Jan 18 '11 at 05:31
  • 1
    There should be some kind of quality control with things like this... People TRUST you that your login method is secure, so people will use the same password for this game as for their bank account, mobile phone etc... Do them a favour, and hash their passwords, and protect their details because you are only helping the 'hackers'... And let's face it, this architecture could be hacked by a 10 year old. It sucks! – Darbio Jan 18 '11 at 05:46
  • I have warnings all over this login page that their passwords are not encrypted and can be seen by the site admin. I probably will add encryption sooner or later. – dukevin Jan 18 '11 at 05:53
  • Made my day. The comment regarding SQL injection just killed me – Your Common Sense Jan 18 '11 at 12:48
  • @Kevin for the love of god don't write your own unsafe(probably) login system. Use openid(lightopenid) instead as one of the safe alternatives! – Alfred Jan 18 '11 at 21:12
  • @Kevin it is difficult to post the write answer on here because there are so many things that can go wrong! – Alfred Jan 19 '11 at 07:46
  • @Alfred I understand this, but I'm just trying to get this up and running (will have to be redone professionally in the future). All I would like is to prevent duplicate usernames, however ugly the method may be. I suggested appending new usernames to the top of the list, so that they don't overwrite existing passwords. I was also playing with get_file_contents but this is going to be harder since user/pass are just plaintext $password = $passwords[ $user ]; (not even in an array). – dukevin Jan 19 '11 at 07:52
  • @Kevin Duke can't you use a database? Then it is very easy to prevent duplicate usernames. If for example you can't use mysql/postgresql you should check out if you can use SQlite. You can probably use that because php5 has it precompiled I believe. You should try if you can run the script in this link => http://www.bernzilla.com/item.php?id=296. Please report back to me after that! – Alfred Jan 19 '11 at 07:57
  • @Alfred Thanks for being so helpful! Anywho, I inputted that php code and my website shows "I Want It That Way" – dukevin Jan 19 '11 at 08:10
  • I understand you correctly you got a working sample? Still I don't mind if you add me to XMPP to talk!? – Alfred Jan 19 '11 at 08:13

3 Answers3

2

Frankly, there are major issues here.

Zero. You shouldn't be storing plaintext passwords. Ever. Use one-way hashing such as sha1() (not md5) with salt, plenty of manuals on the internet about that.

One. Using eval() is bad practice, both in terms of performance, and in terms of security. Seek for other mechanisms, they're always out there.

Two. You should use reliable data storage mechanisms, other than php file. Suggest using RDBMS such as mysql which has means of ensuring no duplicate records are ever created for users.

Three. You shouldn't place any special meaning on the username, such as admin or mod, make permissions a special field, or better yet, consider using role-based authorization.

Four. You cannot control security of the code run for certain user without proper architecture. Consider using object-based MVC approach, you again can find many manuals about that.

Sorry of this sounds critical, but I seriously believe that this is a better answer than publishing patches to the code you presented.

Dennis Kreminsky
  • 2,117
  • 15
  • 23
  • Yes, I know having mySQL is ideal, but I don't have that available to me. Also, the purpose of this website is to create simple authorization for an online game, nothing important. I also have warnings on the site that state the site admin can see passwords – dukevin Jan 18 '11 at 05:30
  • My questions still hold though, how can I make new logins/pass'es append to the top of the list. Doing this prevents people from creating duplicate accounts. – dukevin Jan 18 '11 at 05:33
  • If it is an online game, get ready for attacks and misuse, I also strongly suggest that you improve your hosting capabilities and get mysql. With flat-file storage you will not only have to care about unique usernames, but about not losing your data upon multiple concurrent writes from several web server processes (each client connection will create one). administrator shouldn't be _seeing_ passwords, really, this is a poor business process; he/she should be able to _reset_ them, which is a better approach. – Dennis Kreminsky Jan 18 '11 at 05:36
  • This isn't a state-of-the-art game, rather a proof of concept for the time-being. – dukevin Jan 18 '11 at 05:39
  • Dude... Listen to etranger and take onboard what he is saying. This isn't just mindless criticism... This is REAL advice. – Darbio Jan 18 '11 at 05:43
  • 1
    You should get rid of evals, use some sensible text format (such as ':'-separated fields, used for user-based authentication on unix), read it with file_get_contents, parse on every request, i.e. into an associative array, and check that new user is not in that array's keys, as a prerequisite before adding user and appending to user file. you will also have to implement some locking to make sure the file isn't read by other processes while it's being written. – Dennis Kreminsky Jan 18 '11 at 05:43
  • @JD - As I said earlier, this is proof-of-concept, probably only 30 people will register on this. . . . @etranger - could you elaborate further in a new post? – dukevin Jan 18 '11 at 05:48
  • @Kevin Duke, with all the possible respect, lack of audience is a poor excuse for poor quality in development :) And I'm afraid that I cannot elaborate more than I did, this will require some effort on your side. – Dennis Kreminsky Jan 18 '11 at 05:49
  • hehe, yes, but this login is the least of my worries :) – dukevin Jan 18 '11 at 05:51
  • @Kevin Duke, perhaps doing this part of the system properly will help you understand how to develop the rest of the system properly, instead of hacking together a solution. As suggested, hashing passwords is childs play (e.g. $password = md5("password"); ) and provides a level of security for your platform. Frankly I am concerned by your responses and your levels of blase... If you are serious about this, do it properly man! – Darbio Jan 18 '11 at 06:02
  • @JD no, I am not serious about this. But please do bring me to a page that explains hashing better, as i have no knowledge on it. I will implement hashing asap, as soon as i know how to – dukevin Jan 18 '11 at 06:06
1

Login Script

If you can't really don't use anything like openid, then here you could view my improved script to your login script(Should be last resort..).

OpenId

Please for the love of good don't write your own login-system(do not store passwords). Read this article from Stackoverflow author about how Lifehacker got hacked. I especially like this quote which I agree with completely:

I'm not here to criticize Gawker. On the contrary, I'd like to thank them for illustrating in broad, bold relief the dirty truth about website passwords: we're all better off without them. If you'd like to see a future web free of Gawker style password compromises -- stop trusting every random internet site with a unique username and password! Demand that they allow you to use your internet driver's license -- that is, your existing Twitter, Facebook, Google, or OpenID credentials -- to log into their website.

You should instead use for example openid(lightopenid). Read the link to find out how easy it is to integrate openid into your website.

Community
  • 1
  • 1
Alfred
  • 60,935
  • 33
  • 147
  • 186
  • I'll try this out, but the log-in system is done in the game's GUI, not the website. The game calls this code to login. creating new accounts is web-based. I will have to see if open-id is workable. – dukevin Jan 19 '11 at 06:51
  • if the GUI has the ability to use webbrowser you could easily integrate openid. I really don't think you should be storing passwords. – Alfred Jan 19 '11 at 07:15
  • All user/passes need to be in the form $password = $passwords[ $user ]; ...is this possible with openid? The game gui can't use webbrowser – dukevin Jan 19 '11 at 07:31
  • 1
    if you can not use something like openid you should really learn PDO for SQL-injections(http://tinyurl.com/3yjzkjo). P.S: you should store your passwords in a database if possible and not a file on dics, learn how to use phpass properly to store your passwords safely(http://tinyurl.com/ynpyvo). Also you should learn about CSRF(http://tinyurl.com/2t7bzd). Finally you should learn how to protect against XSS using filter(http://tinyurl.com/5vucbsb ). Also this http://tinyurl.com/ybefbvb. These things can make your login safe(r)(but then again, I am not a security expert ;))! A lot can go wrong :$ – Alfred Jan 19 '11 at 07:44
  • Thanks, I'll give those a good read when i come around to rewriting this – dukevin Jan 19 '11 at 08:00
1

OMG!

Can I post this on dailywtf.

There's nothing intrinsically wrong with eval and plaintext databases, but only if there's not a better way of solving the problem. And even then you should be filtering the input to eval extensively and using abstraction on top of the database.

OTOH reading the entire database every time you want to perform any operation is just plain wrong.

Storing unencrypted passwords is wrong.

You've said you can't use mysql - but what about dbm? sqlite? A quick google suggests that there's lots of flat-file abstraction layers running on top of plain text or CSV files.

symcbean
  • 47,736
  • 6
  • 59
  • 94