Monday, July 29, 2013

Getting PHP Info without phpinfo function.

Recently I was able to reproduce a fairly good duplicate of the output of the phpinfo() without actually using the function as it has been disabled on the server. You can see the result here.

How I did this was fairly simple and can easily be trumped by changing a few settings if you are a sysadmin of a web hosting server. I will explain the methods I used, but I will not release the source (yet) as getting this done involved me snooping around the host's server. I will note I was not and do not condone the use of this for malicious purposes. I have been with this company for four or five years now and sometimes I enjoy playing around with their free hosting.

The first section of this phpinfo page contains information about the PHP binary itself such as the build date and configure command. The two aforementioned values are hardcoded right into the PHP binary itself and I used some simple regex matching to find them. I did test with a few different binaries on CentOS 6.4 (which the host uses as well) and found that the regex works regardless of the binary suggesting that it is put into the binary in the same order in that environment at the very least.

Instead of explaining in length how I figured out the rest, I will post some links for you and briefly cover it so I can get to the solution to prevent this method of getting phpinfo.

PHP: stream_get_wrappers - Manual
PHP: Reflection - Manual
PHP: get_loaded_extensions - Manual
PHP: stream_get_transports - Manual
PHP: get_defined_constants - Manual
PHP: phpcredits - Manual

Basically that was all I really needed to retrieve the rest of the data. I looped through the result of get_loaded_extensions and passed them through the ReflectionExtension class, which actually prints formatted HTML about the extension.

As far as solutions go, if you REALLY, REALLY don't want people to be able to do this you could disable the ReflectionExtension class to prevent getting the information on the extensions in php.ini:

disable_classes = ReflectionExtension,ReflectionZendExtension

You could disable the functions I used, but some scripts may actually use them to determine if they can run or not so it may not be advisable. It really is up to the administrator and how many complaints they are willing to deal with if it comes to it.

To prevent grabbing information from the PHP binary itself, if you don't need it to be readable you can just remove the read permissions on it from a command line:

chmod -r /usr/bin/php 

I am currently not aware of any problems that this would bring up, aside from functions like those in libmagic.

This little project wasn't to try and bypass the security by obscurity that disabling the phpinfo function... well, okay, maybe it was. It was rather annoying to not have that function available when I needed to know more about the extensions and such. It also proves that on a standard installation, disabling the phpinfo function does absolutely nothing.

From here, I am going to eventually release a pure php package with a few different ways of getting as much information as possible, including the methods I used plus fallbacks to not have to rely on the functions and classes I used in this method. I will also include a bit of magical detection and methods on how to harden your php installation. The latter being the original motivation of taking on this little project.