Sunday, 16 August 2009

Apache 2 with SSL/TLS: Part 3

Introducing part three

This article concludes our three part series dedicated to configuring Apache 2.0 with SSL/TLS support -- for maximum security and optimal performance of SSL based e-commerce transactions.

Part one introduced key aspects of SSL/TLS and then showed how to compile, install and configure Apache 2.0. The second part discussed the configuration of mod_ssl and authentication issues, and then showed how to create web server's SSL certificate.

Now, in the third and final article, we will take a look at client authentication using client certificates, show how to chroot a secure Apache, discuss common attack vectors, and then describe some typical configuration mistakes made by administrators that will decrease the security level of SSL communications.

Client authentication

One of the most popular methods for authenticating users in web applications is a password, passphrase or PIN, in other words, "something you know." The greatest advantage of such a method is its simplicity. For an administrator, it is enough to add few directives to httpd.conf and create a passwd file to implement such a schema.

Unfortunately, because of their simplicity passwords are vulnerable to a number of attacks. They can be guessed, sniffed over the wire, brute-forced, stolen (such as when a user writes them down on sticky notes) or coaxed out (through social engineering or some kind of "phishing" method). This is why standard password authentication is considered to be weaker than using one-time passwords, hardware tokens or others forms of authentication.

Few people realize that when using a SSL web server there is an stronger method of authenticating users: client SSL certificates, or "personal" certificates for each user. In this method, we can authenticate web users based on "something you have," using a certificate and a private key corresponding to the client certificate, as well as "something you know," which would be a passphrase to the private key. Thus, using certificates is more secure than using standard password solutions, mainly because besides an intruder would need to get both pieces of authentication -- the private key that corresponds to the user's certificate, as well as the passphrase -- to gain access. Moreover, unlike a standard password, the certificate's passphrase is not actually sent over the network at all, it is used only locally to decrypt the private key.

As will be shown, the implementation of this method of authentication is not complicated and it can be performed in few steps, which administrators will find to be almost as easy as the more popular Basic Authentication password method.

Configuring Apache to use client certificates

In order to configure Apache to support client authentication via X.509v3 certificates, we need to perform four actions:

  1. Enable client authentication in the Apache's web server

    To enable the use of client certificates, we need to add the following directives to httpd.conf:

    SSLVerifyClient require
    SSLVerifyDepth 1

    Thanks to the SSLVerifyClient directive, the access to the web server will now be limited only to the web browsers that present a valid certificate, one which is signed by our local CA. Note that the process of creating local CA has been described in the previous article. The "SSLVerifyDepth" value specifies the maximum depth of the intermediate certificate issuers in the chain of certificates. In our case, we will set this value to "1," because all client certificates must be signed by our local CA -- we are not using intermediate CAs.

  2. Install the local CA's certificate into the Apache directory structure.

    install -m 644 -o root -g sys ca.crt /usr/local/apache2/conf/ssl.crt/ 
  3. Set the SSLCACertificateFile directive (in httpd.conf) to point to the CA certificate we just installed.

    SSLCACertificateFile /usr/local/apache2/conf/ssl.crt/ca.crt
  4. Now restart Apache.

    /usr/local/apache2/bin/apachectl stop
    /usr/local/apache2/bin/apachectl startssl

From now on, access to the web server via SSL will be granted only to the web browsers that present a valid client certificate, signed by our local CA. To test it, we can try to access the URL of the website. After establishing SSL connection, MS Internet Explorer will ask us to choose the client certificate we want to use, as shown below in Figure 1.

Figure 1. Internet Explorer asking for a client certificate.

Since we do not yet have any client certificate installed, access to the web server will simply be denied.

Creating a client certificate

In general, creating an individual client certificate is very similar to creating a web server certificate. The only difference is that we will use different X.509v3 extensions (the "ssl_client" section from openssl.cnf) and we will store both the private key and certificate in PKCS#12 format (also referred as PFX).

For the sake of simplicity, please follow the steps below using OpenSSL to produce the client certificate. Note that it is highly recommended that any actions that are to be performed by users (numbers 1, 2, 7, 8 in the steps below) should be as automated and simplified as possible to minimize user interaction and user error. To that end, additional technology such as Java Applets could be used. Alternatively, a dedicated host can also be used for the purpose of creating client certificates. In this latter case, users would need to visit the server in-person and enter their passphrase on the dedicated host to encrypt their own private key. Although this option might seem a bit inconvenient, it is the most secure method, as a user's identity can be verified and both the certificate and the private key can be passed to the user without sending it over the network.

The steps to create and install a client certificate are exactly as follows:

  1. Create a private/public key pair for the user, together with a certificate request. If a dedicated host is not being used to serve the certificate, this should be executed on the user's host:

    openssl req \
    -new \
    -sha1 \
    -newkey rsa:1024 \
    -nodes \
    -keyout client.key \
    -out request.pem \
    -subj '/O=Seccure/OU=Seccure Labs/CN=Frodo Baggins'
  2. The user sends the certificate request (request.pem) to the local CA, to be signed.
  3. The local CA's task is to verify that the information from the client certificate request is indeed valid and correct.
  4. After verifying, the certificate request (request.pem) should be copied into the $SSLDIR/requests directory on the local CA host using removable media, such as a USB drive.
  5. The local CA should sign the certificate request as follows. This should be executed on the CA's host.

    openssl ca \
    -config $SSLDIR/openssl.cnf \
    -policy policy_anything \
    -extensions ssl_client \
    -out $SSLDIR/requests/signed.pem \
    -infiles $SSLDIR/requests/request.pem
  6. The local CA should send the certificate (signed.pem) to the user.
  7. After receiving the signed certificate, users need to store their private key together with their certificate into PKCS#12 format.

    openssl pkcs12 \
    -export \
    -clcerts \
    -in signed.pem \
    -inkey client.key \
    -out client.p12

    The newly created client.p12 file should be protected with a hard-to-guess passphrase. All other files (including the unencrypted private key, the signed certificate and the certificate request) should be securely erased from the user's disk space using a wipe utility.

    wipe client.key signed.pem request.pem
  8. The client certificate, together with the private key, should be installed in the user's web browser. An example of this for Microsoft Internet Explorer is shown below in Figure 2.

    Figure 2. Installing a certificate in Internet Explorer.

    To protect the private key against accidental or unauthorized use, the option "Enable strong private key protection" should be checked. Also, to protect the certificate from being stolen, it should be not be possible to export the certificate -- the option "Mark this key as exportable" should be disabled. Both these browser configuration options are shown below in Figure 3.

    Figure 3. Protecting the client certificate in Internet Explorer.

    In addition, the security level of the browser should be changed to "High." We see this during the next step of the Import Wizard, as illustrated below in Figure 4. Thanks to this option, a user will be asked to enter his password every time the web browser wants to use that client certificate.

    Figure 4. Security level should be set to "High" in IE.

That's all there is to it. The certificate can now be found under the "Personal" tab in the certificate view (in MS Internet Explorer's menu -> tab "Content" -> "Certificates"). If we double click the certificate we should see some properties similar to Figure 5, below.

Figure 5. Client certificate details in IE.

Using the client certificate

At this point we should try to access the URL of the website again. If the above have been successfully completed, once it is requested we should be able to see and choose the installed certificate from the list, as shown in Figure 6.

Figure 6. Choosing the client certificate when prompted.

After choosing the certificate, the user must enter the required passphrase that decrypts the corresponding private key, as shown in Figure 7.

Figure 7. Entering the passphrase for the certficate.

Now we will have access to the secure website, illustrated in Figure 8.

Figure 8. Secure access, using certificates, has been granted.

Customizing access control

With additional server-side directives, we can control which parts of the website particular users or groups of users are granted or denied access. For example, when and organization must deal securely with many different companies, we can restrict access to the website to just one particular company (O=Seccure), by adding the following directives to httpd.conf:

SSLRequire %{SSL_CLIENT_S_DN_O} eq "Seccure"

Another example shows how to allow access only to a certain department (OU="Seccure Labs") within the company (O="Seccure"):

   SSLRequire %{SSL_CLIENT_S_DN_O}   eq "Seccure" and \
%{SSL_CLIENT_S_DN_OU } eq "Seccure Labs"

Or alternatively, we can provide access to just a few departments (OU="Seccure Labs" or OU="Development") within the same company (O="Seccure"):

   SSLRequire %{SSL_CLIENT_S_DN_O}   eq "Seccure" and \
%{SSL_CLIENT_S_DN_OU } in {"Seccure Labs", "Development"}

Finally, we can even provide access to just one specific user (CN="Frodo Baggins") from a specific company (O="Seccure"):

   SSLRequire %{SSL_CLIENT_S_DN_O}  eq "Seccure" and \
%{SSL_CLIENT_S_DN_CN} in {"Frodo Baggins"}

Note that we can also provide the above environment variables to CGI scripts (including PHP and others), by adding the "+StdEnvVars" parameter to the SSLOptions directive. This features allows us to use DN names inside web applications (PHP and others), to provide more detailed authorization and access control.

SSLOptions +StdEnvVars 

Revoking a client certificate

If a client certificate becomes compromised or lost, what do you do? In this case we need to revoke the certificate, as was already described in the previous article. Then, we must copy the CRL file into the Apache directory, as follows:

install -m 644 -o root -g sys crl.pem /usr/local/apache2/conf/ssl.crl/ 

We also need to make sure that the "SSLCARevocationFile" in httpd.conf points to the above file:

SSLCARevocationFile /usr/local/apache2/conf/ssl.crl/crl.pem 

Then, we need to restart Apache for the changes to take an effect. The revoked certificates will not be allowed access to the website, as shown below in Figure 9.

Figure 9. Access attempted with a revoked certificate.

Chrooting the server

To improve our web server's security and make Apache less vulnerable to buffer overflow attacks, it is recommended that one run Apache in the chrooted environment. Chrooting the web server isolates the process to a new root directory so that it cannot see the rest of the server's files.

The process of chrooting Apache has been already described in "Securing Apache 2.0: Step-by-Step," so readers are encouraged to follow steps that were shown there. With the added support for SSL/TLS, we will need to install some additional libraries and create a few new subdirectories. In the case of FreeBSD 5.1, the list of these libraries and directories are as follows:

cp /usr/lib/ /chroot/httpd/usr/lib/
cp /usr/lib/ /chroot/httpd/usr/lib/
cp -R /usr/local/apache2/conf/ssl.key /chroot/httpd/usr/local/apache2/conf/
cp -R /usr/local/apache2/conf/ssl.crt /chroot/httpd/usr/local/apache2/conf/
cp -R /usr/local/apache2/conf/ssl.crl /chroot/httpd/usr/local/apache2/conf/

We also need to add urandom device as follows. Once again, the example below is taken from FreeBSD 5.1:

ls -al /dev/*random
crw-rw-rw- 1 root wheel 2, 3 Jan 4 12:10 /dev/random
lrwxr-xr-x 1 root wheel 7 Jan 4 12:10 /dev/urandom -> random
cd /chroot/httpd/dev
mknod ./random c 2 3
ln -s ./random ./urandom
chown root:sys ./random
chmod 666 ./random

In the case of other operating systems, readers can create the list of required files by using commands like truss, strace, ktrace etc., as was described in details in the section "Chrooting the server," from the SecurityFocus article, "Securing Apache: Step-by-Step"

Once all these steps have been completed, we can run Apache in the chrooted environment, as follows:

chroot /chroot/httpd /usr/local/apache2/bin/httpd 

Known attacks on SSL/TLS

Although SSL/TLS protocols offer a high level of security in theory, its actual implementations may be vulnerable to several types of attacks. Of the many attack vectors, two are worthy of special attention:

  • Man in the middle (MITM) attacks

    In this type of attack, an intruder intercepts the traffic that is being sent between a client and server, such as by forging DNS replies or by performing ARP redirection. Then, it impersonates the client to the server, and vice-versa. During this attack, the user's web browser does not connect directly to the destination server, but instead to the intruder host, which impersonate the web browser and essentially acts as a proxy.

    There is good and bad news for an administrator who wishes to defend against such attacks. The good news is that the web browsers warn users when the web server's identity cannot be verified, which may indicate possible man-in-the-middle attack, by displaying a message window with a warning. The bad news is that in real life, users very often ignore such warnings. Hence, if the user's web browser accepts connections to SSL web sites that identities cannot be checked, we can only rely on users' education and trust that they will not press the "proceed" button, if such warning message has been displayed.

  • Brute-force attack on the session key

    This attacks can be performed when the intruder knows or can assume part of the clear text that was sent during SSL/TLS session, such as (such as "GET / HTTP/1.0"), and the intruder can eavesdrop this session (such by using tcpdump, Ethereal or other tools). Then, intruder can encrypt the assumed part of the text by using every possible key, trying to find its occurrence in the originally encrypted SSL/TLS traffic. Once such an occurrence has been found, the key that was used to encrypt this part of the message can be used to decrypt the rest of originally encrypted SSL/TLS traffic.

    The good news is that maximum number of keys that must be checked is 2^128 when 128-bit symmetric cryptography has been used. Today this is believed to be strong enough to protect the session for literally dozens of years. However, since CPUs grow in strength every year, we cannot really predict for how long 128-bit symmetric keys will be considered to be secure, particularly for hackers with access to large supercomputers.

    In case of export-class cipher suites (40-bit, and in some extended 56-bit ciphers) such brute force attacks can be successfully performed in a reasonable amoung of time -- sometimes even in few days, depending on the available number of CPUs. If export regulations in your country allow for the use of strong cryptography, one should definitely use it instead of export-class cipher suites.

In addition to the two types of attacks listed above, there are some other potential vulnerabilities, including algorithm rollback attacks, timing attacks, traffic analysis, Bleinchenbacher's attacks, and others. Those interested in understanding them can find more information in Bruce Schneier and David Wagner's document, "Analysis of the SSL 3.0 protocol," (PDF document) as well as in many other documents that can be found on the public Internet.

Typical SSL/TLS implementation mistakes

  • Certificates signed by a CA that is not known to the web browser
  • The biggest mistake that can be made when implementing SSL/TLS is with the signing of the web server's certificate by a CA that is not trusted by web browser. In other words, the CA's certificate is not installed in the web browser. This makes Man-In-The-Middle attacks very easy to perform, because users have no way of verifying the identity of the web server.

    To avoid this problem, it is important to make sure that signer's certificate (usually, a trusted CA) is installed in user's web browser. If a local CA was used for signing the web server's certificate, then we must make sure that all web browsers on all clients requiring access have the local CA's certificate installed. The same rule applies to self-signed certificates.

  • Expired certificates

    The web browser's certificate should be renewed before the previous one expires. Otherwise it will result in the same problem as above, whereby web clients will not be able to authenticate with the web server -- which once again makes SSL/TLS connections vulnerable to man in the middle attacks. In this case, users may get used to seeing a warning message saying the certificate has expired, and then will probably not notice if it is a bogus certificate.

  • Vulnerable versions of OpenSSL and Apache

    It is very important to always run the latest versions of OpenSSL and Apache. Programmers writing larger pieces of code such as these without bugs is virtually impossible, so we should always use the latest stable versions of the above software. The latest versions should theoretically contain fewer security vulnerabilities (both discovered and not-yet discovered) than previous versions.

  • Acceptance of SSL v2.0, anonymous authentication (aNULL), and cryptography (NULL) by the web server

    As was previously discussed, the use of cipher suites that support anonymous authentication or require no encryption should be disabled. Otherwise, there is a risk that client can be tricked into negotiating parameters that can dramatically lower the security level of the connection. For this reason we should disable the use of the SSLv2.0 protocol and use TLSv1.0 or SSLv3.0 instead.

  • Use of weak encryption

    Early implementations of SSL were only able to use 40-bit keys for symmetric encryption, due to US government restrictions. Unfortunately, the data encrypted by 40-bits symmetric keys can now be decrypted in a relatively short period of time, and for this reason 40-bit and 56-bit keys should no longer be used. Most modern web browsers support 128-bit keys for symmetric encryption, and this is now the minimal recommended length of key for use with SSL/TLS.

  • Improper use of a Network Intruder Detection System (NIDS)

    It is important to stress that unless a NIDS is capable of decrypting the SSL traffic (such as through the use of the web server's private key) it is simply unable to detect attacks on the web application. To detect eventual break-ins, we must either use either a HIDS (Host-based Intruder Detection System), or put the NIDS in a segment where SSL/TLS traffic is being sent in clear text, such as between a SSL Reverse Proxy and the web server's farm. Otherwise we may not be able to detect any attacks, except denial of service, performed against the web server.

  • Allowing access not only via SSL, but also via non-encrypted protocols (HTTP)

    Setting up SSL/TLS and opening port 443/tcp to the web server, by itself, means nothing if users can still access website via non-encrypted HTTP on port 80/tcp. Thus, one must double-check that the protected content cannot be accessed via non-encrypted HTTP or other protocols (including FTP, Samba, NFS, and so on).

  • Vulnerable client machines

    When we focus on securing Apache web servers, we can easily forget about the security of the client machines. If they are compromised, the security of SSL/TLS is compromised as well. In that case, intruders could do as they like with client hosts, such as replace certificates in web browsers, install keyloggers, change /etc/hosts to redirect web requests to bogus web servers, or even steal client certificates if they they have been marked as "exportable."

    Therefore, if the client machines are under our administrative domain, we need to take great care with their security. Enabling a personal firewall, antivirus/antispyware software, and turning on automatic Windows updates should be the absolute minimum. Most importantly, web browser versions should be always up-to-date.

    It is also recommended that one apply the following options (related to SSL/TLS) to the web browser configuration:

    • checking for a publisher's certificate revocation should be enabled
    • checking for any server certificate revocation should be enabled
    • encrypted server pages should not be stored in the cache
    • the use of SSLv2.0 should be disabled, and only TLSv1.0 and SSLv3.0 should remain enabled
    • the displaying of warnings about invalid web servers certificates should be enabled
  • Using the same Session IDs / cookies for SSL and HTTP

    It is possible to have an Apache configuration that accepts both HTTP and HTTPS requests on the same server, such as an information website accessible via HTTP, and a transaction part accessible via HTTPS. In this case, the we must be very careful in our web application not to use the same session IDs / cookies for both protocols. Otherwise, an intruder can sniff the HTTP traffic between web server and victim, and can try to use session IDs to get access to authorized part of web application via SSL.


This article closes the series of articles devoted to configuring Apache 2.0 with SSL/TLS support. It has been presented how to set up SSL/TLS protocol to achieve maximum security and optimal performance. It has been also shown how to create and revoke certificates, and how to use them in practice.

Although the series has covered most important aspects of Public Key Infrastructure for use with SSL web servers, including creating, installing using and revoking certificates, we did not exhaust the subject related to PKI. On the contrary, only the real basics of PKI have been presented. Readers interested in further reading on this topic are encouraged to take a look at the documents created by the PKIX Working Group, or the OpenCA PKI Development Project, where the latter is quite a robust and open-source Certification Authority.

No comments: