By Steve Knoblock & Jason Birch
Running PHP Scripts Securely
Connecting to a database requires that passwords be included in the script at some point. Other scripts you write may include sensitive information. This information may be exposed if you do not wrap your PHP scripts. Protecting your scripts from prying eyes is called “wrapping.” When you wrap a script, it is called by another script that hides your script and performs a number of security checks to ensure only authorized use is made of it.
How do other users see the passwords?
There are two ways:
If you are not paying attention and place your passwords in the web tree inside a file whose extension is not parsed by the php interpreter. (i.e. they can load it as http://www.mysite.com/passwords.txt and get the contents) This is particularly bad because anyone on the web can see the file.
If you place the password in a file that can either be read by the web server directly or by other users in your group on the same web server. This does not apply to people who can afford a dedicated server to themselves. If you place the passwords in a file that is readable by other users in your group, then they can browse to your directory using FTP or Telnet and read them directly. Some hosts prevent this behavior by chrooting (making /usr/home/username equal to / when you login; chroot is Unix for “change root”) user logins. However, many of them do not plug a similar hole that can allow other users on your server to access your files if they are readable by the web server. In these cases, the other users can simply write a script (that is run as userid “nobody”) that can access any files on the server that are readable by the web server.
How does wrapping prevent that?
Wrapping sets the user who is accessing the files to be equal to your userid. A good (safe) wrapper also does several security-based sanity checks on the request before running it. The only drawback to running a wrapper is that you need to write secure code or a hacker could potentially access any of the files within your web tree (or even outside of it if the wrapper allows that).
What is php-cgiwrap?
A script wrapper for PHP. This is a version of the cgiwrap script wrapper used for Perl programs. The php version of cgiwrap was created by pairNetworks for use on their servers. If you host your php scripts elsewhere, some other method will have to be employed to wrap them.
Note: php-cgiwrap is only available on sites hosted by pairNetworks. They have a support page fot it. If you’re curious about how it works, they modified the cgiwrap source to call php with the script as an argument instead of calling the script itself.
There are alternatives, which are explained below.
Some web hosts offering PHP enabled pages essentially make wrapping transparent. The server may seem to run cgi-wrap on PHP scripts transparently, as long as they have the .php extension. You may not even realize your scripts are being wrapped. But it’s important to ask your hosting provider if they are.
There are several ways of doing this. You could use mod_rewrite to automatically pipe all php requests through a script wrapper, or you could use the Apache suExec functionality, which is likely what your host may have done. For a good primer to the subject, see (http://www.apache.org/docs/suexec.html).
Caution: If the provider has not made available a way of running your scripts in a way that keeps the passwords away from the prying eyes of other users on your site, then you should move to a provider that actually cares about user security.
How Do I Get Wrapped?
You’re probably thinking all this is very confusing. And you’d be right. Wrapping is a confusing subject, partly because of the redirection going on and partly because for the wrapper to remain secure it must be something of a “black box.” I hope you will find this a clear explanation, which you can take away with you when assessing your PHP wrapping needs on your own site. Don’t worry if you feel the explanations are too technical, you don’t have to know how everything works to ensure your scripts are secure.
How do I know if my host uses wrapping?
Simple, create a script and mark it with chmod 700. If the web server can still run it, then they are using wrapping. If not, then they are not.
How do I setup wrapping anywhere?
You don’t, your provider does. This is because wrapping is a dangerous thing if it is not set up properly, and the responsibility for installing it should be taken by the sys admin. Also, multi-user wrappers need to have suid and sgid ability, which is usually only vested in root.
That’s about it for now, let me know if this raises more questions than it answers (as is usually the case).
How do I setup wrapping for my PHP scripts?
Okay, now that you know what a script wrapper is and why you need one, it’s time to wrap your PHP enabled pages. The example I will give is for using php-cgiwrap (available only on pairNetworks sites at this time) and the Apache web server. You will have to check with your own hosting provider for information on how they implement script wrapping. Wrapping can be a very individual thing. However, many of the basic concepts apply to other environments.
To enforce wrapping of scripts in a sub-directory of your web site, add these lines to your .htaccess file. They simply tell the web server to dynamically add a new MIME type for files having the .wphp extension. And for any such files requested, execute them by running them through the PHP interpreter, which is a CGI program in of itself written in C.
AddType application/x-httpd-wphp wphp Action application/x-httpd-wphp /cgi-sys/php-cgiwrap/cityg/php3.cgi
Caution: If you place these lines in the .htaccess file in your document_root directory (the base directory where web pages are servced from, the first publicly accessible directory, i.e. the public_html or www directory on your web hosting account), all files having the wphp extension on your web site will be executed as PHP programs. This is the desired behavior, not really a caution, but I wanted to get your attention about it because it’s important to know.
However, you may dislike giving your pages a non-standard file extension, so if place these lines in your .htaccess file in a directory where your PHP enabled pages are, all will be run through the wrapper. There’s no need to have separate extensions for wrapped an unwrapped pages.
AddType application/x-httpd-wphp php3 Action application/x-httpd-wphp /cgi-sys/php-cgiwrap/cityg/php3.cgi
Caution: If you do use the option to wrap all PHP enabled pages in a directory, keep this warning in mind. Before you place those lines in your .htaccess in your document_root directory, be aware that every script on your site will be executed by first running through the wrapper. This is grossly inefficient and wasteful of shared resources, and should only be used if your entire site is a web application consisting of all PHP generated content. Even in that limited case, if most of your PHP pages do not contain sensitive information (like database passwords in included configuration files), then you should avoid doing this. Remember, every time php-cgiwrap is called a program must be run besides the program that runs your PHP scripts. This additional overhead could become significant. You can place these lines in an .htaccess file for a sub-directory of your site, if it contains a specific web application that accesses a database on most of its pages. In other words, if the balance of PHP enabled pages being served require hiding passwords, then it makes no difference to wrap all of them.