This tip describes how to configure an Apache 2.x SSL server in a manner that is unusually resilient to attack. It assumes that you already have a working SSL server, and know how to use the various Apache configuration contexts (server config, virtual host, directory, etc.). Note: I did not test the syntax of the commands in this tip explicitly on a test server. There may be mistakes, but getting it to work should be fairly straightforward.
First, some best-practices for your server configuration:
Reading the documentation for mod_ssl will help understand what's going on. Looking at the SSLCipherSuite directive, it tells us that the Apache default ciphers' list is:
First, some best-practices for your server configuration:
ServerTokens Prod
ServerSignature Off
Read the rest of the hint for the interesting part.Reading the documentation for mod_ssl will help understand what's going on. Looking at the SSLCipherSuite directive, it tells us that the Apache default ciphers' list is:
SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP
So the first thing we do is disable ciphers at the server context with:
SSLCipherSuite -ALL
This, of course, makes the server refuse to talk to anything! Very secure, but probably not what you want. Reading the docs for SSLCipherSuite more carefully, we see:
Notice that this directive can be used both in per-server and per-directory context. In per-server context, it applies to the standard SSL handshake when a connection is established. In per-directory context, it forces a SSL renegotation with the reconfigured Cipher Suite after the HTTP request was read, but before the HTTP response is sent.So now we go in and enable a select set of ciphers for a particular area with say:
<Directory "/disc2/htdocs/mysecretplace/">
SSLCipherSuite HIGH
SSLRequireSSL
</Directory>
Then restart Apache and test your configuration with openssl s_client:
echo -e 'GET / HTTP/1.0nn' | openssl s_client -state –connect server:443
echo -e 'GET /mysecretplace/ HTTP/1.0nn' | openssl s_client -state –connect server:443
The first request should fail with a nasty looking SSL error. If you read the output, you'll see that the server is requesting a "change cipher spec� and then failing. The second request should work OK. How is this better than configuring my server to use user credentials through AuthType Basic and require valid-user? - Attackers looking for SSL web servers on port 443 will probably miss you. nmap -sV, for instance, doesn't figure out that it's an SSL service. Even if they do figure it out, they won't get back a Server: header unless their request is one of your exposed URL paths.
- Web server attack tools (Nikto, etc.) fall on their face terribly when things fail at the SSL layer. The output of curl –visk https://server/, after applying the above changes, shows how non-communicative the server is. Tools that attempt to guess valid URLs or test for specific vulnerabilities will fail in an equally severe fashion.
- You can publish HTTPS URLs and users won't have to authenticate. A good example is if you have an SSL server that handles form transactions via POST. You need only expose say https://server/secure/process/ through a Directory directive, and the user is unaware of the SSL defense. Yet if someone wants to poke at your server to any extent, they will have to know or discover which URLs you are exposing.
- Use client side SSL certificates.
- Have a more complex SSLRequire
- Require that REQUEST_METHOD be say POST
- Require a particular HTTP_REFERER so that only links from particular sites are valid
- Require HTTP_HOST to be your DNS name so that requests issued by IP address alone are rejected
- Require HTTP_HOST to be some unusual value, and have your users put an entry for this name into their hosts file with your IP address
- It should be possible to use either of the last two techniques above on your document root and get an OK level of protection, but remember that an attacker can generally get your DNS name from the Common Name in your SSL certificate.
•
[10,575 views]

