From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: "Kelly Dean" Newsgroups: gmane.emacs.devel Subject: Emacs package manager vulnerable to replay attacks Date: Tue, 30 Dec 2014 10:42:16 +0000 Message-ID: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: ger.gmane.org 1419936261 18364 80.91.229.3 (30 Dec 2014 10:44:21 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Tue, 30 Dec 2014 10:44:21 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue Dec 30 11:44:16 2014 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1Y5uHf-0004V6-3t for ged-emacs-devel@m.gmane.org; Tue, 30 Dec 2014 11:44:15 +0100 Original-Received: from localhost ([::1]:36477 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y5uHe-0006VG-CZ for ged-emacs-devel@m.gmane.org; Tue, 30 Dec 2014 05:44:14 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:40921) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y5uHP-0006UC-8P for emacs-devel@gnu.org; Tue, 30 Dec 2014 05:44:01 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Y5uHL-00013j-3b for emacs-devel@gnu.org; Tue, 30 Dec 2014 05:43:59 -0500 Original-Received: from relay4-d.mail.gandi.net ([2001:4b98:c:538::196]:53053) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y5uHK-00013d-Qd for emacs-devel@gnu.org; Tue, 30 Dec 2014 05:43:55 -0500 Original-Received: from mfilter12-d.gandi.net (mfilter12-d.gandi.net [217.70.178.129]) by relay4-d.mail.gandi.net (Postfix) with ESMTP id 9CD33172089 for ; Tue, 30 Dec 2014 11:43:53 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at mfilter12-d.gandi.net Original-Received: from relay4-d.mail.gandi.net ([217.70.183.196]) by mfilter12-d.gandi.net (mfilter12-d.gandi.net [10.0.15.180]) (amavisd-new, port 10024) with ESMTP id GTvFFbzkpgoW for ; Tue, 30 Dec 2014 11:43:52 +0100 (CET) X-Originating-IP: 162.248.99.114 Original-Received: from localhost (114-99-248-162-static.reverse.queryfoundry.net [162.248.99.114]) (Authenticated sender: kelly@prtime.org) by relay4-d.mail.gandi.net (Postfix) with ESMTPSA id 6667917208B for ; Tue, 30 Dec 2014 11:43:44 +0100 (CET) X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:4b98:c:538::196 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:180884 Archived-At: Remove your ~/.emacs.d/elpa/ directory, and start 24.4. Use the default of '(("gnu" . "http://elpa.gnu.org/packages/")) for package-archives. Do M-x list-packages, which will download the archive metadata (http://elpa.gnu.org/packages/archive-contents and its sig file), verify the sig, and generate archive-contents.signed which indicates successful verification. Then: mkdir /tmp/localarch; cd /tmp/localarch cp ~/.emacs.d/elpa/archives/gnu/* . # archive-contents and archive-contents.signed wget http://elpa.gnu.org/packages/undo-tree-0.6.5.el # Currently latest in elpa wget http://elpa.gnu.org/packages/undo-tree-0.6.5.el.sig Now in Emacs, do (setq package-archives '(("gnu" . "/tmp/localarch/"))) Undo-tree 0.6.7 doesn't exist yet, but let's pretend that it does, and it fixes a hypothetical security vulnerability in 0.6.5, and the update has been uploaded to elpa. (Skipping 0.6.6 for this example since it does exist, just not in elpa.) To simulate this, edit /tmp/localarch/archive-contents, find the entry for undo-tree, and change the (0 6 5) to (0 6 7). Your modified file will no longer verify with http://elpa.gnu.org/packages/archive-contents.sig, but that's ok since you already have /tmp/localarch/archive-contents.signed. Now, to simulate a package replay attack, rename undo-tree-0.6.5.el to undo-tree-0.6.7.el, and undo-tree-0.6.5.el.sig to undo-tree-0.6.7.el.sig. Then do M-x list-packages again, then install undo-tree 0.6.7. It installs successfully, meaning you've tricked Emacs into installing the vulnerable version of the package even though archive-contents lists the fixed version. For a live attack, first retrieve all packages and their sig files from elpa, then wait for a vulnerability to be discovered and fixed in one of them, e.g. undo-tree 0.6.5. Allow your victim to run list-packages to download the new archive-contents (which lists the fixed undo-tree 0.6.7) and to verify it using the new archive-contents.sig. Then when he tries to download undo-tree-0.6.7.el and undo-tree-0.6.7.el.sig, intercept his connection and give him the content of undo-tree-0.6.5.el and undo-tree-0.6.5.el.sig, so that his Emacs saves the old content using the new names. His Emacs will successfully verify the signature because it is authentic; you retrieved authentic (but now stale) packages and signatures in your first step. His Emacs will then install the stale package because the version number embedded in the filename matches the version number specified in the new archive-contents file. The attack also works for already-installed packages when new versions are published; you can deliver stale data when the victim tries to upgrade. To solve the problem above, simply include a hash of the package content in the package's record in archive-contents, rather than only including the package name and version number in that file as Emacs currently does. This solution also happens to make per-package signatures from the elpa key superfluous, so you can remove that feature from Emacs and remove those signature files from elpa for the sake of simplicity, and use the elpa key only to sign the archive-contents file. (Of course, per-commit (not just per-package) signatures from authors would still be useful, so that users don't have to trust the elpa keyholder alone, but that's a separate issue. Emacs should barf if a package hash doesn't verify, regardless of whether any signatures verify.) Package replay attacks could be prevented without putting hashes in archive-contents, by instead verifying that the version number listed in archive-contents matches the version number listed in the package itself, if version numbers were never reused for different versions of packages. But there is at least one package (undo-tree) that does re-use version numbers, so hashes are still necessary. Hashes also prevent elpa itself from reusing version numbers; forcing elpa to issue a new archive-contents whenever it lists a new version of any package makes it more conspicuous that something changed, and making the historical record clear closes off one particular method of attack if the elpa key is compromised. After the problem of package replay attacks is solved, you can still attack by replaying not only packages, but also the metadata (i.e. the archive-contents and archive-contents.sig files). To solve this problem, include a timestamp of archive-contents in that file itself (so that the signature depends on the timestamp), and have Emacs ignore any new archive-contents that's older than the latest valid one that Emacs has already seen or is older than some specified limit (IIRC Debian's apt-get uses a 10-day limit). For details on replay attacks, see the 2008 publication https://www.cs.arizona.edu/stork/packagemanagersecurity/attacks-on-package-managers.html Another attack is the endless-data attack; I haven't checked whether Emacs is vulnerable. See https://www.cs.arizona.edu/stork/packagemanagersecurity/otherattacks.html But since Emacs signs its repository metadata, it appears it is not vulnerable to any of the other attacks described on that page. In addition to recording hashes, also record the length of the content; it's convenient for early detection of endless-data attacks and of misconfigurations. One final feature that isn't necessary for preventing any of the vulnerabilities above, but still is helpful to make the historical record even more clear, is to include in each version of archive-contents a hash (and length) of the previous version of that file. This further constrains an attacker who has compromised the elpa key; he can still launch attacks, but it's harder to keep the attacks secret for very long, since he's forced to cause a fork in what's supposed to be a linear hash chain. Fortunately, all four of these features (package hashes, content length, archive timestamps, and archive hash chaining) are straightforward to implement.