Wandering Thoughts archives

2008-09-30

The consequences of your SSL certificate getting compromised

Suppose that your web server's SSL certificate's private key is compromised and stolen by an attacker. Further suppose that you detect this and replace the compromised certificate with a new one. Now, here's a question: what damage can the attacker still do with their stolen certificate?

  • they can impersonate your web server. In theory they can only do this until their stolen certificate expires; in practice, I think that many users ignore 'expired certificate' errors because they are relatively common.

    (SSL certificate revocation would protect against this, if it worked.)

  • they may be able to decrypt any past SSL conversations that they've already captured, depending on what cipher was used.

The attacker cannot decrypt future SSL conversations, because those will be protected by your new certificate even if the SSL conversation uses a cipher without forward secrecy.

If the attacker compromised a wildcard certificate they can imitate any of your web servers, regardless of what certificate the web server normally uses, but can only potentially decrypt past conversations from web servers that used the wildcard certificate. (Of course, if you went to the bother and expense of getting a wildcard certificate, you're probably going to use it on all of your web servers.)

I believe that the only relatively certain way of stopping an attacker's use of the stolen certificate is to remove the name from your DNS. Of course, this often presents certain difficulties.

(It is not safe to turn the compromised name into a website that just redirects people to the new name, because that means that users are still using the old name; the attacker could interpose their fake version and just not redirect to your new name.)

web/CertCompromiseConsequences written at 22:51:45; Add Comment

Using Python to find out what cipher a SSL server is using

I have a new-found interest in finding out what ciphers various SSL servers around here are using in some easy and convenient way. Doing this in Perl is easy (there's an example here), but I prefer Python. I'd normally use pyOpenSSL, my favorite Python OpenSSL module, but unfortunately it doesn't (currently) have an interface to the necessary 'get the connection's cipher' OpenSSL routine, and there's no visible substitute for it.

(While the .get_cipher_list() method of Connection objects looks tempting, I discovered through some experimentation that it doesn't return anything like the list of ciphers that are common between the server and the client.)

However, all is not lost; it turns out that the commonly available M2Crypto module does have enough functionality to do this. In fact, it's pretty easy, and so here is sample code to do it (omitting error checking, as usual):

from M2Crypto import SSL
def printcipher(host, port):
    ctx = SSL.Context('tlsv1')
    s = SSL.Connection(ctx)

    # No, really, all I care is that you successfully
    # negotiated SSL, especially as some of your checks
    # are broken.
    s.postConnectionCheck = None
    s.connect((host, port))

    # The space at the end is [sic]
    if s.get_state() == "SSLOK ":
        c = s.get_cipher()
        cp = c.name()
        print "Cipher %s, %d bits" % (cp, len(c))
        if cp.startswith("DHE-") or cp.startswith("EDH-"):
            print "forward secrecy: yes"
        else:
            print "forward secrecy: probably not"
    s.close()

This code works for protocols that start SSL/TLS immediately on connection, such as https or imaps. Extension to protocols that have a plaintext conversation and then start TLS (such as ESTMP with STARTTLS) is left as an exercise for the sufficiently interested.

I believe but am not sure that there is no point in asking for anything except TLS v1; the OpenSSL ciphers(1) manpage suggests that SSLv3 and TLSv1 have the same set of ciphers. (Presumably this is TLS v1.0.)

(Note that M2Crypto is pretty under-documented; reading the source is not so much recommended as required. Fortunately it comes with a large set of examples.)

python/FindingSSLCipher written at 00:41:06; Add Comment


Page tools: See As Normal.
Search:
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.