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');
Related
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!
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.
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!
I am in the middle of creating a game server control panel and i have a few issues.
The control panel needs to basically issue commands to a remote Linux server, starting and stopping processes, i have the commands written for this, however the problem is.
I am not sure whether to just SSH in using a PHP library and then issue the commands OR have remote files on the server to deal with this. Which would be most efficient?
Is it even safe running SSH commands from PHP, using the root account? Even if commands that will be sent are hard coded.
If the remote Linux servers would need remote files, what language would this be written in and what functions are best?
If you have any other ideas of the best way around this, please share, i will be very grateful.
Thanks!
that is possible but only done in special occasions. Usually the simpler way is to use some form of reqeust protocol, like for example http and thus evoke predefined routines (scripts) on the servers side. What protocols does the server speak?
NEVER DO THAT ! Usually that would mean to grant root access inside ssh which is unsafe. you could also use something like sudo or suid bits, unsafe again. And you would even top that by send the commands, since that would mean your setup would ahve to acceppt any command it is given and execute it under root rights. Not a good idea...
Use any language that is available on the server and that you feel comfortable with. Does it really matter what language you use to express what you want to say? No, the content matters. Maybe the coice also depends on what type of access you chose. Some languages offer themselves more easily in certain situations.
In short: without more detailed informations only a vague answer is possible.
imagine that I have two services with the same domain but different hostnames and on different physical computers (for example maps.google.com and mail.google.com). I want to include some php code from one server to the other... how can I do this? (I see a lot of things about how to include across different domains on the same server but this isn't what I want.)
EDIT: I control both of the services that I want to include between but they are on different physical servers under the same domain. It has been suggested that I use a repository and then have each server clone that, so my question is now will I be able to automatically have every server update to the most recent version when changes are made to that repository? I am trying to make a code base of basic functions across the different services.
If you want to include a php file from a remote HTTP server, you will face two issues:
the remote server will interpret its php file, so you will only get a HTML (or any other generated format) stream. It can be bypassed, but you have to access the remote server settings.
it's absolutely NOT safe. If someone changes the remote script, he can do very bad things (like removing files, or even executing system commands)
However, if the remote server let you access the script in its plain text version, you can just include it.
You can't, at least not without exposing your code to the public. If it were possible to read PHP source from any server, that would be a terrible security hole.
If your code definitely isn't sensitive, change its extension so that it's non-executable (say, a .inc file) and include that instead.
I suggest mounting the remote host's directory (examples: NFS (Network File System) for Linux, Windows shares for Windows).
Including (= executing) code over HTTP isn't a good idea since there's no authentication involved.