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.
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.
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.
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 have a website where each person has his personal profile. I would like to have static URL like mywebsite/user1, mywebsite/user2, but actually I would remain in the same page and change the content dynamically. A reason is that when I open the site I ask to a database some data, and I don't want to ask it each time I change page.
I don't like url like mywebsite?user=1
Is there a solution?
Thank you
[EDIT better explenation]
I have a dynamic page that shows the user profile of my website. So the URL is something like http://mywebsite.me?user=2
but i would like to have a static link, like
http://mywebsite.me/user2name
Why I want this? Because it's easy to remember and write, and because i can change dynamically the content of the page, without asking each time data to my database (i need some shared info in all the pages. info are the same for all the pages)
Yes there are solutions to your problem!
The first solution is server dependend. I am a little unsure how this works on an IIS server but it's quiet simple in Apache. Apache can take directives from a file called .htaccess. The .htaccess file needs to be in the same folder as your active script to work. It also needs the directive AllowOverride All and the module mod_rewrite loaded in the main server configuration. If you have all this set up you need to edit your .htaccess file to contain the following
RewriteEngine on
RewriteRule ^mywebsite/([^/\.]+)/?$ index.php?user=$1 [L]
This will allow you to access mywebsite/index.php?user=12 with mywebsite/12.
A beginner guide to mod_rewrite.
You could also fake this with only PHP. It will not be as pretty as the previous example but it is doable. Also, take into concideration that you are working with user input so the data is to be concidered tainted. The user needs to access the script via mywebsite/index.php/user/12.
<?php
$request = $_SERVER['REQUEST_URI'];
$request = explode($request, '/'); // $request[0] will contain the name of the .php file
$user[$request[1]] = $request[2];
/* Do stuff with $user['user'] */
?>
These are the quickest way I know to acheive what you want.
First off, please familiarise yourself with the solution I have presented here: http://codeumbra.eu/how-to-make-a-blazing-fast-ajax-call-to-a-zend-framework-application
This does exactly what you propose: eliminates all the unnecessary database queries and executes only the one that's currently needed (in your case: fetch user data). If your application doesn't use Zend Framework, the principle remains the same regardless - you'll just have to open the database connection the way that is required by your application. Or just use PDO or whatever you're comfortable with.
Essentially, the method assumes you make an AJAX call to the site to fetch the data you want. It's easy in jQuery (example provided in the article mentioned above). You can replace the previous user's data with the requested one's using JavaScript as well on success (I hope you're familiar with AJAX; if not, please leave a comment and I will explain in more detail).
[EDIT]
Since you've explained in your edit that what you mean is URI rewriting, I can suggest implemensting a simple URI router. The basics behind how it works are described here: http://mingos.eu/2012/09/the-basics-of-uri-routing. You can make your router as complex or as simple as needed by your application.
The URL does not dictate whether or not you make a database call. Those are two separate issues. You typically set up your server so example.com/username is rewritten internally to example.com/user.php?id=username. You're still running PHP, the URL is just masking it. That's called pretty URLs, realized by URL rewriting.
If you want to avoid calling the database, cache your data. E.g. in the above user.php script, you generate a complete HTML page, then write it into a cache folder somewhere, then next time instead of generating the page again the script just outputs the contents of the already created page. Or you just cache the database data somewhere, but still generate the HTML anew every time.
You could write an actual HTML file to /username, so the web server will serve it directly without even bothering PHP. That's not typically what you want though, since it's hard to update/expire those files and you also typically want some dynamic content on there.
Select all from your database.
Then create file containing the scripts contents(index.php?user='s) for each one. set the file name to user_id/user_name you got from the SELECT statement.
This will create a page for each user in the present folder.
To avoid having to recreate 'static' pages, you could set a new column named say 'indexedyet' and change it to 1 on creating a file. You select only files which have this as 0. You could perform this via cronjob once a day or so.
This leaves you vulenderable to user data changes though, as they won't autmatically update. a tactic to use here is to update the static page on any editing.
Another, probably better (sorry not had enough coffee yet-) ideal would be to create a folder on a users registration. Make the index.php page tailored to them on registration and then anything like www.mysite.com/myuser will show their 'tailored version'. Again update the page on user updates.
I would be happy to provide examples depending on your approach.
I've been told that it is unsecure to make database connections inside a PHP includes. For example If I have a login page and add an "include('process.php')" at the top of the page that has a database connection, is that unsecure?
For example If I have a login page and add an "include('process.php')" at the top of the page that has a database connection, is that unsecure?
No.
Maybe the person who told you this was talking about something else - like including a file using a dynamic value coming from a GET parameter, or using remote http:// includes, or as #AlienWebguy mentions, having the password include inside the web root. But using includes in itself is not insecure.
It's only insecure if you are storing your passwords literally in your PHP files. They should be declared outside of the web root. That being said, the lack of security is not due to the use of the include() function.
In and of itself, no, it is not insecure. How it's implemented inside the include is of course a different story.
That's the way I've always done it. I make sure that the include is in a different directory that has open permisions and that the directory your writing in has locked permisions. Hopefully that makes sense.
This question is way too broad to get a good answer from anyone. Short answer is no, there's nothing inherently insecure about including a file that connects to a database. However, if you write code that isn't written properly, then yes it may be insecure to do this.
Since using "include('process.php')" is exactly the same as pasting 'process.php' into the code of the other file, that should not be, per se, a security issue. The insecurity could be in your code, not in the fact the you use the "include". In fact, it could maybe improve the safety of your code, due the reuse.