Is it unsafe to switch environments based on domain? - php

I am curious if doing something like setting your "environment" to Production, Dev, Staging, etc. based on a domain name such as dev.domain.com, staging.domain.com is a bad idea.
Can somebody just edit their hosts file to point dev.domain.com to domain.com so now the system thinks it's in Dev when it really is in Prod? This would mean any Dev specific code will be ran by a complete stranger.
Is this possible or is there a better way to determine your environment such as setting it manually in a server variable?
For reference, I am using PHP.

I would set the environment in a server variable on the machine. This allows you to control it during deployment and it cannot be mucked around with by people who are not authorized to do so. Although if you are worried about developers inadvertently connecting to production that is a whole other issue. You should be controlling access to production credentials via some other process such as jndi (in the java world) or environment keys replaced at runtime or deploy time (works in any language).

Setting your "environment" to Production, Dev, Staging, etc. based on a domain name is absolutely safe. This is, because you have total control about what your domain name is.
BEWARE: do not trust what others make you believe what your domain name is. For example, $_SERVER['HTTP_HOST'] is not your domain name. It is the value of the HTTP Host header, that the client sent you, and is therefore free to manipulate.

This is depends on how do you use your domain? Suppose that there are domain.com but there are several sub-domain, sub1.domain.com, sub2.domain.com, etc and every sub domain is managed by different user and/or application!

Related

Make apache send a false SERVER_NAME to PHP

Does anyone know if there's a way to send PHP a different $_SERVER['SERVER_NAME'] value to the one that's actually being used to call Apache? I.E: if the user types dev.mydomain.com in the URL bar of the browser, it arrives at the correct IP address, but tells PHP that the server name is live.mydomain.com? I've Googled around for this, but not found anything.
"Why do I want to do this?" I hear you ask
I've inherited a large PHP system that makes a lot of decisions based on the domain name being used to call the system. The domain name is sometimes hardcoded, and sometimes stored in the database.
I now need to make a development environment separate from the live environment. I could search and replace all those domain names, but I then have different code for the two environments, and problems with the code versioning.
Please note
I don't need the user to hack or fake anything, so there's no security issues. I want, as the site administrator, Apache and PHP to use different domain names.
The following 'solutions' are not what I'm asking
ServerAlias : No. Apache still sends the wrong domain name to the code.
Redirecting : Is only going to send the request to the wrong server.
Hacking the client's host file : Sure I can do that on my own machine, but a number of 'technically naive' people without administrator rights on their machines also need to test the development site. And they would need to remember to change it back when done tesing. It would become unworkable.
Any ideas please?
After another 3 hours searching on the internet, I eventually found an answer. I'll leave it here for the next person searching how to do this.
First things first. ModRewrite was not the answer! By the time Apache is processing its ModRewrite and SetEnv settings, the SERVER_NAME and 'HTTP_HOST' variables are cast in stone. You can try resetting them, but your PHP won't ever see the changed values.
What does work is PHP's auto_prepend option. How you set this depends on your PHP setup, but the flag is as follows:
auto_prepend_file=prepend.php
Then create the prepend.php file in your document root:
<?php
if($_SERVER['HTTP_HOST'] == 'dev.mydomain.com'){
$_SERVER['HTTP_HOST']= 'live.mydomain.com';
$_SERVER['SERVER_NAME']= 'live.mydomain.com';
}
?>
It even works in Symfony. All you have to do is ensure the prepend.php file stays out of your master repository.
And then, literally 30 seconds after posting the question, I thought to myself: "Hang on... You haven't tried ModRewrite yet. I'll leave the question here for now. I could get other useful feedback!

Better way to check if script is running on dev server or prod server

For several years, I have been using the approach usually recommended to check whether a page was invoked locally or remotely by inspecting whether $_SERVER['SERVER_ADDR'] equals 127.0.0.1 or is empty. This has been discussed in other questions, such as this and this. Other superglobals such as $_SERVER['REMOTE_ADDR'] are also often mentioned.
Over time, I have found that this approach sometimes seems to fail.
What I really want to know is whether the script has been invoked on my dev server (xampp, wamp, IDE debugger...) or on a production server. This is so that paths to scripts above the web root can be properly set. While this works 99.999% of the time, it seems that sometimes, when Apache redirects to a 404 page, the $_SERVER['SERVER_ADDR'] must be lost, and a script running on a production server passes the "local" test.
As a result, I am looking for other approaches. Of course I may be doing something wrong in Apache, but regardless, it would be good to have a foolproof test in php.
A couple ideas came to me, and I wonder if these are safe, or whether someone has a better idea.
A. One idea is to look at the current path: something like
define ( 'DEV_SERVER',
(substr(
strtolower($_SERVER['DOCUMENT_ROOT']),
0,8)
=="c:/xampp")
);
B. Another idea would be to check for the existence of a local file with a particular name, but hitting the file system seems like too much work.
Thanks in advance for all insights!
You could also try gethostname().
Although, the best method is probably to only deploy dev specific stuff to dev servers. I.e. keep those scripts separate to your production / regression testing scripts. You don't want these DEV server specific stuff to accidentally become visible to users.

php secure way to detect localhost from server

There are a lot of ways for detecting if you are running PHP code on localhost or server. However they use $_SERVER and http header which can be fake by user.
It is serious for me because I have made a developer php shell interactive on my website which should go to 404 if it is not on the localhost.
The most straightforward answer is $_SERVER["REMOTE_ADDR"]. It's generally considered reasonably safe.
However, if you provide access to command line commands through your script, it may not be enough. It may be possible to send a request to your script from the outside through IP spoofing. That may be enough to trigger a destructive command even though IP spoofing usually means that the attacker will not receive a response. (This is a very esoteric scenario and I know little more about it than that it may be possible.)
What you could do:
Instead of checking the IP from within PHP, make sure the page can not be accessed from the outside using tougher means, for example by setting up a hardware or software firewall that prevents any access from outside, or configuring your web server to listen only to local requests.
Instead of checking the IP from within PHP, protect the page by using some sort of password authentication.
Talk to a security expert (maybe on http://security.stackexchange.com), explain your network setup and ask for opinions whether IP spoofing is a possibility in your specific scenario.
Make your script available through CLI, the server's local command line, instead of the web server. Place your script outside the web server's root. (This option will probably defeat your specific purpose of having an interactive shell, though)
Or you can of course trust that no one will ever find out. If this is for a low-risk, private project, thinking about IP spoofing is probably overthinking it massively.
I believe you are looking for $_SERVER['REMOTE_ADDR'].
Check it with localhost or 127.0.0.01 or a LAN IP of your choice.
Pekka 웃 with his answer goes into further details on how this may be spoofed.
$serverList = array('localhost', '127.0.0.1');
if(!in_array($_SERVER['HTTP_HOST'], $serverList)) {
}
you can't fake this one

Securing DB password in php

Am new to web development. I am curious as to how people do it.
I am writing some php code that uses a mysql DB. I have the password hardcoded in the code as of now. This code can be checked out by all devs and so every one has access to the password. Seems very very wrong to me. On top of that I can think of some complications. I am listing the issues in bullet point form -
Password hard coded in code is wrong. I don't want all devs to have access to it as all of them can check out the code.
How to differentiate between production and development servers/credentials? I have the same file containing both prod and dev DB credentials. What is the best way to handle this?
I want to prevent against lazy/drunk times so that devs do not delete/drop tables etc. I can obviously have different access to different devs. So is that the solution to all of this?
Potential solution: Do not have the password in code. Ask devs to add the password themselves and make sure its never checked in.
Problem with solution: Tedious process of deployment. Have to add the password for production/QA deployment manually and make sure its able to connect to the DB everytime before deployment. Sounds too painful and error prone. What do people usually do?
Also on the same note (kind of linked to the above question)
If you have 4 devs in the team how do you set up the dev environment? Do all of them use the same DB? If not how do you create the tables and populate the tables with test data? Do you have to write code to populate the test data?
Thanks a lot for any input.
Put the password in a separate PHP file, containing all your app settings, and include it at the top of the page. This file can then be kept out of Version Control, and replaced for each deployment.
Make sure that you keep the config.php file (or whatever you choose to name it) out of your root directory, also, so that it can't be accidentally served up to any users of your app. Also, as a further precaution, make sure that you give it the .php extension, so that if it somehow does still get served up, it should be parsed by PHP first, and any useful information (hopefully) removed - a common practice would be to name it with a .conf.php or .inc.php extension for this reason.
As for the Dev Environment, we use a single database shared by all the devs. It was originally created from live client data, cloned into our database, with certain information redacted / replaced for privacy reasons. The same database is used in our development build as well as our localhost builds.
In that situation you describe, you could write a deployment script that "fills" the password in the correct spot in the source code automatically. Then your production passwords only reside in your production environment deployment scripts. You can have developers manually add it to their own local environments.
Also, you could have a configuration file with all this settings and have your app load them from it, or a even a separate php file as someone else suggested. Either configuration/php file should not be in source control and each developer can do its own, and you can have the correct one in production.
This is often solved by having both a development and production version of a config file. The production version contains connection information for the development database ( servername, database name, username, password). This file can be viewed edited by all developers.
The production version contains connection information for the production server, and is unreadable by untrusted developers. When code is deployed to the production site, do not deploy the development version of the configuration file. The production server's version will then stay intact.
You can consider removing the configuration file from version control altogether. Using this scheme, each developer will maintain his own version or can access a development version from a standard location.

secure php host name information - $_SERVER['HTTP_HOST'] alternative

I have a public facing debug script that I would only like to run on certain dev boxes, I was hoping to do this programatically inside this script, by detecting the server ip or name-
So I have a question about the security of $_SERVER and $_SERVER['HTTP_HOST'] in particular.
From this: http://shiflett.org/blog/2006/mar/server-name-versus-http-host blog post I have gathered that this var is pretty insecure, and can't be trusted.
What is the best way to find out from php what box you are currently on?
I thought of using FILE , since that seems to be pretty secure, but I'm not sure I have enough info just from the file path.
I don't necessarily need the server name, even ip would be fine.
thanks in advance.
The best way? It depends on the level of control you have on your environment. Here are some options:
Set an environmental variable via the webserver to indicate the box.
if (getenv('env_server') == 'production')
This is nice, since there's no files that you need to worry about. Just the webserver configuration.
Set a file in a "known" place on the server, and check that (one file for the entire server).
require('/path/to/environment.php');
That file should define a constant to determine the environment.
Manually configure each application for the server. This is the easiest to do, since it doesn't require anything on the server side, but it's also the least convenient since you need to manually configure each install...
External IP address used to get to the site:
$_SERVER['SERVER_ADDR']
This is nice since it requires no additional configuration on the server side. But it will require you to keep a map of all active IP addresses, and the servers they are bound to (especially since more than 1 IP can point to the same server)...
The best method is to explicitly define the machine by placing an environment config file on it and checking for it:
if (file_exists('environment.php')) {
include 'environment.php';
}
This file could contain just the name of the machine you're on, or configuration settings like $debug = 0 or whatever else you want to customize for specific machines.
What is the best way to find out from php what box you are currently on?
$_SERVER["SERVER_NAME"] will usually be fine. The security problems Chris outlines need very, very specific circumstances to work.
$_SERVER["SERVER_ADDR"] would be an alternative, too.
Other than that, I would tend to go with __FILE__ if there is any chance of getting a hint from the path.
You could use exec() to run a shell command.
echo exec('hostname');
This can get the IP address on OS X, may be platform specific.
echo exec('ifconfig | grep "inet " | grep -v 127.0.0.1 | cut -d\ -f2');

Categories