i am trying to figure out if there is a way to make a password recovery system that actually hides the "connection.php" with all the mysqli db username and password. is this possible?
most of the tutorials i found have the "connection.php" file shown to make the connection to the database and it can be viewed from source which makes the the database login info visible. can someone help me with this or point me in the right direction to go about this please?
example:
<?php
$connection = mysqli_connect('localhost', 'root', 'Rvm#i[9)0?~=');
if (!$connection){
die("Database Connection Failed" . mysqli_error($connection));
}
$select_db = mysqli_select_db($connection, 'pixelw3p_demo');
if (!$select_db){
die("Database Selection Failed" . mysqli_error($connection));
}
?>
this is in the connection.php file which needs to be added as a
require_once('connection.php');
now this php file can be seen in the source then you know which php file to look for to get the database info. any way all of this can be hidden so my db isn't vulnerable?
To put it straight: there is absolutely nothing wrong in having credentials in a PHP file. What everyone is talking about is "NEVER store passwords, API keys, or other sensitive information" in a file included in the version control (e.g. git).
A PHP file by itself is no worse than ENV, INI, JSON, XML, YAML or whatever. Actually a PHP file is even slightly better, as it doesn't need to be put strictly above the document root. And also, using PHP for the configuration allows a better integration with your application.
Whereas what is really essential, is having all the application settings in a separate file with which is removed from the version control, so it will never make it into a repository or another server.
Given all the above, to make your configuration file separated from the source code:
add the config.php line in .gitignore (in case you are using git)
create a file called config.sample.php with all variables set to empty values like this
return [
'db' => [
'host' => '127.0.0.1',
'username' => '',
'password' => '',
'dbname' => '',
'port' => 3306,
],
];
add it to the version control
in your application bootstrap file have a code like this
if (!file_exists('config.php'))
{
throw new \Exception('Create config.php based on config.sample.php');
}
$config = require 'config.php';
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli(...$config['db']);
$mysqli->set_charset('utf8mb4');
then, as suggested, create config.php on the every server your application runs, each with its own set of values
What you have to understand, this routine is obligatory for any file format, config.ini icluded. And it's this routine that makes your passwords secure and portable, not a file format you choose.
To be blunt, most of the tutorials you've found are probably absolute garbage and everything they're telling you is wrong. Few of them actually address serious security concerns, and those that do usually either gloss over it, or fail to address the issues by promoting best practices.
It's not hard, but it can be tricky to do right. You need to keep in mind a bunch of things.
NEVER store passwords, API keys, or other sensitive information in your source code. Use configuration files, especially simple ones in INI, JSON or even XML format. PHP has functions for reading all of these quickly and easily.
NEVER store configuration files in a place that's within your public "web root", that is a place that could be accessed by someone tinkering with the URL to probe for files like these. Even if you have rules in your web server configuration to block these requests those rules might be disabled by accident, a problem that often manifests when you redeploy your application to a new server that isn't configured correctly.
NEVER check your production configuration files into version control. This is how you leak API keys and passwords to would be attackers. For instance, accidentally pushing an Amazon AWS key to a public GitHub repository is often swiftly punished by someone who will use that key to spin up hundreds of expensive instances. It doesn't matter if repositories are private: These can be cloned by people and made public without your knowledge.
ALWAYS do what you can to minimize the number of places where critical passwords, API keys and other credentials are stored. Use a secure storage system like 1Password as a "vault" where the contents are properly and thoroughly encrypted, not something like a Google Doc which could be compromised.
ALWAYS burn all passwords, API keys, and other credentials stored on a server in the event of a compromise. If you don't know how much access had or how long they've had access, re-issue new passwords, generate new API keys, and be absolutely certain the old credentials no longer work. Do not assume you have time to fix this. You might not. Immediately and permanently fix the problem when you realize you've got an issue.
The simplest answer here is to make a config.ini file with this information in it that's saved outside the web root and kept only on the server. Don't download it. Don't copy it. Don't touch it unless you need to. This helps avoid costly, painful mistakes.
A .htaccess file is usually impossible to display in browsers, but mind that depends on webserver settings. It's the default in Apache, and also in NGINX (where a .htaccess file has no functionality), but be very aware other webservers could have other defaults, and may display the contents of a .htaccess.
Contrary: a php.ini file is usually not configured to be rejected at HTTP requests!
Also if PHP processing fails, you end up with credentials in plaintext.
Anyway, I consider the .htaccess method as reliable as using htpasswd for authentication or limiting access.
In Apache's .htaccess this works:
php_value mysqli.default_host localhost
php_value mysqli.default_user obelix
php_value mysqli.default_pw zKSIOSwjsiyw9263djcaleP982WLdDU3kzn6
php_value mysqli.default_db broccoli
Then in PHP it's as easy as:
$db = mysqli_connect();
$db->select_db('menhirdb');
It's anyway better than storing credentials in sourcecode.
If you think your webserver performance sucks because a .htaccess is read line by line at each HTTP query, than you better put it in httpd.conf
That's anyway the way I would do it, but then like:
php_admin_value mysqli.default_host localhost
php_admin_value mysqli.default_user obelix
php_admin_value mysqli.default_pw zKSIOSwjsiyw9263djcaleP982WLdDU3kzn6
php_admin_value mysqli.default_db broccoli
The benefit of using 'php_admin_value' is automatically that .htaccess values can't overwrite them. Which is a great security benefit, I think. As I've witnessed more than once that vulnerable CMS systems wrote hostile .htaccess files.
Related
I'm just writing a PHP file to connect to my SQL server for a website login system and I'm terrified I'm just going to leave massive security holes.
I have my connect.php file in a directory of the websites root directory with this in it:
$db = new mysqli('localhost', 'publicguest', '**********', 'website');
where the password is open to see. I know when someone is looking at the website they cannot see the PHP code through the source but is this insecure and what is the common way to avoid this?
If your server has configuration issues, specifically php scripts aren't executed then someone may be able to get that info.
To avoid that you can put the file above the document root directory.
Unless they have direct access to the files you're working with, it should be fine.
Most commonly, people will store passwords and settings in a configuration file above root level which they then parse and use in those statements. It will then be up to the attacker to reach that file.
If you really want to be obscure about it, you could encrypt those settings as well.
Unless an attacker has FTP/direct access to the files, this is not a security risk as the PHP file is processed before outputting it to the client.
If the attacker has FTP/direct access, the mysql auth info is the least of the problems!
Wordpress stores the mysql login info in clear text in the wp-config.php, joomla does the same, there is no other way to do it i think.
For a good practice you shouldn't use your password in the source code of your application, but rather store it in a db_config.php file outside your web root, making sure your config file is not publicly accessible.
This should get you deeper into the argument:
http://www.mediawiki.org/wiki/Manual:Securing_database_passwords
For the most part its safe, unless:
For some reason your web server spits out your code in plaintext, this can happen in rare cases with server misconfiguration.
You can store your connection data outside of the web root to stop general access, but in the event a hacker has been allowed to execute PHP on your server for any reason, its game over anyways.
The only thing I would change about that line of code is getting the username and password out of that particular line, eg:
$host = 'localhost';
$user = 'publicguest';
$pass = 'hunter2';
$database = 'website';
$db = new mysqli($host, $user, $pass, $database);
The reason for this is if, at some point, your code encounters and error and spits out a stack trace it will not accidentally spit out your connection information as well.
If you really wants to be paranoid you can call:
unset($user);
unset($pass);
After the connection goes through, but that really only protects you from code injection, and so long as you never ever use eval() you should be fine. [seriously, never. >:I]
Anything further that people in this thread are suggesting is just paranoid faffing about because once someone has file-level access to your code they have the keys to your kingdom anyways and it's game over. But take heart! 99 times of 100 no one cares about your code or your database, they just want to inject their own code to send spam and/or DOS other people. :P
We have a Java IRC application where users are allowed to execute arbitrary PHP and get the result. Here is one example of what this is used for:
btc: <php>$btc = json_decode(file_get_contents('https://btc-e.com/api/2/1/ticker'), true); $ticker = $btc['ticker']; echo "Current BTC Ticker: High: $".$ticker['high']." Low: $".$ticker['low']." Average: $" . $ticker['avg'];
We also have a python setup, but we like PHP because PHP does not require newlines in the code anywhere. (Because this is IRC, we cannot give it newlines unless we exec a web-loaded .py file)
The issue is how to prevent people from trying to exploit the system, such as in:
<php>echo readfile("/etc/passwd");
Which would, clearly, read out the passwd file for all to see.
We are also having this problem, after we tried to block readfile():
<php>$rf = readfile; echo $rf("/etc/passwd");
How should we go about securing this system? (The full code is on github, for any interested: https://github.com/clone1018/Shocky)
As an aside, no real sensitive information is being exposed, as the whole thing is in a VM, so it isn't a "timebomb" or anything. We still want to lock it down though.
That sounds like plugging one hole in a colander. Filesystem security should be handled by the OS, not the application. And as far as /etc/passwd goes, the OS is already securing it.
Here's the first line of my /etc/passwd - yes, I'm going to post it publicly:
root:x:0:0:root:/root:/bin/bash
Usually, passwords aren't actually stored in /etc/passwd. User information is, but the passwords are replaced with x, with the real password only available to the root user.
However, you should lock down PHP to some degree. You can change many PHP options during runtime with ini_set, including open_basedir. http://www.php.net/manual/en/ini.core.php#ini.open-basedir
If you only want to restrict the file reading maybe this can help
http://www.php.net/manual/en/ini.core.php#ini.open-basedir
If you are using an old version of php < 5.4 you can consider using php safe mode
http://php.net/manual/en/ini.sect.safe-mode.php
Set the following vars for safe mode to restrict php
safe_mode_exec_dir
disable_functions = readfile,system
and many other
Also the user wont be able to read any file for which uid is different, e.g. /etc/password.
Be advised that safe mode is depreciated/ removed from latest versions of php
I have a php script that logs into my servers via the ftp function, and backs up the entire thing easily and quickly, but I can't seem to find a way to let the script determine the folder where the main index file is located.
For example, I have 6 servers with a slew of ftp accounts all set up differently. Some log into the FTP root that has httpdocs/httpsdocs/public_html/error_docs/sub_domains and folders like that, and some log in directly to the httpdocs where the index file is. I only want to backup the main working web files and not all the other stuff that may be in there
I've set up a way to define the working directory, but that means I have to have different scripts for each server or backup I want to do.
Is it possible to have the php script find or work out the main web directory?
One option would be to set up a database that has either the directory to use or nothing if the ftp logs in directly to that directory, but I'm going for automation here.
If it's not possible I'll go with the database option though.
You cannot figure out through FTP alone what the root directory configured in apache is - unless you fetch httpd.conf and parse it, which I'm fairly sure you don't want to do. Presumably you are looping to do this backup from multiple servers with the same script?
If so, just define everything in an array, and loop it with a foreach and all the relevant data will be available in each iteration.
So I would do something like this:
// This will hold all our configuration
$serverData = array();
// First server
$serverData['server1']['ftp_address'] = 'ftp://11.22.33.44/';
$serverData['server1']['ftp_username'] = 'admin';
$serverData['server1']['ftp_password'] = 'password';
$serverData['server1']['root_dir'] = 'myuser/public_html';
// Second server
$serverData['server2']['ftp_address'] = 'ftp://11.22.22.11/';
$serverData['server2']['ftp_username'] = 'root';
$serverData['server2']['ftp_password'] = 'hackmeplease';
$serverData['server2']['root_dir'] = 'myuser/public_html';
// ...and so on
// Of course, you could also query a database to populate the $serverData array
foreach ($serverData as $server) {
// Process each server - all the data is available in $server['ftp_address'], $server['root_dir'] etc etc
}
No, you can't do it reliably without knowledge of how Apache is setup for each of those domains. You'd be better off with the database/config file route. One-time setup cost for that plus a teensy bit of maintenance as sites are added/modded/removed.
You'll probably spend days getting a detector script going, and it'll fail the next time some unknown configuration comes up. Attemping to create an AI is hard... you have to get it to the Artificial Stupidity level first (e.g. the MS Paperclip).
I came across a similar question once on SO but didn't mark it and can't find it now.
Currently my init.php file looks like this:
$db_username = user;
$db_password = pass;
//$db_username = user213124; // webhost
//$db_password = pass214142; // webhost
and I alternately comment/uncomment those lines depending on if its running on my test machine's XAMPP installation or on my webhost.
Sometimes I forget, and upload the wrong one, which is always good for a laugh.
I'm sure there's a way to write a short function allowing init.php to detect its location and use the appropriate username/pass combo.
The first solution that popped into my head was a simple if(file_exists()) {} and checking for something that would ONLY be on my test machine. I'm guessing there's a better way that doesn't prompt disk access though, amirite?
Thank you.
PS - please edit my subject to make it more accurate. Tried my best. Kinda hard to describe...
There are several ways of accomplishing this, some may be better than others, I think it all depends on your situation.
One way is to check for something in $_SERVER. For example, you might user the server name:
if ($_SERVER['SERVER_NAME'] == 'my.dev.server') {
$user = 'dev_user';
$pass = 'dev_pass';
} else {
$user = 'other_user';
$user = 'other_pass';
}
You might also consider having a local configuration file, unique to whatever environment you're on. This could be an ini file or php file that just defines the above variables, and is included, but isn't under version control and doesn't get changed very often.
Sometimes people will also define environment variables. There are probably other ways as well.
I use the ServerAdmin directive of apache to identify my local development machine... Just look how you can set the ServerAdmin of your XAMP server and check
$_SERVER['SERVER_ADMIN']
I was wondering (and used Google with no clear result) if there is any way to connect to a MySQL database with PHP using a hashed password. Say I have the following:
Password (plain): 'foobar'
Password (sha1): '8843d7f92416211de9ebb963ff4ce28125932878'
Now I would like to connect to MySQL like this (using the mysql_* function as example, I'm using PDO though):
$db_link = mysql_connect ( 'localhost', 'user', '8843d7f92416211de9ebb963ff4ce28125932878' );
I this possible? Have anyone done this before?
Then the "hash" would be the password. What would be the benefit?
The short answer is no.
But, just wondering... what is your real concern? Someone hacking into your server and discovering your password?
the usage case would be having multiple developers editing the .php file that contains the sql connect password that you might not want them to know.
I think one solution would be to move the connect statement out to a file like so, make sure you don't have a $password variable though cause someone could just call it and print it out later in their .php file
mysql.php
<?php
mysql_connect('db.cs.dal.ca','user','password');
#mysql_select_db($database) or die( "Database Error ".mysql_error());
?>
and only give your self rw------- permissions to the mysql.php file, then in all of your group accessible .php files you can just include that file to evoke a connection.
index.php
<?php include("mysql.php") ?>
<!-- some web content -->
<?php mysql_close(); ?>
and give your developers group rw-rw---- permissions on all the other .php files, as long as the owner of the mysql.php file can read it should executed on the php server..... i think.
you can also exclude mysql.php from git for example, and have developers run their own local copy of a DB with their own mysql.php file and just provide a stripped down copy of your production database for local development and testing
Simple answer is "You can't."
I know what you are trying to accomplish: You are probably on some shared hosting plan and cannot put your config file above the html folder.
Stefan is thinking that a hacker would just be hunting for the config file and wants to make him have to work for the info. Once the hacker realizes he needs more info, he has to crack the site a second time.
This has nothing to do with a table of usernames & passwords. This is for the MySQL config file.