Web pages that must be publicly readable demand a certain level of local security. If you don’t create effective barriers, users may view your source code and use the information they find to their advantage. Viewing the source to your application is not necessarily a bad thing, but do you really want to advertise the username and password for your backend database account through your Web pages? Probably not.
Since PHP, by its nature, is an interpreted scripting language, how can you keep everyone from seeing the source to your proprietary application? Or prevent snoopers from seeing sensitive company or employee data they shouldn't be seeing?
One solution is a pair of products produced by Zend, Inc. Zend has been instrumental in the development of PHP for quite some time. In fact, PHP4 includes the Zend Engine, which speeds up the processing time it takes to interpret your PHP pages. Beyond the Zend Engine, however, are two closed-source applications from Zend that focus on local security. The first application, Zend Encoder, compiles your PHP source into binary files, while the second application, Zend Optimizer, interprets what Encoder compiles, as well as optimizes the code for faster execution.
In this Daily Drill Down, I will walk you through the installation, configuration, and basic usage of both of these powerful tools.
The Zend Optimizer is a module you plug in to your Web server so that the server can interpret and optimize the compiled PHP files. The Optimizer reads the intermediate code that is generated by the standard Zend run-time compiler and optimizes it for faster execution. This alone makes the Zend Optimizer a worthwhile product for every server using PHP. However, the other advantage of the Zend Optimizer is that it can execute the compiled PHP files produced by Zend Encoder. These compiled PHP files are known as Zend Intermediate Code files and can only be created by the Zend Encoder, which I will discuss in a moment.
Zend Optimizer is a free product that is available for free use. In order to download it, however, you need to register on Zend's Web site through its online store. I find this a little excessive for a free product, but I concede that they may wish to track how many people are downloading and using the product.
Download the version of Zend Optimizer for your particular Web server platform and you’ll be ready to install it. You can download Zend Optimizer for Linux, Windows, FreeBSD, and Solaris. If you are using PHP 4.0.5 or PHP 4.0.6 on Linux using glibc 2.1 or higher, the file you will end up downloading is called ZendOptimizer-1.1.0-PHP_4.0.5-Linux_glibc21-i386.tar.gz. Copy this file to your /usr/local directory and unpack it as root, using:
# tar xvzf ZendOptimizer-1.1.0-PHP_4.0.5-Linux_glibc21-i386.tar.gz
You will now have a horribly long subdirectory that you will rename to simply Zend/ by issuing:
# mv ZendOptimizer-1.1.0-PHP_4.0.5-Linux_glibc21-i386 Zend
Now change into that directory. You will want to create a new subdirectory called lib/, which will store the ZendOptimizer.so file currently sitting in /usr/local/Zend. The ZendOptimizer.so file is the library, which you need to load into your PHP system that works in concert with the Zend Engine. This will allow you to execute your PHP code faster. To do this, execute:
# cd /usr/local/Zend
# mkdir lib
# mv ZendOptimizer.so lib
At this point, you will want to edit your php.ini file, which is typically found in /etc. Take your favorite editor and open /etc/php.ini and add the following to the end of the file:
You may also want to add another line to your php.ini file if you do not plan to use files encoded with Zend Encoder. This will help to speed up the execution of your plain PHP files even further. If this is the case, add the following:
zend_optimizer.enable_loader = 0
Finally, you will have to restart your Apache server to load the new commands into your PHP system. For those of you who use Sys-V style initscripts (used in Red Hat, Mandrake, etc.), you will execute:
# /etc/rc.d/init.d/httpd restart
For those of you who don't, you will execute:
# apachectl stop
# apachectl start
Once you've restarted your Web server, you may want to create a quick test PHP file that simply contains:
<? phpinfo(); ?>
Then load that page in your browser. The PHP info displayed should indicate that it is making use of the Zend Optimizer as well as what version it is using. Once you see this information, you’ll know your installation was successful.
As I mentioned earlier, Zend Encoder is the program that actually encodes your PHP files into the Zend Intermediate Code binary format, which the Zend Optimizer is able to read and execute. Unlike the Zend Optimizer, however, the Zend Encoder is not free and must be purchased from Zend. The price of the Zend Encoder—US$2400—is not for the faint of heart and may be too costly for a hobbyist PHP programmer. But for larger companies or ISPs with multiple users allowing shell access, it may be worth the investment. At any rate, if you plan to develop PHP applications and use Zend Encoder, rest assured that the cost is yours alone since the users of your application can download and install Zend Optimizer for free. Because of this, Zend Encoder may be more appropriate for proprietary applications written in PHP as opposed to open-source projects that simply want to optimize their code.
Once you have downloaded the trial version of Zend Encoder or purchased it, you can install Zend Encoder in the same location as Zend Optimizer—if you plan to develop on the same system as your Web server. If not, /usr/local/Zend is still a good place to put the files. As of this writing, the filename of the purchased version of Zend Encoder is ZendEncoderUnlimited-1.1.0a-PHP_4.0.3-Linux_glibc21-i386.tar.gz. You can unpack this file by using:
# cd /usr/local
# tar xvzf ZendEncoderUnlimited-1.1.0a-PHP_4.0.3-Linux_glibc21-i386.tar.gz
# mv ZendEncoderUnlimited-1.1.0a-PHP_4.0.3-Linux_glibc21-i386.tar.gz Zend
The trial version of Zend Encoder will have a slightly different name from the purchased version, but the contents are the same, except that the test drive version contains a 30-day evaluation license. If you purchased Zend Encoder, copy your zend_encoder.dat license file to the /usr/local/Zend directory.
At this point, you will have a few files in your /usr/local/Zend directory, the most important files being zendenc, encode.sh, and lmutil. lmutil is useful if you plan to purchase Zend Encoder. It will generate a unique host ID based on your ethernet MAC address. This not only prevents you from sharing your copy of Zend Encoder with your friends but also prevents you from upgrading your network card.
The zendenc binary is relatively self-explanatory. This is the file used to encode your PHP files into the Zend Intermedia Code format. It has a few basic options that can be used when compiling your PHP source files:
- —optimizations Turn optimization on or off
- —asp-tags [on|off] Turn ASP tag recognition on or off
- —short-tags [on|off] Turn short tag support on or off (short tag being <? ?> as opposed to <?php ?> in your code)
- —delete-source Delete the original source file and save the encoded file with the same name as the source file
- —rename-source [ext] Move the original source file to [input_file].[ext] and save the encoded file with the same name
- —quiet Do not report encoding progress
- —silent Do not print messages except errors
- —force-encode Force encoding already-encoded files
More often than not, the only options you are likely to use are the “—delete-source” and “—rename-source” options. The ASP tag recognition defaults to off and the short tag support defaults to on, which are accurate settings for most people.
So, to encode index.php, you might use:
# ./zendenc —rename-source src index.php
This will rename the original index.php file to index.php.src and create an encoded file called index.php, which is what you’ll place into your Web server directory tree. If you opened the new index.php in your text editor at this point, you would see a bunch of binary characters with the prefix Zend-. The size of this encoded file depends entirely on what is in the source file. For instance, our test file that consists only of:
<? phpinfo(); ?>
is a 17-byte file. The encoded file is 119 bytes. So there is a bit of a size increase, but the overall optimization will save time in the processing of the file, which is more important (to me, at any rate) than the size taken up on the hard drive.
The encode.sh script, which is also included in the directory, is a batch encoder that will encode your source after you define a source directory and a destination directory. You can do this either by manually editing the script or by using some handy command-line options. You will, however, want to edit the script to set the location of the zendenc binary if it is not in the assumed /usr/local/Zend/bin directory. If you are following along with our instructions, you would edit the script by changing:
If you want to get a listing of all the options the script supports, use:
# ./encode.sh -h
Now for a quick example: Let's assume you have your Web site pages in the directory ~/cvs/website because you use CVS to track the changes to your Web site. If your Web root directory is /var/www/html, you might use the following to encode all of the files:
# cd ~/cvs/website
# /usr/local/Zend/encode.sh -s ~/cvs/website -d /var/www/html
This will encode all of the files in your ~/cvs/website directory and save the encoded files into /var/www/html. For some odd reason, the encode.sh script insists that your current working directory is the directory in which you wish to encode the files, despite the fact that you manually specified the directory in the command-line options. If you wanted to clean out the destination directory first, you would add "-c" to the end of the above command.
I have to admit that Zend Encoder is a very useful little tool. It definitely has its place, especially considering how many PHP applications are being developed. PHP is a powerful language, and many people much prefer it to CGI scripts written in C or Perl. Until now, the commercial offerings could only write their applications in CGI scripts. Because C is a compiled language, companies can protect their intellectual property while still providing a good product. Zend Encoder, however, allows people to write code in PHP and still protect their code.
The downside to this, however, is the hefty cost. Zend Encoder is not cheap. Of course, one must assume that the people who would be using it most would be those creating commercial applications. To that end, if they're receiving money for their applications, asking them to spend some up-front for a tool to protect their work sounds reasonable.
After poking around on Zend's Web site a little, I was able to find an option for modest PHP programmers who would like to take advantage of the security and speed that Zend Optimizer and Encoder offer without forking over the big bucks. Zend Developer Server Suite is a monthly licensed package deal for a minimum of twelve months. This package comes with Zend Encoder, as well as Zend's PHP IDE (Integrated Development Environment), a service called Zend LaunchPad, and online support. The cost for this service is $600 per year—a much more reasonable expenditure for PHP hobbyists.
If you go to Zend's Web site, you might want to check out the Zend Non-Commercial Developer Suite. While this package does not include Zend Encoder, it does offer the IDE and the LaunchPad service. The assumption is that the Zend Encoder would not be of interest to most noncommercial developers.
If you're in the market to develop proprietary Web applications, Zend Encoder may be just the tool for you. The encoding process is fast, and when coupled with the Zend Optimizer to execute the code, the application is fast as well. While the price may seem steep, rest assured that if you have just written the next killer Internet Web application, your up-front cost of Zend Encoder would be paid for in no time.
Vincent Danen works on the Red Hat Security Response Team and lives in Canada. He has been writing about and developing on Linux for over 10 years and is a veteran Mac user.