[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Emacs package manager vulnerable to replay attacks

From: Kelly Dean
Subject: Emacs package manager vulnerable to replay attacks
Date: Tue, 30 Dec 2014 10:42:16 +0000

Remove your ~/.emacs.d/elpa/ directory, and start 24.4.
Use the default of '(("gnu" . "http://elpa.gnu.org/packages/";)) for 
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 
mkdir /tmp/localarch; cd /tmp/localarch
cp ~/.emacs.d/elpa/archives/gnu/* . # archive-contents and 
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 
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 

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

Another attack is the endless-data attack; I haven't checked whether Emacs is 
vulnerable. See
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.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]