So I make some basic PHP software and have a config file. The file contains database information only, there are no user passwords etc etc. However, I declare the variables just as normal ($test = "test";), and was wondering if someone could use require/include to get the variables? I think they wouldn't be able to access the variables with file_get_contents(); due to the way PHP works. But I'm not sure about require/include. Obviously you can do it locally, but what about from other sites?
Example to clear things up:
http://example.com/config.php
$db_host
$db_user
$db_pass
$db_base
Now with http://anotherexample.com/somepage.php would they be able to use require/include to fetch the PHP script from example.com and then echo the variables?
Thanks!
If you file is a PHP file, and the configurations are PHP code, and your server is setup to correctly run .php files through the PHP processor...then, only people within the same server could potentially require or include the file. There are some basic PHP base directory configurations, etc., and some "safe mode" features that will prohibit users on shared servers from being able to do this--so long as it's setup correctly.
Other than on a shared server that's not configured to protect your directory from other users on that same server...about the only way the file can get compromised is if Apache stops recognizing the file extension and serves it to the web browser as plain text, etc...which is also a configuration issue.
Related
I have a PHP/MySQL website hosted on GoDaddy. I am trying to remove all security flaws from the site.
To connect to my database, I have a file that is "Connect.php" that I include in all the necessary PHP files. It consists of the following code:
<?php
//Connect To Database
$hostname='xyz.hostedresource.com';
$username='username';
$password='password';
$dbname='dbname';
?>
I understand a common fix to address the use of hard-coded passwords is to store the password in a config file outside of the webroot folder. However, with GoDaddy shared hosting, I do not have access to anything outside of the webroot folder. Does anyone have any suggestions to resolve this CWE in this situation?
With PHP the issue is (or could be) that the interpreter stops interpreting and the files are served as plain text.
In your case, perhaps this is as far as you can go:
Put 'hidden' files in a folder, and prevent access to that folder using .htaccess and other Apache directives. This is actually not that far off having it in a separate folder (since Apache and its configuration are managing the security for you either way).
and:
Remove the ability for the MySQL server to be accessed outside of the local machine/IP address you're using. I'm not sure if you can do this with your hosting provider (or to what extent you can single yourself out)
I've got a file on my site called dbSettings.php with the lines:
<?php
$host = "localhost";
$dbName = "database";
$user = "user";
$pwd = "pass";
$db = new mysqli($host, $user, $pwd, $dbName);
?>
I get this page into my main page with the require_once() function. Is there ANY way for someone who's reaching this page through the server(my domain) to get a hold of the values stored in these variables? Is this a secure way to keep the database settings?
This is a common way to keep database credentials in php applications. Generally a config file would keep those settings some good practices are
Proper file permissions to the file such as
chmod the file 640 instead of 600. Keep file ownership to your user and change group to webserver. This way, the webserver can only read and not modify it
Move file out of webroot so its not accessible directly by others
Only give needed database privileges to that database user
If user just needs to access one database only give privileges for that database and data not give Structure or Administration related privileges if not needed
If possible protect with
.htaccess
<files dbSettings.php>
order allow,deny
deny from all
</files>
If your webserver is configured properly, web clients should not be able to view the settings. When a .php file is accessed through the webserver, it executes the script, and returns what it prints to the client. The source code of the script is not sent to the client.
You can make things more secure by putting files like this outside your webroot. Then clients can't even address them, they can only be accessed by being required from another script.
From what I know of PHP security, there are a couple ways for this information to leak:
If dbSettings.php can be somehow loaded by a client, without the server processing the page. This would obviously give out the details, since they can just look at the file. Generally speaking, if you server is correctly configured, and and you have no backup files created, this shouldn't be an issue.
If dbSettings.php is loaded by the client, you want to make sure no errors could leak the information (so for instance the mysqli creation can't fail and leak the information). Since your app isn't initialized, it is possible for errors you regularly mask to appear.
As for securely storing the information, I don't believe there is a much better solution then to do as Barmar suggests, and put the configuration files somewhere the web server doesn't actually serve files. PHP can still generally access these files, but the web server won't give them out to clients. Depending upon your hosts, this may or may not be possible.
Make sure that your dbSettings.php is not accessible through URL, so php must be able to read this file, but this file should not be accessble by typing it's address in the browser (by guessing, luck, etc). But if you have properly configured www server you should be fine because php will be processed and blank page will be returned to user.
Only if you misconfigure your web server so it will not process php pages but return them to the user - the file will accessible by others to download. So again your settings must not be accessible from outside.
Besides that You should never have echo, dump, etc those values from your php code on production server and you should also catch any errors from mysql driver so they will not be printed out to the user on production server.
The most important security measure, as outlined by previous answers, is proper webserver configuration.
As you are creating a configuration file that should never be directly accessed, you can safely place it outside the server root, or in a directory for which the server is configured to not serve files. As long as the file has proper permissions, you can include() it without the webserver's help.
If for what ever reason you choose to stick with having the configuration file in an accessible location, you can use a define() trick to prevent unauthorised execution. This is done by defining a constant in the file to include the config file, prior to the actual include(), then checking for the existence of the constant in the config file itself.
example.php:
<?php
define ('my_const', 1);
include ('config.php');
echo $super_secret_data;
?>
config.php:
<?php
if (!defined ('my_const'))
die ();
$super_secret_data = 42;
?>
Of course, the only security benefit here is that executable code will not run without the constant if the page is accessed directly, and that its data will not be accessible by files that do not define the const (which is pretty bad security through obscurity, as you can probably still call getfilecontents() on the file).
I am a PHP newbie and a have a php security question. Is it possible for somebody to get the source code of a php script file running on a server with default configuration? If so, what is the best way to be protected? I am asking this because I happened to download a php file when I requested a page from a site and what triggered my concerns. I think that maybe apache configuration was wrong and served that file to me like a simple file but I am not sure. Also what is the best place to keep "sensitive" data such as database or smtp configuration?
Thank you,
Alex
For the most sensitive information, I'd suggest putting it outside of your web root folder, and including it through "require" or "include". This way, even is some configuration gets botched on the server, the visitor will only get served the line "include('secret_stuff.php');" and not the actual script.
Exactly what David Dorward said but i would advise you take a look at the following patch(s) that would modify apache to not send source code's regards if there is a misconfiguration.
http://mirror.facebook.net/facebook/patches/ap_source_defense.patch
Patch like so:
cd apache-1.3.x
patch -p1 -i ap_source_defense.patch
More Patches from Facebook Development Team: http://mirror.facebook.net/facebook/patches/
The best way to protect your much needed source is to place them outside the public root directory, as if apache is running it will not be able to serve files directly from the folder up public_html
for example:
C:/server/apache/
C:/server/apache/htdocs/
C:/server/apache/htdocs/includes/
People can specifically view the files my going to
http://hostname.tld/includes/
but having the directory structure of:
C:/server/apache/
C:/server/apache/includes/
C:/server/apache/htdocs/
and then within
C:/server/apache/htdocs/index.php
you have
<?php
require_once('../includes/config.php');
?>
this should protect all major files bar the view file (index.php)
If the server is not configured to handle PHP files, then it will treat them like any other unknown file (and serve them as either text/plain or application/octet-stream.
PHP support is, as far as I know, always provided as an extension or external program (for CGI, FastCGI, etc) and never as a built in for an HTTP server.
If the server is properly configured to run PHP code, then people without direct access to the server cannot view the PHP source code. You don't have to do anything else.
It is only because that server was not configured to run PHP, and instead served it as text, that you could see the source.
If you have this line in your apache.httpd.conf file,
AddType application/x-httpd-php .php
Apache should deal with data, rather than showing them...
Also you need to start php services.
What you describe as "default configuration" is a webserver without php installed (or with php disabled). In these cases, it is certainly possible to download the php script.
Make sure php is installed (as it will be on ~100% of production php servers) and/or block access to your configuration file with an .htaccess file like this:
<FilesMatch "^config.php$">
Order allow,deny
Deny from all
</Files>
If you want to be extra-tricky (and work even on servers where .htaccess files are ignored), prefix the configuration file with .ht, like .ht.config.php. Most Apache(and some other webserver) configurations will refuse serving files beginning with .ht. However, in general, the only way you could be sure no webserver serves your file is to move it to a directory outside of the server's document directory. On most hosts you or your php script won't be able to access those though.
Your second problem are misconfigurations. There's not much you can do, albeit there might(?) be options to construct a rewriterule to prevent accidential accessibility.
The best prevention however is to keep all scripts outside of the DOCUMENT_ROOT. Just leave a single index.php there, and include all dependencies from there. This is also the best strategy to avoid leaking of configuration data (also don't use ini files for sensitive data, but always .php scripts).
Another worry are shared hosting servers however. All concurrent users on a server can read out your scripts (if not through PHP then via Perl/bash CGIs). Nothing you can do about that, unless you change to a professional hoster which supports running everthing through suexec and thus allowing individual permissions.
Well, "default configuration" is a vague term, but as long as the web server is configured to parse .php files through PHP, you should be fine from that angle. If your scripts themselves happen to parse other PHP files (for eg. a template system) then you need to make sure there aren't any loopholes in that too, since the PHP scripts have full access to your files on the server.
Assuming these are taken care of, you don't need to keep the "sensitive" data in any special place -- just put them in your .php files, but make sure all your scripts end in .php (for eg. config.inc.php) so that they are always parsed via PHP and not sent as plain text.
I would like to ensure that any scripts that are trying to "include" my database connection file are located under my own domain. I don't want a hacker to include the database connection file to their malicious script and gain access to my database that way. My connection file's name is pretty easy to guess, it's called "connect.php". So without renaming it and taking the security through obscurity route, how can I protect it by making sure all connection requests are made by scripts residing under my own domain name? How can this be checked using PHP?
Generally speaking if someone tries to include a file on your domain, they will see the results of the execution of that file. What do you see when you load the connect.php script in your web browser? Thats what they'll see as well if they try to include a remote file.
That said, its generally a good idea to keep important files inaccessible from the outside of your public web space. So, if your website is /var/www/yoursite/ then keep your connect.php in /some/dev/dir/yoursite and include the files from your pages using require_once '/some/dev/dir/yoursite/connect.php';
thetaiko's answer addresses the fundamental issues here - but if anyone else has access to run code on the server (i.e. its a shared server) then access to the file will depend on how the server is configured.
There are lots of ways that access might be constrained - e.g. suphp, base_opendir, multiple chrooted servers. The only way to find out what's going on for sure is to casr yourself in the role of the hacker and see if you can access files outside your designated area.
C.
What do you mean by including your connection file? If a script does include "connect.php" then they can see the source code of the file, so whatever security measures you add to that file will be pointless, as it will be like:
if($notFromHostname)
{
echo "DONT LOOK AT THIS";
die();
}
define('DB_PASS',"myPassword");
...
And the "hacker" will clearly be able to see your password. You are probably better off using something like iptables to deny hosts that are not from a specific domain.
Are you on a shared server and don't want other users of the same server instance to be able to get at your files? That'd be up to your server provider, then, to provide some sort of chroot or virtual system to keep your things in. For Apache, mod_suid can accomplish this nicely, and each vhost gets its own userid and permissions set.
If you want external users to not be able to get at your files, then unless you've badly munged your code, or the server's badly misconfigured, then all they'll get when they visit http://yourserver.com/connect.php is a blank page
No other user than yourself should have access to your PHP files in any way, as Felix mentioned. However, this is how you'd check in PHP:
if($_SERVER['SERVER_NAME'] != "example.com")
die("I've been kidnapped!");
I have an config.php file where I simply make an huge array that contains all the framework configuration. Also the database source string thing like "mysql:host=localhost;dbname=mydb" (whats that called, btw?) and username + password for DB. I'm afraid this is:
stupid
not good; better solution there
not secure (?)
so how do the PHP experts do that?
If you have a www, httpdocs or public_http folder or something like that, where your php application is situated, then it is good practice to put the config file outside of that folder, and just access it like this:
include "../config.php";
Nobody can gain access to that file without FTP access, and so it's relatively safe compared to having it in the application folder.
If you don't have such a folder, you can create one, and make a .htaccess file in the root, which redirects all requests to that folder. There are many different ways to do that, but that's a different question all together.
I store it in a plain text ini style configuration file, usually above the web root so as not to allow users access to it. In the cases where it is accessible, I usually have a .htaccess file with deny from all so as to prevent all access to it.
Storing it in a PHP file accessible to users should be fine, but it isn't ideal. If the sever handles PHP files correctly, even if people can access the file, they can't access the values as they just get the output (nothing). There are of course issues with this, (see comments).
Using PHP files is the most common method with PHP projects (Both FOSS and commercial) I have used. Most of them didn't both storing them above the web root. With any stable setup, there is on the face of it very little point in storing your configuration file above the web root, although given Murphy's law it is worth doing if you can (That or use .htaccess or the equilivent for your server to deny user access to a directory)
That's how most do it, but you could also try some of these solutions:
Save the configuration file outside the web folder (this requires that the open_basedir configuration in PHP is disabled).
Restrict access to the configuration file by using .htaccess:
<Location /config.php>
Order deny,allow
Deny from all
</Location>
Use .ini files and the parse_ini_file function (this is not really a solution in itself, but could be combined with the others)
Why storing DB username & password in "config.php" is not fine? as long as i know, the data in this file can't be shown publicly.
E.G.
<?php
$DB_User = "amindzx";
$DB_Pass = "Something";
// connect to DB and so on.
?>
unless if the hacker can gain access to your FTP.
Why it's stupid to hold simple config.php file without any securities? Even if programmer finds this file he can do nothing, because, like amindzx said "this file can't be shown publicly." Or I'm wrong?
With sensitive info like database or payment gateway credentials, and when I have control over the server, I like to add lines like the following to my apache virtual host config:
SetEnv DB_USER "myuser"
SetEnv DB_PASS "mypass"
In your PHP, you can access these using $_SERVER['DB_USER']. You can make this config file readable only by root, which you can never do to a file that php accesses at run time. One caveat: Be sure you disable php_info and don't expose these variables with something silly like print_r($_SERVER). (Much of this is paraphrased or stolen from here.)
For non-sensitive configuration, I like to do a class full of constants, which is similar to your setup, but I like the OOP-ness of it.
class Application
{
const CONTACT_EMAIL = "me#mysite.com";
}
usage:
$contactEmail = Application::CONTACT_EMAIL;
I usually store settings in a config.php too, such as database connection settings, file paths etc.