all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Re: bug#19479: Disclaimer is now on file at FSF
@ 2015-02-24 18:11 Glenn Morris
  2015-02-24 23:02 ` Kelly Dean
  0 siblings, 1 reply; 20+ messages in thread
From: Glenn Morris @ 2015-02-24 18:11 UTC (permalink / raw)
  To: Kelly Dean; +Cc: 19479, Emacs developers


So, I don't want to get into this discussion, but I've always assumed
that disclaimers do not/cannot apply to future changes. I asked
assign@gnu.org, and they confirmed "Disclaimers are not valid for future
contributions".

I mention this because AFAICS you are sending new patches.

Your disclaimer is dated 2015-1-8. AFAICS we cannot apply anything after
that. Someone should also check the several patches from you that have
been applied recently to make sure they originated before this date.

Sorry, I don't have time/inclination to discuss special cases.
Maybe you want to take it up with rms and/or assign@gnu.



^ permalink raw reply	[flat|nested] 20+ messages in thread
* bug#19479: [PATCH] Re: bug#19479: Package manager vulnerable
  2015-01-08  3:31 bug#19479: [PATCH] " Kelly Dean
@ 2015-01-08  3:44 Glenn Morris
  2015-01-08  5:29 ` Kelly Dean
  0 siblings, 1 reply; 20+ messages in thread
From: Glenn Morris @ 2015-01-08  3:44 UTC (permalink / raw)
  To: Kelly Dean; +Cc: 19479


I appreciate the spirit of wanting to provide a patch, but unless you
have changed your position on the Emacs copyright assignment, I don't
see that this patch can be used by Emacs.

(Ref: http://debbugs.gnu.org/14492#19)





^ permalink raw reply	[flat|nested] 20+ messages in thread
* bug#19479: [PATCH] Re: bug#19479: Package manager vulnerable
  2015-01-05  2:16       ` Stefan Monnier
@ 2015-01-08  3:31 Kelly Dean
  2015-01-08  5:50 ` bug#19536: [PATCH] package-upload-buffer-internal fails for tar files Stefan Monnier
  -1 siblings, 1 reply; 20+ messages in thread
From: Kelly Dean @ 2015-01-08  3:31 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: 19479

[-- Attachment #1: Type: text/plain, Size: 2116 bytes --]

Stefan Monnier wrote:
> > If filenames include version numbers and the version numbers are never
> > reused,
>
> The ELPA system in general does not enforce that.  But the GNU ELPA
> scripts do, and other ELPA servers work in a way that should generally
> make sure this is also the case.

But having security rely on that makes it easier than necessary to accidentally open a window of vulnerability by failing to enforce that constraint. It's a brittle solution.

>> then your solution does prevent package replay attacks. Since Emacs
>> packages already include a Version header (and the package name), you could
>> actually do your proposed verification using that header, without changing
>> the way signatures are currently made, which is a solution I addressed in my
>> original emacs-devel message.
>
> Indeed, I realized this just after I sent my message.
> So we can fix this problem simply by changing package.el so as to check
> that the name&version of the downloaded file match the name&version
> contained therein.
> Patch welcome.

Ok, but as I explained in my original message, that solution still makes the attacker's job easier than necessary in some cases. Verifying the hash is a more robust solution than verifying the version number, so my patch below verifies the hash.

This is forward compatible. You can install this now and start putting archive-contents with hashes on elpa (and melpa and marmalade), and old clients will simply ignore the hashes and operate as usual.

BTW, one happy side effect of properly fixing this vulnerability is eliminating melpa's incentive to mangle package version numbers (they're mangled apparently to deal with the problem of package maintainers reusing version numbers).

> It should be fairly easy to add a timestamp in there without
> causing any backward incompatibility.

Unfortunately, I don't see how to add timestamps to archive-contents without breaking old clients, so the metadata replay vulnerability will have to remain open until you decide how to handle the compatibility problem. My patch here only fixes the package replay vulnerability.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: package-replay-vuln.patch --]
[-- Type: text/x-diff, Size: 3425 bytes --]

--- emacs-24.4/lisp/emacs-lisp/package.el
+++ emacs-24.4/lisp/emacs-lisp/package.el
@@ -314,6 +314,11 @@
 
 (defvar package--default-summary "No description available.")
 
+(defvar package-hashfun 'sha256 "Function for secure hashing.")
+
+(defvar package-acceptable-hashfuns '(sha256)
+  "Past and current `package-hashfun' functions that are still secure.")
+
 (cl-defstruct (package-desc
                ;; Rename the default constructor from `make-package-desc'.
                (:constructor package-desc-create)
@@ -843,6 +848,20 @@
                          (epg-context-result-for context 'verify)))
         good-signatures))))
 
+(defun package--check-size (pkg-desc)
+  (eq (cdr (assoc :size (package-desc-extras pkg-desc)))
+      (pcase (package-desc-kind pkg-desc)
+	(`single (string-bytes (buffer-string)))
+	(`tar (buffer-size)) ; Because insert-file-contents mangled the literal
+	(kind (error "Unknown package kind: %s" kind)))))
+
+(defun package--check-hash (pkg-desc)
+  (let* ((x (cdr (assoc :hash (package-desc-extras pkg-desc))))
+	 (hashfun (car x)) ; Avoid Git's shortsightedness
+	 (hash (cadr x)))
+    (and (memq hashfun package-acceptable-hashfuns)
+	 (string= hash (secure-hash hashfun (current-buffer))))))
+
 (defun package-install-from-archive (pkg-desc)
   "Download and install a tar package."
   (let* ((location (package-archive-base pkg-desc))
@@ -859,6 +878,10 @@
 	    (unless (eq package-check-signature 'allow-unsigned)
 	      (error "Unsigned package: `%s'"
 		     (package-desc-name pkg-desc)))))
+      (unless (package--check-size pkg-desc)
+	(error "File size not correct: %s" (package-desc-name pkg-desc)))
+      (unless (package--check-hash pkg-desc)
+	(error "Failed to verify hash: %s" (package-desc-name pkg-desc)))
       (package-unpack pkg-desc))
     ;; Here the package has been installed successfully, mark it as
     ;; signed if appropriate.
@@ -1172,7 +1195,10 @@
            (package--prepare-dependencies
             (package-read-from-string requires-str)))
        :kind 'single
-       :url homepage))))
+       :url homepage
+       :size (string-bytes (buffer-string))
+       :hash (list package-hashfun
+		   (secure-hash package-hashfun (current-buffer)))))))
 
 (declare-function tar-get-file-descriptor "tar-mode" (file))
 (declare-function tar--extract "tar-mode" (descriptor))
@@ -1184,7 +1210,10 @@
   (let* ((dir-name (file-name-directory
                     (tar-header-name (car tar-parse-info))))
          (desc-file (package--description-file dir-name))
-         (tar-desc (tar-get-file-descriptor (concat dir-name desc-file))))
+         (tar-desc (tar-get-file-descriptor (concat dir-name desc-file)))
+	 (size (buffer-size tar-data-buffer))
+	 (hash (list package-hashfun
+		     (secure-hash package-hashfun tar-data-buffer))))
     (unless tar-desc
       (error "No package descriptor file found"))
     (with-current-buffer (tar--extract tar-desc)
@@ -1196,7 +1225,8 @@
                       (error "Can't find define-package in %s"
                              (tar-header-name tar-desc))
                     (apply #'package-desc-from-define
-                           (append (cdr pkg-def-parsed))))))
+                           (append (cdr pkg-def-parsed)
+				   (list :size size :hash hash))))))
             (setf (package-desc-kind pkg-desc) 'tar)
             pkg-desc)
         (kill-buffer (current-buffer))))))

^ permalink raw reply	[flat|nested] 20+ messages in thread
* Emacs package manager vulnerable to replay attacks
@ 2014-12-30 10:42 Kelly Dean
  2015-01-01 12:38 ` bug#19479: Package manager vulnerable Kelly Dean
  0 siblings, 1 reply; 20+ messages in thread
From: Kelly Dean @ 2014-12-30 10:42 UTC (permalink / raw)
  To: emacs-devel

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.



^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2020-09-08  8:10 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <E1Y8Bor-0003yH-Mu@fencepost.gnu.org>
2015-01-06  6:38 ` bug#19479: Package manager vulnerable Kelly Dean
2015-01-07  4:27   ` Richard Stallman
2015-02-24 18:11 bug#19479: Disclaimer is now on file at FSF Glenn Morris
2015-02-24 23:02 ` Kelly Dean
2015-02-25 21:09   ` Glenn Morris
2017-09-02 12:24     ` Eli Zaretskii
  -- strict thread matches above, loose matches on Subject: below --
2015-01-08  3:44 bug#19479: [PATCH] Re: bug#19479: Package manager vulnerable Glenn Morris
2015-01-08  5:29 ` Kelly Dean
2015-01-08 14:39   ` Stefan Monnier
2015-01-08 21:06     ` Kelly Dean
2015-01-09  2:37       ` Stefan Monnier
2015-01-08  3:31 bug#19479: [PATCH] " Kelly Dean
2015-01-08  5:50 ` bug#19536: [PATCH] package-upload-buffer-internal fails for tar files Stefan Monnier
2015-01-08 11:40   ` bug#19479: Package manager vulnerable Kelly Dean
2014-12-30 10:42 Emacs package manager vulnerable to replay attacks Kelly Dean
2015-01-01 12:38 ` bug#19479: Package manager vulnerable Kelly Dean
2015-01-04 20:00   ` Stefan Monnier
2015-01-05  1:11     ` Kelly Dean
2015-01-05  2:16       ` Stefan Monnier
2017-09-03  1:10   ` Glenn Morris
2019-10-04  9:49   ` Stefan Kangas
2020-05-06  0:55     ` Noam Postavsky
2020-09-06 23:59       ` Stefan Kangas
2020-09-07 14:14         ` Noam Postavsky
2020-09-07 18:11           ` Stefan Kangas
2020-09-07 17:19   ` Stefan Kangas
2020-09-07 23:54     ` Noam Postavsky
2020-09-08  8:10       ` Stefan Kangas

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.