Professional PHP Programming - Installing a Private Key (
Page 8 of 9 )
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
CertificateTo 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 CertificateChances 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
MechanismNormally 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.