I've been reading through different secure ways to connect to databases and wanted to run this idea past you before I tie myself in knots trying it with my actual databases if it has no security benefits or simplification of switching between databases.
I was thinking that it would ensure the db_* variables are killed off after the function is used and the connection has been made to the relevant database:
<?php
function dbconn($db_hostname='localhost',
$db_username='',
$db_password='',
$db_database='database1'
$db_object='connection') {
if($db_username=='' && $db_password=='') {
switch ($db_database) {
case 'database1':
$db_username='user1';
$db_password='pass1';
break;
case 'database2':
$db_username='user2';
$db_password='pass2';
break;
default:
echo "No database defined to connect to";
break;
}
}
else if($db_password=='') {
switch ($db_username) {
case 'root':
$db_password='rootpass';
break;
case 'user':
$db_password='userpass';
break;
default:
echo "No password known for this user";
break;
}
}
$db_object= new mysqli($db_hostname, $db_username, $db_password, $db_database);
if ($db_object->connect_error) die($db_object->connect_error);
}
?>
It's unclear to me what you're trying to do, from the code you've provided. However, I can answer your question: "What is a secure way to connect to a database?"
With PHP working as a CGI-like language, the primary concern with connecting securely, is that your configuration file could be exposed. There are two possible solutions to this:
1. A PHP file as your configuration
This is probably the most common approach, and especially used often in redistributable software. By making your "configuration file" a PHP file that simply sets variables and is included in other pages, the PHP interpreter will parse this file, rather than returning its contents. The location of the file doesn't really matter - as long as it's somewhere where PHP files can be executed. In a typical application, this is anywhere in the document root except for the uploads directory.
An example configuration file (db_config.php):
<?php
$db_host = "localhost";
$db_user = "username";
$db_pass = "password";
$db_database = "database_name";
You would simply require('db_config.php'); in your initialization/header/etc. code.
You should only use the configuration file for configuring the connection, not for making it. This way, it makes it easy to change your connection code later on, without having to modify your configuration file on every server that your application runs on.
2. A serialized configuration file
Alternatively, you could use something like JSON or YAML to create a configuration file. The main advantage is that you can use the same configuration file for any auxiliary scripts or applications that need to connect to the same database, but aren't written in PHP.
However, you should never place this file in your document root. As far as your webserver is concerned, a JSON or YAML file is a 'viewable' file, and it will happily show it to anybody who has the URL.
The correct way to use a JSON/YAML/etc. file as your configuration file, is to make sure that it's placed outside of the document root, so that the webserver cannot possibly serve it up to a user. Trying to give it an 'unguessable' name is not sufficient.
You could also use something like .htaccess, but this is not recommended as it will make changing to other webservers harder, and a webserver misconfiguration could expose your database connection details. Only use this as an absolute last resort.
Other considerations
There are three other main points that I want to address here.
Multiple database credentials
In your original code, it looks like you're trying to add a feature where you can select the database you want to select to. In reality, this is almost never what you want. Every server/installation should only have its own database credentials.
If you follow the suggestions I gave for storing your configuration data, then it will be very easy to have a separate configuration file on each system, without having to ever change it. If you're using Git or another version control system that lets you ignore files, you can safely (and should) make it ignore the configuration file. You'll simply have a different configuration file on each server.
Overall security
Of course, you should make sure that your overall security is in proper working order. If you have a LFI vulnerability or somebody can upload a shell to your server, then no amount of putting files outside a document root is going to protect your database credentials. OWASP is a decent resource on general (web) application security.
PDO or mysqli_?
Judging from your snippet of code, you're using mysqli_. While this can be a valid choice if you use parameterization / prepared queries correctly, I would not recommend using it. PDO is a database-independent SQL library that focuses more heavily on parameterized queries. It's included by default in more or less every recent PHP installation, and as a bonus it'll let you switch between different SQL servers.
Using parameterized ("prepared") statements is absolutely critical - it is the only reliable way to prevent SQL injections, which seems to be the most important issue you'll want to protect yourself against here. A goood introductory guide can be found here.
Related
I currently have a web pages which pull data from an SQL database and display it using php to handle the connection and query.
I am currently using this snippet in my PHP file to connect and pull data:
$conn = odbc_connect(
"DRIVER={SQL Server Native Client 10.0};Server=xxx.xxx.xxx.xxx;Database=databasename", "username", "password");
if (!($conn)) {
echo "<p>Connection to DB via ODBC failed: ";
echo odbc_errormsg ($conn );
echo "</p>\n";
}
Does anyone see vulnerability with this and is there practice I should use?
I would put code such as this into a PHP Class file, and model it after the DAO Pattern (Data Access Object). Then, use the require or require_once directive on the script(s) that need to read/write to the DB.
This cuts down on the repetition and adheres to D.R.Y (Don't repeat yourself), when other scripts/code needs to read/write to the same DB, you'll already have a method in place to do so.
I would recommend against printing the error message to the screen. By all means, log it to a file (or check the error logs to see what happened).
As Adam T suggests, this type of code should definitely be captured in a separate file that is re-usable across your application (perhaps this is already the case - not clear from the details given).
If you look at any CMS system eg. WordPress, Joomla or Drupal, you will see they all store the DB credentials in plain text in a config.php file or similar, that gets read in early in the request processing cycle.
With respect to vulnerabilities though, ultimately, you have to place the login credentials somewhere that the PHP code can access it, so either it has to be stored in clear text in a PHP or text file that gets included or read in, or else obfuscated in some way, though generally this is a waste of time and effort.
Your best bet is to ensure the file containing the login credentials is suitably protected via filesystem permissions to prevent access from unauthorised prying eyes.
Suppose i have a page config.php which contains
<?php
$username = "your_name";
$password = "your_password";
$hostname = "localhost";
//connection to the database
$dbhandle = mysql_connect($hostname, $username, $password)
or die("Unable to connect to MySQL");
echo "Connected to MySQL<br>";
?>
I know i need to include this config.php file where i want to ensure database connection.But is there any way to do this globally so that i don't need to include connection file in every required page ?I am asking so because i have seen lots of script where they are running query in a particular php page without including the database connection file!
My usual approach is to create an autoloader function to pull in classes as I need them and have a class handle the DB connection. However that might be a bit excessive for some projects. Also that config still needs to be included prior to my code that calls for a class and expects something to go and get it.
A lot of open source PHP software will set values like this in a config file which gets included very early on along with any libraries etc.
For Example (LM)NucleusCMS uses the config file to load the global functions and other core classes and that way the only thing a PHP script needs to do is ensure that config.php has been included.
Sometimes code you are looking at is intended to be included at run time by other code and so trusts that these settings are already in place. For example I am currently working on a project that redirects all calls to PHP files to start.php which does what is needed and then calls for the file after that and then finally calls for the template to process the output.
If you really want to do no includes at all then there is one other option but it is not recommended. You could set the php.ini directive auto_prepend_file and have the file included in EVERY script the server runs. As I said, you probably do not want this.
However that said if you would like to have the script handle the including for you and this is important then using the .htaccess and start.php example (actually ./engine/start.php) then this might work for you better than fooling about with ini directives. However the downside is that you need to check that your .htaccess redirects are working properly passing the filename back to the start.php and then make sure that some naughty user is not asking your script to do something bad. Once you have sanitised and sanity checked the input then you can go ahead and require_once($filename)...
My .htaccess looks a bit like this:
RewriteEngine on
RewriteRule ^(.*).php?$ ./path/to/start.php?page=$1 [QSA,L]
However, as I have said unless you have a specific need to do this then it would be safer not to as you are allowing ANY input into the include/require line and have to spend a lot of resources on EVERY page load making sure the request is safe.
To be honest the most common best practice is to have a file called, say common.php, and have all of the includes that the scripts need to get to in there and just
require_once('./path/to/common.php');
at the top of every page. If your project ends up with a lot of classes and/or libraries in it then you might be glad that you did.
The way I normally handle my Database connections is to include my config file in my header.php (which handles the navigation, logo, etc) file and the header file has to be included everywhere to keep uniformity.
So that is one solution that you can try
You should include this code on every page. That's how PHP works.
If you don't want to do it manually and your project is quite big you should probably consider using a framework on your project. Good PHP framework can take care of DB connection and many other common tasks such as request/response processing, validation etc.
There are plenty of PHP frameworks and you can select what will fit you.
I'm trying to connect to my database, but I changed my database's root password in the interest of security. However, in order to connect to the database and use PDO, I apparently have to pass my password in the php, which obviously is not good for security:
$hsdbc = new PDO('mysql:dbname=hs database;host=127.0.0.1;charset=utf8', 'root','passwordgoeshere');
$hsdbc->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$hsdbc->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Am I being stupid and that because it's PHP no-one but the person who views the actual file will be able to see the password, or is there some way to do it without passing the password in the file.
Generally speaking it's not bad practice to have connection strings in files that are not user facing. If you don't want to have your personal password in the php file, then you can create a new mysql user for php.
You can also restrict the user's IP address in MySQL to the server hosting your php scripts. This way if a nefarious person browsing the web somehow was able to see the database password, they would have more difficulty accessing it.
People are not able to just go and read into your files. They should be safe on the place where you host it. They are only able to get into to files if they are able to get into the place when you host your stuff. Which should not be possible if they don't have the info to get there.(which should only be known to you).
This is not just for PDO. but also my mysql and mysqli to do it like this
Going to extend SupSon (SC2 Select fan?)'s answer:
PHP itself is server coded language.
There are only 3 ways (maybe more if someone want to add to it) that code can be shown to an outside user:
By having an unsecure .htaccess file that shows php file as text
file (then you should move servers at that point because normally
this doesn't happen)
Somehow your operating on debug mode and something in your page
triggers this mode and you get a whole bunch of PHP code gets shown
FTP/SSH access to your .php file (then you have more than a PDO
problem in your hands)
So if one of these cases is happening, coding into a .php file your username/password won't be a breach in security.
I have seen websites that expose PHP code, when the Apache type handler for PHP becomes unconfigured by accident. Then the code in .php files is displayed instead of executed. There's also an Apache type handler to display PHP source deliberately, though this is not usually configured.
To avoid this vulnerability, it's a good practice to put your sensitive PHP code outside your htdocs directory. Instead, put in your htdocs directory a minimal PHP script that loads the rest of the code using include() or require().
An alternative is to put your MySQL credentials in a config file instead of PHP code at all. For example, the file format used by /etc/my.cnf and $HOME/.my.cnf is readable by the PHP function parse_ini_file(). It's easy to store your MySQL password outside of your code this way.
For example, read user and password from the [mysql] or [client] sections of /etc/my.cnf:
$ini = parse_ini_file("/etc/my.cnf", true);
if (array_key_exists("mysql", $ini)) {
$connect_opts = array_merge($connect_opts, $ini["mysql"]);
} else if (array_key_exists("client", $ini)) {
$connect_opts = array_merge($connect_opts, $ini["client"]);
}
$pdo = new PDO($dsn, $connect_opts["user"], $connect_opts["password"]);
Yes it seems insecure at first, but once you get the hang of it and know how to manage your files to minimize potential security breaches, you can minimize the risks associated with having passwords stored in plain text in potentially publicly exposed spaces. Yet AFAIK PDO doesn't even let you form a connection without supplying a password. The solutions are a combination of what everyone has said and then some. Here's my quick guide for what I do.
Separate SQL users for separate purposes (minimizes damage from SQL injection or hacked accounts):
There should be a PHP-specific user for each table you need to access. That user will be granted only enough rights to handle as much of that table that he needs to, if it doesn't need to delete then don't grant it delete. If it doesn't need to select then don't grant it select. It seems fussy but very quickly you'll have a copy-paste template to make the users, give them the right(s) they need, and document it. If there's a joined table, you'll want to also grant the user access to that table also, naturally.
-- a single user account for a specific purpose:
CREATE USER 'usermanager'#'localhost' IDENTIFIED BY '5765FDJk545j4kl3';
-- You might not want to give access to all three here:
GRANT SELECT, UPDATE, INSERT ON db.users to 'usermanager'#'localhost';
The purpose of this is so that if you have a bug in your code that lets people SQL inject, they won't be able to cause any harm beyond the scope of what that role can do.
Stupid mistake can reveal PHP code and files if left in-directory, move them out:
Never mind revealing the source code, even just trying to access php files "out of order" can be destructive.
Move as many files to an out-of-scope directory as possible. Then call them like so:
require_once('../lib/sql_connectors.php');
This should escape your html / webdir and you should hopefully be able to store all sorts of fun stuff outside the scope of what a stupid admin mistake could reveal.
You can even have a php file that gets pictures and videos from outside your webdir, that's how streaming sites protect their resources and also conduct php-based authentication to file access. To learn how to do that you'll want to look up assigning your own etag headers to make sure browsers cache your php-retrieved files otherwise you'll have a very busy server, here's a short introduction.
Block wrongful access to PHP that are left in-directory:
All of your in-directory PHP files can be protected by checking that the $_SERVER['REQUEST_URI'] isn't itself. If it is, you can have a function called show404() that loads the 404.php page and dies there or just directly call your 404.php with an include. That way, even if you have hackers trying to brute force your php files they'll never see them because they'll get 404 errors (fools the bots) and they'll see the 404 page (fools the humans).
I avoid using .php in any publicly visible paths, to do that, I make rewrite rules in my .htaccess files that look like this:
RewriteEngine On
RewriteRule ^login$ login.php [L,QSA]
The L makes it stop running other rules.
The QSA preserves the $_GET tags.
The first lines of code for every file (consider prepending) could be:
// they should be connecting via a redirect, not directly:
$fileName = basename(__FILE__);
if ($_SERVER['REQUEST_URI'] === '/' . $fileName) {
error_log('Security Warning: [' . $_SERVER['REMOTE_ADDR'] . '] might be trying to scrape for PHP code. URI: [' . $_SERVER['REQUEST_URI'] . ']');
include('404.php'); // should point to your 404 ErrorDocument
exit();
}
// redirect to actual file
include('../hidden/php/' . $fileName);
In this example, assuming you have the redirect in your .htaccess, a login.php with the code above, and a login.php in your hidden directory, the user would experience the following two scenarios: attempt to connect to '/login' and see the hidden '/login.php' page; attempt to connect to the visible '/login.php' directly and get a 404 error.
Those are the 3 big things, lots of small limited accounts to minimize damage in case of security failure, keep all possible files outside the web directory, and make all in-directory php files produce an error letting only non-php links access them.
I'm working on a PHP project and I'm using a global settings file which I include where I need some global values such as database credentials for connecting to mysql.
For example:
settings.php:
<?php
const DB_ADDRESS = 'localhost';
const DB_USERNAME = 'johndoe';
const DB_PASSWORD = 'mypassword';
const DB_PORT = 7777;
?>
My question, is it safe enough?
For example, is there any way to see variables values while debugging in explorer/chrome?
Is there any alternative safer way?
Thanks.
PHP information is processed on the server before being sent to the browser so it can't be seen inside of a browser under normal circumstances. However, if your webserver is misconfigured the plain text version of your code may be sent to the browser thus rendering it visible to users. That's why important code should always be kept outside of your document root and included into files when needed.
Whilst this offers little protection in the event of a compromised server, should your source code ever become publically viewable, through a bug or other vulnerability (such as this: http://www.php.net/archive/2012.php#id2012-05-06-1) an increasingly common approach is to set various credentials and parameters as server environment variables.
E.g. in apache vhost/.htaccess you can set an environment variable such as the following:
SetEnv DB_ADDRESS localhost
...
And in your PHP code:
$DB_ADDRESS = getenv('DB_ADDRESS');
Of course you could assign this value to a class constant, global constant depending on your use case etc....
This also makes your source code more portable, allowing different configurations to be provided depending on the hosting environment (staging/production etc):
SetEnv APPLICATION_ENV development - .htaccess interacting with Zend Framework?
Your settings are never hard coded and not accessible in the source code. Heroku uses a similar approach to application configuration.
Variables are kept within a server, and aren't sent to the client. Unless your script has any vulnerabilities that allow users to output custom variables, then they'll remain secure to anyone without sourcecode access.
Your back-end code should never appear on the front-end, unless something goes terribly wrong with your setup. If that happens and your back-end source code is "leaked" -- unlikely but possible -- then your password will be visible in plain sight.
You can encrypt the password string with a symmetric encryption scheme, but you will have to store the encryption key somewhere. Then if the encryption key gets leaked, you are back to the starting point. It's still a bit better than having the password in plain text, but nothing will be 100% safe.
That's the standard way (look at phpmyadmin, mediawiki, etc.) : this php file is not accessible and if you don't make any error in your server settings, it's not readable.
Usually you'll add a test to check this settings file is included in one of your php files :
<?php
if ( !defined('IN_KP') ) die("Hacking attempt");
?>
Of course you define 'IN_KP' in your including files :
<?php
define('IN_KP', true);
include("sensitive_file.php");
?>
But the best protection overall is that those sensitive data aren't so sensitive because your mysql account is only accessible by localhost (if not fix it !).
For example, is there any way to see variables values while debugging in explorer/chrome?
If you never send them to the view (i.e. echo, var_dump, print_r, session etc) - then no. The browser will never know about them.
Ok , so many people are asking this question, and there are many approaches on how to make the connection to DB secure,
Now I did some googling , many suggest, putting the connection to DB code in a file outside the html_public , and to call it from there when I need to make a connection.
to be honest, am happy with what I have, though I'm not sure how secure it is,
this is how I connect to the DB:
first, I make sure all inputs are fully escaped and validated...
after , in the same page , i make the connection, for example:
mysql_connect("localhost","Admin","Password") or
die ("DB Connection Error");
mysql_select_db("Users") or die ("DB Error");
and the rest of the code after, I close the mysql connection.
Now , It just don't feel right that the DB user info are written in the page, but how can someone (a "hacker") , get this info?
I mean , all inputs are fully escaped and validated, the users I use have very limited previleges, like select and update... only.
Is this secure?? and if not, can u please suggest a more secure way?
Thank you very much for ur help in advance :)
shady
The reason you should consider putting this file outside the web root is that some hosting providers have temporarily stopped interpreting PHP from time to time (due to configuration faults, often after an update on their part). The code will then get sent in clear text and the password will be out in the wild.
Consider this directory structure, where public_html is the web root:
/include1.php
/public_html/index.php
/public_html/includes/include0.php
Now consider this index.php:
<?php
include('includes/include0.php');
do_db_work_and_serve_page_to_visitor();
?>
If the web server starts serving this file in the open, it won't take long before someone tries to download include0.php. Nobody will be able to download include1.php, however, because it's outside the web root and therefore never handled by the web server.
I've personally not heard of a hosting provider not interpreting PHP, leading to your php source code going public. I just did a quick test on this on a RHEL5-Based server without php installed, and just got back a blank page when trying to access a php document.
mysql_* functions have become deprecated with the latest releases of php, and are now moving towards mysqli, as an overall more efficient and secure solution; I'd recommend taking a look into that; http://php.net/manual/en/book.mysqli.php - there's no deprecation errors or anything of the sort yet in PHP5.4 for using plain mysql_ functions, but if you're looking to keep on top of things, take a look into mysqli.
As for a quick answer to your above question, to be honest, I'd see that method as reasonably secure. Just make sure you've got escape chars etc set up, and I don't think you'll run into any issues.
Edit: Some people have posted that in very rare cases, some providers can leak your php source code in this manner. If this is the case, my first advice would be to switch provider.. but using an include_once to load your db info from another php file/lib would be a quick workaround for this. But again, if your provider's setup does allow for leaks such as these, I would be more concerned about their security than yours.
You can have php grab your DB password from a text file stored outside of the public webspace (using fopen), but I personally don't see any real reason for doing this.
Best of luck!
Eoghan
The best pratice is to use PHP PDO instead of the old mysql API.
Take a look: http://php.net/manual/en/ref.pdo-mysql.connection.php
Also, here's an interesting article: http://net.tutsplus.com/tutorials/php/why-you-should-be-using-phps-pdo-for-database-access/