• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Legacy GM [SOLVED...?] Is it safe to store passwords inside a game?

marasovec

Member
My game is saving levels to a database using php and the database name and passwords are stored in a room code.
Isn't it safer to store the password inside php?
 
Last edited:

NightFrost

Member
Yeah, having that stuff stored in your game is very bad security. The game should only be calling the server, which in turn handles database calls.
 
D

dannyjenn

Guest
I've never worked with PHP or databases, so I don't know.

But I will say, you shouldn't be storing any passwords to begin with. No security is perfect, but at the very least you should be hashing the passwords first and then storing only the hashes (not the passwords).
 

Roderick

Member
Are you talking about level select passwords, like in oldschool cartridge based games, or user passwords?

If the former, then you shouldn't be storing passwords at all; they should be programatically generated based on the info you want to store, and when the user enters a password, the game decodes it to figure out what levels are completed, powerups obtained, etc.

If you mean user passwords, they should be encoded and stored on the server that they are being used for.
 

Tsa05

Member
Isn't it safer to store the password
It is never, under any circumstance "safe" to store a password in any context where "safe" means "people can't get it."

If you include a password with any code that touches an end-user computer, assume that the end user has the password. Even if the password is packed away in your game's code somewhere, or is encrypted/scrambled to make it hard to find... That's like playing hide-and-seek by closing your eyes and screaming "you can't find me." Making your password look hard to find for yourself does not make it hard to find for someone who wants control of your php server and database.

When servers need passwords, there's a few standard, different ways that these work:
1) The user generates a password
2) The user and server agree upon a temporary password via something like a Diffie-Hellman exchange, using public keys
3) The server uses a trust relationship; aka "google login" where another login service is trusted to authenticate the connection, and that service's "ok" message is the login

Most importantly in each method, the server never stores a permanent password. Sometimes, servers store passwords because they're still living in the 1990s, but it's not the correct method. Imagine that someone gains access to that server, whether through a security vulnerability or physical access or theft. That person would now have a list of all the passwords. This is how huuuuge data leaks are happening today; someone steals a list of passwords from an old, insecure, hackable forum and discovers a list of emails and passwords stored in the server's files. Since people tend to change their passwords infrequently, there's also a reasonable chance that many of these passwords still work for other accounts on other websites, making it valuable for thieves to sell hacked server passwords. Here's an article from January 17 this year. Seven hundred million accounts hacked by combining credentials skimmed across many sites. Storing sensitive data leads to problems.

In computer password stuff, one-way computations are really important. Lots of math can be done in 2 directions: For example, "take every letter and move 5 letters down the alphabet" would turn "hello" into "mjqqt". But anyone who knows the formula can easily reverse the operation by subtracting 5.

Servers should never store real login info, so for example... Let's say the password is "hello". The server passes this information through a hashing algorithm; this is a special kind of math problem where the calculation can only be performed one-way, and generates a large letter/number combination. The MD5-hash of "hello" is 5D41402ABC4B2A76B9719D911017C592. The server stores the hashed value. Note that this is NOT simply an encrypted version of the password. It's a completely new password, generated from the real password using a method that cannot be worked backwards. That's important. Encryption can be decrypted.

If anyone steals this hash information, they cannot work the information backwards to obtain the original password. Thus, with perfect theft of server data, the thief still does not know password information. When a user logs in, they type the real password; the server hashes the information and compares with the stored result. Since the hash formula produces a consistent result, but cannot be worked backwards, it effectively works as a substitute for the password.

(Note, MD5 is old and doesn't generate enough data to be truly uniquely secure anymore; use SHA-2)
 

Tsa05

Member
Check out this article discussing php scripts for connecting:
https://www.binpress.com/using-php-with-mysql/

If you're connecting an authorized application, rather then user accounts, the article above has a good starting point. You'll still want some kind of exchange to demonstrate that your application is truly yours, rather than an random query to your database, but the password part is nicely handled there.

Basically, the client application never connects to the database with a username and password; the client connects to a php script that fetches an access credential from a server location outside of the web root and builds a database command with it. In this way, your application can request anything it likes, but your server scripts ensure that the requests are valid and can handle the authorization. The access credential served can additionally be access-limited to further prevent abuse, should an injection get past your scripts.
 

FrostyCat

Redemption Seeker
Servers should never store real login info, so for example... Let's say the password is "hello". The server passes this information through a hashing algorithm; this is a special kind of math problem where the calculation can only be performed one-way, and generates a large letter/number combination. The MD5-hash of "hello" is 5D41402ABC4B2A76B9719D911017C592. The server stores the hashed value. Note that this is NOT simply an encrypted version of the password. It's a completely new password, generated from the real password using a method that cannot be worked backwards. That's important. Encryption can be decrypted.

If anyone steals this hash information, they cannot work the information backwards to obtain the original password. Thus, with perfect theft of server data, the thief still does not know password information. When a user logs in, they type the real password; the server hashes the information and compares with the stored result. Since the hash formula produces a consistent result, but cannot be worked backwards, it effectively works as a substitute for the password.

(Note, MD5 is old and doesn't generate enough data to be truly uniquely secure anymore; use SHA-2)
If you're going to be offering advice on cryptography, you should do your research better than this.

Hashes can always be worked backwards, just not always to a unique result. The difficulty of finding a reverse-engineered result given finished hashes is called preimage resistance, and is something that every hash algorithm is checked for, especially those used for passwords.

The other mistake is recemmending a fast hash for passwords (which MD5, SHA1, SHA2 and even SHA3 all are), the problems of which are clearly documented in articles like this one. Any non-legacy site these days should already be using a slow salted hash like bcrypt or scrypt, either because the developer knew better or simply because it came default with the framework.

@Roderick
I'm talking about a password that I use to connect to the database.
Code:
mysqli_connect("127.0.0.1", "user", "password", "database_id");
That password should always be on the server side in a configuration file. If the server-side app is checked into source control, that file must be put on ignore and added on a one-time basis at deploy time.

I strongly suggest that you learn a PHP framework like CodeIgniter or Laravel/Lumen if you're serious about this. These frameworks show you how things are really done properly and make that easy, instead of making you improvise with low-level components. Even if you still decide to write raw PHP later, knowing how they do it puts you in a better position to do a better job yourself. Yes, there's a performance penalty to pay for using frameworks, but their ability to save developers from their own stupidity is why demand for raw PHP has virtually disappeared off the job market. A lot of the PHP-related follies I've seen on the GMC are obvious signs of having no prior framework experience, and the most outrageous thing is that some of the worst practices have been explicitly recommended by members writing tutorials.
 

Tsa05

Member
@FrostyCat ok, fair, but I wouldn't aggrandize what I posted to the lofty title of "offering advice on cryptography." I think it would be interesting to consider different ways of coming at this; I posted #353545 to cover the server side advice you mentioned in your post, but the crypto stuff is surprisingly tough to cover. My post was about triple its current length, since I was trying to describe implementation of more modern algorithms, and then I admittedly gave up when I realized that it was useless info. Someone wondering about where to "store the passwords" has a long road to travel from that framework or security to a modern cryptographic implementation, so I turned my post into just the outline of the primary concepts.

I cross-referenced a number of Un**y forums for beginners and discovered that the mere concept of hashing passwords and storing database access privately is apparently beyond the "new user tutorial" level; I endeavored to go so far as to suggest ideas and implementations 1% more advanced, in the hopes of making it clear why the very question of storing passwords in code is in the wrong line of inquiry. I should not, perhaps, have mentioned sha2; mentioning MD5 for simplicty was part of explaining the basic idea behind doing transactions more securely and I had a sudden horrifying impulse thought that someone might go and straight-out implement, so I recommended seeking something stronger without diving into a whitepaper on an entirely more advanced system.

I look forward to your coverage of the subject!
 
H

Homunculus

Guest
Sounds unnecessary since you could store the whole password on the server without giving any hint to a possible attacker, instead of giving half.
 

Amon

Member
Solved! I put a half of the password into the game and the other half is hidden inside a folder inside PHP
Solved? I don't think so. I'll be keeping an eye out for any games you have made that require me to login so that I can avoid them.

If you are not going to take the security of your server seriously then I doubt you will care what info is kept on it that belongs to me.
 

marasovec

Member
Well it's not really a whole half. 5 characters are saved in the game those are used for access to the PHP code. Other more than 25 characters are saved in the PHP code
I am a newbie in PHP so... :D
 
Being new is not an excuse to put people's passwords at risk. If you're not experienced to work safely with passwords, then do not make something that requires a password system. People often reuse passwords, even though they shouldn't, and if their login details get stolen cuz of your dumb ass, well then you're no better than the hacker themselves really.
 

marasovec

Member
I think there was little misunderstanding. I'm not saving any personal data. Levels are loaded into the database anonymously. I would never make a game where you must login without any knowledge
 

Pfap

Member
I personally try to avoid passwords at all costs. Does your game or app really need a password? Also, most distribution platforms will require you to post some sort of privacy policy and statement about how you protect and use your users' data. Which with the current skepticism about data safety, could lead to some legal grey area. As far as I know it is not a crime (yet) to knowingly or otherwise mishandle confidential data. It sounds to me like you could find some other way to structure your system to remove the need for a password per client.
 

Pfap

Member
I think there was little misunderstanding. I'm not saving any personal data. Levels are loaded into the database anonymously. I would never make a game where you must login without any knowledge
What is the password for? Normally users make requests to the server and then the server handles the requests to the database. So, one of your users could submit a level to your server, and then your server could check it over and then submit it to your database. This way there is only 1 connection to your database.
 
Usernames and passwords are personal data. People often reuse them. If I log into your game with "RefresherTowel" as my username and "myactualpassword" as my password, then if someone gets a hold of that they have access to my other accounts. Don't use a login system unless you can safely handle passwords. Not knowing how means you don't make a login system.
 

Pfap

Member
Usernames and passwords are personal data. People often reuse them. If I log into your game with "RefresherTowel" as my username and "myactualpassword" as my password, then if someone gets a hold of that they have access to my other accounts. Don't use a login system unless you can safely handle passwords. Not knowing how means you don't make a login system.
Although, who hasn't been hacked before...
 

GameDevDan

Former Jam Host
Moderator
GMC Elder
Plenty of PHP-based content management systems (for example, Wordpress) store the database password in plain text within PHP files. In theory an attacker can only access them if they have already breached your security (for example by knowing the password to your web host's file manager, or obtaining FTP login details etc.)

Don't store any of the password in the game code itself, not even 5 characters. Just have the PHP script on the server log in to the database after being prompted by the game.
 

FrostyCat

Redemption Seeker
Why not? :D
The attacker would have to decompile the game and then somehow find the folder inside PHP where no one has access but me
Dunno if it sounds stoopid or unnecessarily complicated
You thinking that the attacker has to decompile your game first is where the stupidity starts.

If the requests are in plain HTTP, an attacker can simply install your game and WireShark the database password fragment from its outbound requests. If the server itself has been rooted or has a remote execution vulnerability, then the attacker can just swap out the PHP file handling password requests and intercept plaintext passwords there along with the database password fragment.
That's right. That's why I asked on a PHP forum how to safely (nothing is 100% safe) hide this pw inside PHP
VVV
https://www.php-forum.com/phpforum/viewtopic.php?f=2&t=28969
A much more productive way to learn how it's done safely in PHP is to adopt a PHP framework or CMS, rather than rolling your own as a novice.

The goal is not to hide the PHP file containing the password inside the live server, that's a fool's errand. These rank much higher on importance:
  • Keeping your server's admin SSH private key safe
  • Writing your PHP in a way that does not expose it to remote execution, SQL injection and path traversal attacks (e.g. not using exec(), using prepared statements or an ORM, not including or echoing paths specified by the user, etc.)
  • Excluding the file containing the database password from the code repository
  • Making the database listen on 127.0.0.1 instead of 0.0.0.0
 

marasovec

Member
Writing your PHP in a way that does not expose it to remote execution, SQL injection and path traversal attacks (e.g. not using exec(), using prepared statements or an ORM, not including or echoing paths specified by the user, etc.
- OK
Excluding the file containing the database password from the code repository
- OK
Making the database listen on 127.0.0.1 instead of 0.0.0.0
- OK
 
Top