The compromise of the WordPress 2.1.1 distribution code on its own servers got me thinking about the weaknesses of code distribution security as a general matter. The subject didnt originate with this attack, although it is a stirring reminder of how serious it can be.
On most platforms a distribution file is accompanied by a separate file containing an MD5 hash. Youre supposed to download both, run the hash on your side and compare it to the hash you downloaded and this proves ... what? It certainly proves that the file wasnt corrupted after creation or in transmission, like a CRC back in the days of XMODEM and bulletin boards. But if I can hack into your site and change your file, surely I can create a new MD5 hash file reflective of my version of the file, so checking the MD5 hash doesnt say anything about the integrity of the file.
A better solution would be based on digital signatures, where you could check the publishers public key to see if the file was modified. So how would it work? Heres my first shot at some rules, lacking the sort of consideration that will come as we write up the RFC. Lets call it "Simple File Signing" for now.
The publisher (lets use WordPress as our example) uses a private key to sign a file that users may download. I envision most people using the OpenSSL command line tools to do the PKI (public-key infrastructure) parts of this process. This generates a signature that they put in a file in the same directory as the file that they signed, much as with an MD5 hash. Users download both files.
How do they get the public key to check the signature? The best option here is through HTTP on a special high-number port. (I propose port 5397, which spells "keys" on a telephone.) The specifics of what an HTTP (actually, its probably better to do HTTPS) GET request returns are not important at this point, but they will probably consume the bulk of the time in defining a standard. Lets get back to it in a minute.
In the meantime, in order to check a signature, the client system has to know what domain to check with and how to find the signature file. The default domain to check should be the one from which the file was downloaded, but you should be able to specify a different domain. I suggest prefixing the domain name to the file name. The latest version of WordPress, for example, seems to be at http://wordpress.org/latest.tar.gz. If I were to host this file on eWEEKs site I might name it www.eweek.com/wordpress.org.latest.tar.gz in order to specify that the PKI check should be performed on wordpress.org.
But I would also have to host the signature file, which I suggest should have the same file name with a .sig extension. So my copy of the signature file for WordPress would be named www.eweek.com/wordpress.org.latest.tar.gz.sig.
The simplest version of this system would then have the client system do an HTTP/HTTPS GET from wordpress.org and retrieve a public key. But there is so much more interesting and useful work that can be done between the two systems that it makes sense to enable a two-way conversation, probably through an XML vocabulary. Thanks to Andrew Jaquith, an analyst at the Yankee Group, for pointing out that there is a standard in this space already: XKMS 2.0 (XML Key Management Specification) from the W3C. I havent studied it yet—its a pretty big Web page.
Consider the example of the private key becoming compromised: The publisher would want to convey that information immediately, and a sufficiently rich key retrieval system on port 5397 can do that. It can return a result that says that the key you are requesting belongs to a pair that was compromised and should not be used. In a different example the response might be to return the key and point out that a newer version of the file, with new signatures, exists. In either example the response could include a link to a new version.
Operations like this are always possible through manual twiddling in telnet, but the reality of this process for nearly everyone will involve a Firefox or Internet Explorer extension. Theres no reason why it couldnt be implemented in FTP clients as well.