[Twisted-Python] Foolscap-0.2.7 released, Foolscap vs. debian openssl bug

Brian Warner warner at lothar.com
Thu May 22 16:08:38 EDT 2008

I released Foolscap-0.2.7 the other week, just a few days after the release
of 0.2.6 . This fixes a brown-paper-bag bug in 0.2.6 that prevented the
'flogtool' utility from running at all.

Tarballs can be obtained from foolscap.lothar.com and from PyPI. All releases
are signed by my GPG public key: 0x1514A7BD.


For documentation, bugs, and patches, please visit
http://foolscap.lothar.com/trac .

== Debian OpenSSL Bugs and Foolscap ==

As you've probably heard[1], last week the debian project published a
security advisory that described how the openssl package has been using a
18-ish-bit random number generator for the last two years. As a result, keys
and certificates generated by the affected versions (or used for DSA
signatures by affected versions) should be considered compromised and
immediately replaced. This affects the last 3 or 4 Ubuntu releases too
(Dapper was correct, Edgy was broken). All affected releases now have fixed
versions available for download, and obviously everyone using an affected
release needs to upgrade immediately.

 [1]: http://lists.debian.org/debian-security-announce/2008/msg00152.html

Since the bug affected key generation, keys which were created by the broken
versions will remain broken even after openssl itself is upgraded. The Debian
and Ubuntu projects have released tools to detect weak ssh keys that were
generated by these versions and disable them. Other projects (including
Foolscap) use generated keys for various purposes, so the effects of this bug
will linger even after openssl has been fixed.

How does this affect Foolscap? The short answer: Weak keys generated by the
broken versions of openssl will enable a man-in-the-middle attack, which (if
successful) would reveal the private swissnums that protect access to
Referenceables. Foolscap users who have created Tubs while they had the
broken versions installed should stop using the associated FURLs and generate
new certificates/FURLs.

The longer answer: There are three things in Foolscap that use random

 1: TubIDs [COMPROMISED]. These are a hash of the public key that corresponds
 to a Tub's private key, and are included in FURLs (as the base32 part
 immediately following the pb:// prefix). This provides protection against a
 man-in-the-middle attack: when connecting to a FURL, the certificate of the
 remote end is compared against the TubID in the FURL, and the connection is
 dropped with extreme prejudice if they do not match. This validation is
 performed before any secrets are passed over the wire.

 2: SwissNums [SAFE]. These are a randomly-generated name for a reference,
 created when tub.registerReference(obj) is called without a name= argument,
 and when a Referenceable is sent over the wire without being explicitly
 registered. They appear at the right-hand end of the FURL, after the last
 slash. Most Referenceables are given these unguessable names, because that
 limits access to parties that have been explicitly granted access. (when
 registerReference() is called with a guessable name, anyone who can guess
 that name will get reference to the given object). The capability-based
 security of foolscap Referenceables depends upon these swissnums remaining

 3: SSL transport sessions [VULNERABLE]. Foolscap runs over SSL, which uses
 random numbers to generate the Diffie-Hellman key agreement parameters. An
 eavesdropper who can guess one of these parameters will be able to determine
 the session key, and can decrypt the remainder of the conversation.

TubIDs are derived from an SSL certificate that OpenSSL generates on demand,
and if the broken version of OpenSSL was used for this purpose, than that
certificate will be guessable. (at some point it would be great to write a
tool that would generate the 128000-ish TubIDs that can be generated by the
broken SSL, to create a blacklist like the ones created by debian/ubuntu for
ssh keys).

So if you've generated a TubID with the broken version of openssl, it is
pretty easy to guess the corresponding private key. This allows an attacker
to mount an undetectable man-in-the-middle attack: if they can convince you
to make your TCP connection to their server instead of the right one, then
they can impersonate the real server, and they'll get to see the unencrypted
conversation (revealing the private swissnums).

Swissnums are generated by calling os.urandom(), which was not affected by
the openssl bug. As long as one of the other problems (man-in-the-middle
attack) doesn't reveal your swissnums to an attacker, access to
Referenceables will remain limited to the parties to whom you've explicitly
granted it (by telling them the swissnum, in a FURL).

Foolscap uses SSL for its encrypted transport, and SSL frequently uses
Diffie-Hellman key negotiation to establish a session key. This key
negotiation process depends upon random numbers, generated by the same buggy
RNG that is used to create keys. So if one of the two ends of an encrypted
session was using the buggy version of openssl, then an attacker may be able
to guess the session key, and thus decrypt the conversation. (note, I'm not a
cryptographer, and I'm not as confident about this attack as I am about the
others). So like the MitM attack, it seems likely that swissnums used by
sessions established during the buggy openssl era may be compromised: an
eavesdropper who recorded that encrypted conversation may be able to decrypt
it after the fact.

Of course, the whole idea of capabilities is to implement the Principle Of
Least Authority: each FURL gives access to a specific Referenceable that will
only do some specific limited task. If an MitM/eavesdropper manages to guess
your supposedly-unguessable swissnums, they'll still only be able to do
whatever the Referenceable will let them do.

So to summarize: if you've been using the buggy openssl libraries, here's
what you need to do:

 1: upgrade openssl
 2: throw out your old FURLs (tell everyone that you've given them to to stop
    using them): this protects clients from the MitM attack.
 3: throw out your old Tub certificates: the certFile= argument to Tub()
    provides a persistent location for this.. just delete that file. This
    prevents clients from ever successfully using the old FURLs to connect
    to your server.
 4: restart the Tub, allowing it to create a new certificate
 5: regenerate and distribute new FURLs

You can also just upgrade openssl (and keep using your old certs and FURLs)
if you're willing to remain vulnerable to man-in-the-middle attacks or
eavesdroppers who have recorded your earlier conversations.


More information about the Twisted-Python mailing list