3

I have PHP project and I need to store MySQL access information.

I have a config.php file outside public directory and in the file I have:

class Config
{
    const host = "dbserver";
    const name = "dbname";
    const user = "dbuser";
    const pass = "dbpass";
}

Then in init.php (also outside public directory) I have helper functions and other stuff:

include "config.php";
$db = MySQLWrapper(Config::host, Config::name, Config::user, Config::pass);
//... init sessions, spl_autoloads, class maps and other stuff

Now in public www directory, I have index.php:

require_once "full path to init.php"
create page

Is this a good, safe design? Or is there any problem with class const's?

I dont want to use directly variables or array, because if someone accidentally allow error logs on server, passwords in variables could leak in error log via variables debug print.

9
  • 1
    Function parameters are also shown in the stack trace... Commented Dec 14, 2018 at 9:32
  • Yes, because they become local variables. But that would require error in the called function, which is essentially just PDO init. So there is a chance, but a smal one. Commented Dec 14, 2018 at 9:42
  • Well, I don't really get what scenario you have in mind then. Can you please elaborate on the possible scenaro? In which case the passwords in variables could leak in error log via variables debug print. With a sketch of code preferably. Commented Dec 14, 2018 at 9:53
  • Related on SO: stackoverflow.com/questions/97984/…
    – Anders
    Commented Dec 14, 2018 at 9:55
  • @Anders I have seen that, but there is nothing about class const for storing pass Commented Dec 14, 2018 at 9:55

2 Answers 2

0

For me, the form in which credentials are stored is not that important as the way they are called.

Having them listed right in the function/method parameters will make them appear in the regular PHP's stack trace:

$db = MySQLWrapper(Config::host, Config::name, Config::user, Config::pass);

function MySQLWrapper($host, $name, $user, $password){
    new PDO("nonexistent", $user, $password);
}

will reveal credentials in the output

Fatal error: Uncaught PDOException: invalid data source name in /in/iLFHa:13 
Stack trace: 
#0 /in/GaEGR(13): PDO->__construct('nonexistent', 'dbuser', 'dbpass')
#1 /in/GaEGR(10): MySQLWrapper('dbserver', 'dbname', 'dbuser', 'dbpass')

So in order to avoid that I usually suggest two things:

  • to avoid variables to be shown from PDO constructor, catch the exception and re-throw it, so it would contain only the message but not the stack trace
  • to avoid variables to be shown from function/method parameters, send them as compound variable - an object or an array.

So, regardless of the variables source I would suggest to send them as an array, not separate variables (it's a bad practice in general, here it's a tradeoff with security) and catch and re-throw the PDO connection error:

$db = MySQLWrapper([
    'host' => Config::host,
    'name' => Config::name,
    'user' => Config::user,
    'pass' => Config::pass,
]);

function MySQLWrapper($config) {
    try {
        new PDO("nonexistent", $config['user'], $config['pass']);
    } catch (\PDOException $e) {
        throw new \PDOException($e->getMessage(), (int)$e->getCode());
    }    
}

Now it's just the error message and a clue where it happened:

Fatal error: Uncaught PDOException: invalid data source name in /in/c9kpM:16 
Stack trace: 
#0 /in/c9kpM(10): MySQLWrapper(Array) 
#1 {main} thrown in /in/c9kpM on line 16
4

Step one is to never store the password in the webroot. You allready got that covered. Good!

Step two is to not store the password in PHP code. Your code base should be free of secrets, be it in class constants or anything else. That let's you commit it to version control, make backups, share it, etc., without second thought.

Keeping the secrets out of the source code is not just good for security, but also good software development practice. Your source should not be dependent on the environment the application is running it.

So how do you solve this? Consider using an environment variable, a configuration file or php_value in httpd.conf. For all these cases you'll have to think about what processes has access to the value and how you restrict that.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .