views:

270

answers:

8

I want some input on what you guys think is the most secure way to connect to a mysql database using php. Currently the way Im doing it is a utility php file that I include in the top of all my other php files. The utility php file is this

<?php
if(!defined('IN_PHP')){
    die("hackerssss");
}
$mysql_host = "localhost";
$mysql_user = "root"; 
$mysql_pass = "root"; 
$mysql_db = cokertrading;
?>

Any suggestions?

+9  A: 

Suggestion: You should probably never be running as root; create another account and give it the 'least' privileges required for your site.

Alex
ok thanks for the help
tim
+1 for the "least privileges" approach.
Pekka
+1 for correcting using semi-colon; root is never a good idea.
turdfurguson
+4  A: 
  • Define a pair of proper login credentials instead of "root/root" (change the user name to something else, and choose a complicated password);

  • if possible restrict access to the database to localhost on a firewall level or, as @Scott says in the comments, set mySQL to listen to connections from 127.0.0.1 only. If both is not possible, restrict access on mySQL level. ("username"@"localhost")

Pekka
The firewall rules aren't a bad idea, but they're unnecessary. You can accomplish the same by changing the mysql config to only listen on 127.0.0.1
Scott Anderson
Unless cokertrading is defined as a constant somewhere else in the file.
Unkwntech
@Scott good point. @Unknwntech yup, it's not sure. Removed.
Pekka
thanks will do!
tim
+1 for restricting access to the local machine.
Daniel Vandersluis
+1  A: 

because php scripts are server side - ie they are parsed on the server and only the output is sent to the browser - the way you are doing this is perfectly secure.

The only way that people would be able to get your username and password would be to acctually hack into your server and view the source code - in which case there's no way (in php) to protect against this.

Thomas Clayson
+3  A: 
  1. remember that anyone who can read that file will know your SQL password: set it not readable by others
  2. don't login with root: create a user for each application
  3. don't use "root" as your root password
  4. don't give your password to everyone
Lo'oris
A: 

This whole question depends entirely on whether the database is on the same server as your web-server (apache etc). Until we get this we cannot give you an answer.

m.edmondson
FYI, you would be supposed to write comments as this one... as comments to the question, not as answers.
Lo'oris
+2  A: 

First of all, as Alex said, you should be using a special account for that application with limited privileges.

After that, take a look at this How To secure passwords in PHP where you will find answers like:

User11318

Several period misread this as a question about how to store passwords in a database. That is wrong. It is about how to store the password that lets you get to the database.

The usual solution is to move the password out of source-code into a configuration file. Then leave administration and securing that configuration file up to your system administrators. That way developers do not need to know anything about the production passwords, and there is no record of the password in your source-control.

da5id:

Store them in a file outside web root.

Sockleg:

If you're hosting on someone else's server and don't have access outside your webroot, you can always put your password and/or database connection in a file and then lock the file using a .htaccess:

<files mypasswdfile> order allow,deny
deny from all </files>

pdavis:

For extremely secure systems we encrypt the database password in a configuration file (which itself is secured by the system administrator). On application/server startup the application then prompts the system administrator for the decryption key. The database password is then read from the config file, decrypted, and stored in memory for future use. Still not 100% secure since it is stored in memory decrypted, but you have to call it 'secure enough' at some point!

Vagner:

Your choices are kind of limited as as you say you need the password to access the database. One general approach is to store the username and password in a seperate configuration file rather than the main script. Then be sure to store that outside the main web tree. That was if there is a web configuration problem that leaves your php files being simply displayed as text rather than being executed you haven't exposed the password.

Other than that you are on the right lines with minimal access for the account being used. Add to that

* Don't use the combination of username/password for anything else
* Configure the database server to only accept connections from the web

host for that user (localhost is even better if the DB is on the same machine) That way even if the credentials are exposed they are no use to anyone unless they have other access to the machine. * Obfuscate the password (even ROT13 will do) it won't put up much defense if some does get access to the file, but at least it will prevent casual viewing of it.

Peter

References:

Garis Suero
My answer is actually better if you have access to the server configuration.
hopeseekr
+2  A: 

These people are all crazy.

This is what all the pros do. My qualification: I was the lead of the secure sign on site for a major branch of the U.S. military:

In your apache vhost for each site you do something like this

<VirtualHost *:80>
    ServerName www.phpexperts.pro

    SetEnv SQL_HOST localhost
    SetEnv SQL_USER phptutor
    SetEnv SQL_PASS someRandom-234qasdfasPass
    SetEnv SQL_DB   rosettablog
</Virtualhost>

Then you run these commands on your vhost config file:

sudo chown root:root 29_phpexperts.pro.conf
sudo chmod 0600 29_phpexperts.pro.conf

What that does is set the user to root and the group to root and then sets file permissions to allow root to read and write it and apache only to read it. As long as apache is started by the root user, only root will then need to have read access to it (thanks @grossvogel).

In your code you do this:

$mysql_user = $_SERVER['SQL_USER'];

Voila! No plaintext password viewable to everyone on your system. Only viewable to apache and root. For kicks, you should encrypt it w/ your secret hash but that might be overkill for most instances.

The odds that someone will be in your root group are very small, and if they do, nothing exception encryption will slow them down much.

What's worse? A file readable by everyone and all they have to do is grep -i PASS * -R or this system, where they have to hack either your root account or be able to write to your PHP server? In any case, they would have long-before gotten your password.

Also, the other way to do this is to set the creds (encrypted, hopefully) into APC and then unset the Apache var.

hopeseekr
So instead of storing the cleartext password into a file viewable by whoever has access to it... you store the cleartext password into a file... viewable by whoever has access to it. *Oh, really clever Mr. I work for the military.*
Lo'oris
+1 I'm not securing anything for Uncle Sam, but this is my preferred method, too. BTW: On Ubuntu Server, I have my virtual host files owned by root:root (not readable by web server or other users), and it works fine, as apache is started by root through init.d.
grossvogel
My first thought was, awfully arrogant, but you can't argue with top notch input. On second thought, I can find out the database password by doing a `print_r($_SERVER)` *in any PHP file on the VirtualHost*, no matter what connection that file has to the configuration files. That looks like a HUGE downside to me - or am I overlooking something? Other than that, this looks great.
Pekka
@Lo'oris: Even though the original answer doesn't accomplish this exactly, this is the only method I know of that allows your credential to be readable only by root. (See my comment above.)
grossvogel
@grossvogel but this makes the data dumpable from every PHP file, doesn't it? I can see the security this method adds on filesystem level, but it feels so awfully easy to circumvent. Am I mistaken?
Pekka
@Pekka: Good point. The way I see it, that credential is by design available to any php script on your site. You can gain some security through obscurity by having it in some unknown constant or variable somewhere, but it's still only a matter of time if somebody can run arbitrary php code in your environment.
grossvogel
If you're worried about print_r(_SERVER) being more insecure than echo config.inc.php, the obvious answer is to encrypt it.
hopeseekr
@grossvogel I see and agree... The situation where this would lead to the greatest gain in security is unfortunately the situation when it can't be done: On shared hosting. I have never seen a hosting provider using a method this advanced.
Pekka
@grossvogel pointless if you think about it. If they hack www-data account, they can use it to create a file that will print that data anyway.
Lo'oris
@Pekka it makes the data dumpable by every php file *under that virtual server*. Still, as I said just before, it is pointless anyway.
Lo'oris
@Lo'oris, ok you talk the talk, now show us your much more secure system ;-) Also, you can do my method via .htaccess if you're on a shared host. It's just not as secure, as anyone on your host can access .htaccess, probably.
hopeseekr
If any one wants me to develop something that would cuase a hacker serious pain, all you have to do is pay me ;-) I'm not about to release it verbatim to SO for free.
hopeseekr
@hopeseekr what are you talking about? I'm saying that this method is as secure and more complicated than just using a `config.php`, I didn't say there is a more secure method. And your suggestion about using `.htaccess` is ridiculous considering that, so I guess you are a bluffing copypaste monkey that have no idea what it is talking about.
Lo'oris
@Lo-oris: www-data should not have write-access to the web root, so that particular example isn't quite enough. Still, I'm fully ready to admit that this method is hardly bulletproof in the face of a real compromise... nothing is. This has been a good discussion.
grossvogel
@grossvogel you're right: www-data is not supposed to have write access. But this still applies to *his user* anyway, in case there is some other way get access to it in that system
Lo'oris
My method is far more secure than a config file.
hopeseekr
Caveat: any phpinfo() scripts left laying around expose Apache ENV vars.
mrclay
@mrclay that's why you disable phpinfo() via php.ini ;-)
hopeseekr
@hopeseekr you should add that to your answer
mrclay
A: 

I can believe noone has mentioned MYSQLI and prepared statements yet, you may lock your password and database connection away, but thats ultimately futile if I can simply type ';DROP TABLE users;-- in the login form.

Check http://en.wikipedia.org/wiki/SQL_injection for an idea about what I'm talking about.

Kristoffer S Hansen
Thanks for this. I need to do more reading about sql injection.
tim