Spring Sale! Save 30% on all books w/ code: PLANET24
Web Dev + WordPress + Security

expose_php, Easter Eggs, and .htaccess

[ Screenshot: PHP Logo ] A reader recently brought to my attention a reported vulnerability on servers running PHP. It’s been known about for eons, but it’s new to me and it involves easter eggs in PHP so I thought it would be fun to share a quick post about what it is and how to prevent leakage of sensitive information about your server. It only takes a moment to disable the easter-egg information, should you decide to do so.

What it is..

Here’s the scoop according to the Open Source Vulnerability DataBase:

PHP contains a flaw that may lead to an unauthorized information disclosure. The issue is triggered when a remote attacker makes certain HTTP requests with crafted arguments, which will disclose PHP version and another sensitive information resulting in a loss of confidentiality.

Couldn’t have said it better myself. Basically if you’re running PHP it may be possible for someone to discover the PHP-version and other sensitive information. Also referred to as a type of “fingerprinting” attack. It’s not “threat level midnight” or anything like that, but certainly worth a few moments to lock it down: another layer of protection to increase the security of your website(s).

How it works..

On servers running PHP, visit any page, remove the trailing slash, and append any of the following query-strings:

?=PHPE9568F36-D428-11d2-A769-00AA001ACF42
?=PHPE9568F35-D428-11d2-A769-00AA001ACF42
?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000
?=PHPE9568F34-D428-11d2-A769-00AA001ACF42

If the vulnerability is present, requests made with these query-strings results in a variety of easter eggs and detailed PHP credits (see screenshots). When these easter eggs are visible, it means that expose_php is enabled on the server. And when expose_php is enabled, PHP-generated pages are sent with X-Powered-By response-headers that give PHP/version infos, such as “X-Powered-By: PHP/5.4.7”. Knowing the version number of software makes it easier for bad guys to research and exploit known vulnerabilities. So let’s take a moment to “plug the leak” by disabling expose_php.

Disable expose_php via php.ini

If you have access to (and can edit) your server’s php.ini file, the recommended solution is to set expose_php = Off and be done with it. In addition to preventing access to the PHP easter eggs and credit information, disabling expose_php has the added benefit of preventing PHP from sending version information in X-Powered-By HTTP Headers. So instead of sending the following response for PHP-generated pages (e.g., WordPress):

[ Screenshot: PHP Info sent via X-Powered-By Response Header ]

..we send this:

[ Screenshot: PHP Info NOT sent via X-Powered-By Response Header ]

Note that in addition to PHP sending its info via the X-Powered-By header, Apache is sending its version information as well. We can’t disable Apache directives via PHP, but as discussed in my book, it’s simple to do with the following directives placed in Apache’s main configuration file (httpd.conf):

ServerTokens Prod
ServerSignature Off

This simply uses the ServerTokens directive to disable the version number. The ServerSignature directive disables the version info on server-generated pages, which is an added bonus.

Prevent access via .htaccess

If you don’t have access to php.ini (as is the case for shared-server hosting), we can use a thin slice of .htaccess to deny access to the PHP credits and easter eggs:

RewriteCond %{QUERY_STRING} PHP[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} [NC]
RewriteRule .* - [F]

Just place that code in your site’s root .htaccess file and you’re good to go (no editing required). How does it work? In the first line we’re matching our regular expression against query-string requests (via RewriteCond). The regex pattern may look complicated, but it’s actually using variations on the same pattern, for example:

[0-9a-f]{8}” matches any sequence of eight numbers and letters “a” thru “f”.

Here’s a comparison to help visualize the pattern:

String: PHPE9568F34-D428-11d2-A769-00AA001ACF42
Regex: PHP[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} [NC]
Translated: “escaped equals sign, the sequence “PHP”, any sequence of eight, hyphen, any sequence of four, hyphen, any sequence of four, hyphen, etc.”

The line terminates with a “no-case” [NC] flag, making the pattern-match case-insensitive and increasing its effectiveness. Then in the second line, the RewriteRule simply denies access to any matching requests. The terminating [F] flag instructs the server to send along a 403 “Forbidden” status along with the request.

All together then

Combining our two Apache techniques, we get an equivalent to disabling expose_php. Again, editing php.ini is the best route, but when that’s not possible, these two code snippets will get you there.

1) Add to Apache’s main configuration file (httpd.conf):

# m0n.co/9
ServerTokens Prod
ServerSignature Off

1) Add to Apache httpd.conf or .htaccess:

# m0n.co/9
RewriteCond %{QUERY_STRING} PHP[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} [NC]
RewriteRule .* - [F]

By combining our two methods we deny access to PHP credits/info and disable broadcasting of the Apache version. That’s effective, but unfortunately there’s no way to prevent expose_php from sending its X-Powered-By headers using .htaccess (afaik).

Note also that Apache’s mod_rewrite must be enabled on the server for this to work. If it’s not, remove the second two lines (the rewrite directives) and just use the first two. They’re part of the Apache core and should work to disable the Apache infos.

PHP easter eggs

When something is intentionally hidden within a book, app, or whatever, it’s referred to as an “easter egg”. PHP has at least four of them:

Type Image URI
PHP Credits [ Screenshot: PHP Credits ] [server with expose_php = on]
?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000
Click here for larger view
PHP Logo [ Screenshot: PHP Logo ] [server with expose_php = on]
?=PHPE9568F34-D428-11d2-A769-00AA001ACF42
Zend Logo [ Screenshot: Zend Logo ] [server with expose_php = on]
?=PHPE9568F35-D428-11d2-A769-00AA001ACF42
PHP Logo [ Screenshot: PHP Logo (blue elephant) ] [server with expose_php = on]
?=PHPE9568F36-D428-11d2-A769-00AA001ACF42

So what’s the deal?

This is all fine and interesting, but is it worth it? It’s been reported that cPanel requires the PHP version info, so some hosts may leave expose_php enabled for that reason, but isn’t there a better way of communicating sensitive data?

Shouts out

Thank you to Warner Nanninga for bringing this to my attention and helping with further information. Cheers!

About the Author
Jeff Starr = Fullstack Developer. Book Author. Teacher. Human Being.
WP Themes In Depth: Build and sell awesome WordPress themes.

21 responses to “expose_php, Easter Eggs, and .htaccess”

  1. Jonathan Weatherhead 2012/10/15 1:45 pm

    Ha. That is a good find. Will be patching this on my sites tonight!

  2. Setting the

    ServerTokens Prod
    ServerSignature Off

    On my .htaccess as you suggested causes my site to throw a 500 Internal Server Error

    • That may be due to configuration of AllowOverride in the main configuration file (httpd.conf). Before asking your host about this, check to see if there is even anything to worry about by checking the response-headers of your PHP-generated pages (or by requesting one of the easter-egg URLs).. expose_php may already be disabled on your server.

  3. Dan Farrow 2012/10/16 6:51 am

    Great tip thanks Jeff!

    My WP server seems to be ok, but the VPS host I use for a Zend Framework based site (which I’m happily already using the 6G Blacklist/Firewall) is vulnerable.

    However when I add the line “ServerTokens Prod” the server throw a 404 error – any ideas?

    Cheers
    Dan

  4. You got the drop on me there, Perishable.

    But…

    =PHPw{8}(?:-w{4}){3}-w{12}

    …simplicate, and add lightness…

  5. Dang. I knew I shoulda posted the whole nine yards.

    Hows about…

    …escape, and add workingness…?

    • ..aaaand you’ve just described the last 10 years of my life.

      i.e., escape from boring day job and get into some work that I can enjoy :)

  6. airos chou 2012/10/21 11:12 pm

    I think the php easter eggs is a very interesting things.

  7. My server seems to have two instances of php.ini:

    /etc/php5/apache2/php.ini
    /etc/php5/cli/php.ini

    They appear to be the same file. So, turned expose_php to Off for both of them. Can anybody explain why I have two instances of the php.ini file and if this is a problem? Also, what is necessary, good, or bad that I edited them both?

    Thanks!

  8. Also, oddly enough my httpd.conf file appears to be empty.

    -rw-r--r-- 1 root root 0 May 6 2012 httpd.conf

    Can anybody explain what that’s about? I haven’t yet added:

    ServerTokens Prod
    ServerSignature Off

    yet since I’m unsure why that file exists, but is empty.
    Thanks!

  9. Sorry to spam your comment section, but you’re not dealing with a pro here, just somebody who wants to practice a little better security.

    After editing both php.ini files by turning expose_php to Off and saving/exiting. My server still seems to be exposing my php information. That is to say, the easter eggs are still visible. I know that oftentimes after editing certain files you need to issue a restart command or something. Is this one of those times?

    • Jeff Starr 2012/11/26 1:41 pm

      A restart shouldn’t be necessary, but is certainly worth a try. Sounds like something specific to your server.. I would contact your host for more information.

      • So, after further research I discovered that according to:

        http://ubuntuforums.org/showthread.php?t=903386

        httpd.conf is deprecated. So, I added:

        ServerTokens Prod
        ServerSignature Off

        to the /etc/apache2/apache2.conf

        at the very bottom of the file. The ServerTokens and ServerSignature did not exist at all beforehand. The entire lines were inserted by me.

        Then I saved and exited, and followed it with

        sudo /etc/init.d/apache2 restart

        Then I checked and none of the easter eggs appear any more. It merely shows me the same page I was already on, with the extended URL. So, I guess it worked.

        If anybody sees anything wrong with what I’ve done here please let me know. Thanks!

      • Hi Seth, this is the first I’ve heard of httpd.conf being deprecated, in fact the latest version of Apache continues to refer to it by name in the Docs (second sentence):

        http://httpd.apache.org/docs/2.4/configuring.html

      • Interesting. I’m too much of a noob to know whether or not what those people were talking about were true or not. But quoting the link you just gave:

        The main configuration file is usually called httpd.conf.

        So, maybe those guys were wrong and it’s not deprecated, but it does sometimes end up in the apache2.conf file.

        Anywho, everything seems to be working great now. So, thanks for the article!

      • Ubuntu officially thinks httpd.conf is deprecated:

        https://help.ubuntu.com/12.04/serverguide/httpd.html#http-configuration

        httpd.conf: historically the main Apache2 configuration file, named after the httpd daemon. Now the file is typically empty, as most configuration options have been moved to the below referenced directories.

      • Thanks for the update! Still can’t find anything from Apache about httpd.conf being deprecated (so it’s technically not deprecated), but interesting to know how Ubuntu sees things. If anyone knows more about this please share the news. Thanks.

  10. OK, so this is a relatively old thread (and like Seth, I’m also a bit of a noob when it comes to configuring Apache), but so far as the “X-Powered-by” header is concerned, surely a simple-ish unset of the head should be a good start. I don’t have access to php.ini or httpd.conf files on my host’s server, but I’ve found using

    ServerSignature Off
    <IfModule mod_headers.c>
         Header unset X-Powered-By
    </IfModule>

    as well as the regex string in .htaccess does the job and (when I get round to it) modifying the rewrite rule will send users attempting to exploit this Easter Egg to my bot trap

  11. qgustavor 2013/04/20 2:40 pm

    Why server info is sensitive data? Hiding the version will not do anything related to security.
    Don’t want make hacker work to find a exploit related to your server version? Always update it.

    • Jeff Starr 2013/04/21 1:15 pm

      “Always update it” is great advice, unfortunately many people have no control over server software (e.g., shared hosting).

Comments are closed for this post. Something to add? Let me know.
Welcome
Perishable Press is operated by Jeff Starr, a professional web developer and book author with two decades of experience. Here you will find posts about web development, WordPress, security, and more »
The Tao of WordPress: Master the art of WordPress.
Thoughts
I live right next door to the absolute loudest car in town. And the owner loves to drive it.
8G Firewall now out of beta testing, ready for use on production sites.
It's all about that ad revenue baby.
Note to self: encrypting 500 GB of data on my iMac takes around 8 hours.
Getting back into things after a bit of a break. Currently 7° F outside. Chillz.
2024 is going to make 2020 look like a vacation. Prepare accordingly.
First snow of the year :)
Newsletter
Get news, updates, deals & tips via email.
Email kept private. Easy unsubscribe anytime.