On Sun, Mar 01, 2015 at 08:21:17PM +0000, Colin Watson wrote: > On Sun, Mar 01, 2015 at 01:21:32PM +0100, Moritz Muehlenhoff wrote: > > This has been assigned CVE-2015-2157: > > http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/private-key-not-wiped-2.html > > Thanks. Fixed in unstable and unblocked. I'd like to upload the > attached debdiff to stable-security; would that be OK? I can also work > on a squeeze-lts upload once this is done.
That'll teach me to send mail before testing. Here's a corrected version that actually builds. -- Colin Watson [cjwat...@debian.org]
diff -Nru putty-0.62/debian/changelog putty-0.62/debian/changelog --- putty-0.62/debian/changelog 2013-08-07 10:11:20.000000000 +0100 +++ putty-0.62/debian/changelog 2015-03-01 21:04:32.000000000 +0000 @@ -1,3 +1,14 @@ +putty (0.62-9+deb7u2) stable-security; urgency=high + + * Backport from upstream: + - MATTA-2015-002: Enforce acceptable range for Diffie-Hellman server + value. + - Fix an erroneous length field in SSH-1 key load. + - CVE-2015-2157: Fix failure to clear sensitive private key information + from memory (closes: #779488). + + -- Colin Watson <cjwat...@debian.org> Sun, 01 Mar 2015 21:04:30 +0000 + putty (0.62-9+deb7u1) stable-security; urgency=high * CVE-2013-4206: Buffer underrun in modmul could corrupt the heap. diff -Nru putty-0.62/debian/patches/enforce-dh-range.patch putty-0.62/debian/patches/enforce-dh-range.patch --- putty-0.62/debian/patches/enforce-dh-range.patch 1970-01-01 01:00:00.000000000 +0100 +++ putty-0.62/debian/patches/enforce-dh-range.patch 2015-03-01 21:04:03.000000000 +0000 @@ -0,0 +1,77 @@ +Description: Enforce acceptable range for Diffie-Hellman server value + Florent Daigniere of Matta points out that RFC 4253 actually + _requires_ us to refuse to accept out-of-range values, though it isn't + completely clear to me why this should be a MUST on the receiving end. + . + Matta considers this to be a security vulnerability, on the grounds + that if a server should accidentally send an obviously useless value + such as 1 then we will fail to reject it and agree a key that an + eavesdropper could also figure out. Their id for this vulnerability is + MATTA-2015-002. +Origin: backport, http://tartarus.org/~simon-git/gitweb/?p=putty.git;a=commitdiff;h=174476813f0ed94337aecc3e2d13a202a1dc2fa8 +Last-Update: 2015-03-01 + +Index: b/ssh.c +=================================================================== +--- a/ssh.c ++++ b/ssh.c +@@ -6007,6 +6007,13 @@ + } + ssh_pkt_getstring(pktin, &s->sigdata, &s->siglen); + ++ { ++ const char *err = dh_validate_f(ssh->kex_ctx, s->f); ++ if (err) { ++ bombout(("key exchange reply failed validation: %s", err)); ++ crStop(0); ++ } ++ } + s->K = dh_find_K(ssh->kex_ctx, s->f); + + /* We assume everything from now on will be quick, and it might +Index: b/ssh.h +=================================================================== +--- a/ssh.h ++++ b/ssh.h +@@ -470,6 +470,7 @@ + void *dh_setup_gex(Bignum pval, Bignum gval); + void dh_cleanup(void *); + Bignum dh_create_e(void *, int nbits); ++const char *dh_validate_f(void *handle, Bignum f); + Bignum dh_find_K(void *, Bignum f); + + int loadrsakey(const Filename *filename, struct RSAKey *key, +Index: b/sshdh.c +=================================================================== +--- a/sshdh.c ++++ b/sshdh.c +@@ -219,6 +219,29 @@ + } + + /* ++ * DH stage 2-epsilon: given a number f, validate it to ensure it's in ++ * range. (RFC 4253 section 8: "Values of 'e' or 'f' that are not in ++ * the range [1, p-1] MUST NOT be sent or accepted by either side." ++ * Also, we rule out 1 and p-1 too, since that's easy to do and since ++ * they lead to obviously weak keys that even a passive eavesdropper ++ * can figure out.) ++ */ ++const char *dh_validate_f(void *handle, Bignum f) ++{ ++ struct dh_ctx *ctx = (struct dh_ctx *)handle; ++ if (bignum_cmp(f, One) <= 0) { ++ return "f value received is too small"; ++ } else { ++ Bignum pm1 = bigsub(ctx->p, One); ++ int cmp = bignum_cmp(f, pm1); ++ freebn(pm1); ++ if (cmp >= 0) ++ return "f value received is too large"; ++ } ++ return NULL; ++} ++ ++/* + * DH stage 2: given a number f, compute K = f^x mod p. + */ + Bignum dh_find_K(void *handle, Bignum f) diff -Nru putty-0.62/debian/patches/private-key-not-wiped-2.patch putty-0.62/debian/patches/private-key-not-wiped-2.patch --- putty-0.62/debian/patches/private-key-not-wiped-2.patch 1970-01-01 01:00:00.000000000 +0100 +++ putty-0.62/debian/patches/private-key-not-wiped-2.patch 2015-03-01 21:04:19.000000000 +0000 @@ -0,0 +1,60 @@ +Description: Add some missing memsets and sfrees + The absence of these could have prevented sensitive private key + information from being properly cleared out of memory that PuTTY tools + had finished with. + . + Thanks to Patrick Coleman for spotting this and sending a patch. +Origin: backport, http://tartarus.org/~simon-git/gitweb/?p=putty.git;a=commitdiff;h=65f69bca7363ceceeac515ae2a82b8f8adc6404d +Bug: http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/private-key-not-wiped-2.html +Bug-Debian: http://bugs.debian.org/779488 + +Index: b/sshpubk.c +=================================================================== +--- a/sshpubk.c ++++ b/sshpubk.c +@@ -839,6 +839,7 @@ + goto error; + } + sfree(public_blob); ++ memset(private_blob, 0, private_blob_len); + sfree(private_blob); + sfree(encryption); + if (errorstr) +@@ -859,8 +860,10 @@ + sfree(mac); + if (public_blob) + sfree(public_blob); +- if (private_blob) +- sfree(private_blob); ++ if (private_blob) { ++ memset(private_blob, 0, private_blob_len); ++ sfree(private_blob); ++ } + if (errorstr) + *errorstr = error; + return ret; +@@ -1144,8 +1147,14 @@ + } + + fp = f_open(*filename, "w", TRUE); +- if (!fp) +- return 0; ++ if (!fp) { ++ sfree(pub_blob); ++ memset(priv_blob, 0, priv_blob_len); ++ sfree(priv_blob); ++ memset(priv_blob_encrypted, 0, priv_blob_len); ++ sfree(priv_blob_encrypted); ++ return 0; ++ } + fprintf(fp, "PuTTY-User-Key-File-2: %s\n", key->alg->name); + fprintf(fp, "Encryption: %s\n", cipherstr); + fprintf(fp, "Comment: %s\n", key->comment); +@@ -1162,6 +1171,7 @@ + sfree(pub_blob); + memset(priv_blob, 0, priv_blob_len); + sfree(priv_blob); ++ memset(priv_blob_encrypted, 0, priv_blob_len); + sfree(priv_blob_encrypted); + return 1; + } diff -Nru putty-0.62/debian/patches/series putty-0.62/debian/patches/series --- putty-0.62/debian/patches/series 2013-08-07 10:09:08.000000000 +0100 +++ putty-0.62/debian/patches/series 2015-03-01 21:04:19.000000000 +0000 @@ -6,3 +6,6 @@ vuln-bignum-division-by-zero.patch private-key-not-wiped.patch proactive-tightening.patch +enforce-dh-range.patch +ssh-1-key-load-length.patch +private-key-not-wiped-2.patch diff -Nru putty-0.62/debian/patches/ssh-1-key-load-length.patch putty-0.62/debian/patches/ssh-1-key-load-length.patch --- putty-0.62/debian/patches/ssh-1-key-load-length.patch 1970-01-01 01:00:00.000000000 +0100 +++ putty-0.62/debian/patches/ssh-1-key-load-length.patch 2015-03-01 21:04:19.000000000 +0000 @@ -0,0 +1,22 @@ +Description: Fix an erroneous length field in SSH-1 key load + We incremented buf by a few bytes, so we must decrement the + corresponding length by the same amount, or else makekey() could + overrun. + . + Thanks to Patrick Coleman for the patch. +Origin: upstream, http://tartarus.org/~simon-git/gitweb/?p=putty.git;a=commitdiff;h=1f757928051b6d6ff231b2265bad2d263b0fe3ea +Last-Update: 2015-03-01 + +Index: b/sshpubk.c +=================================================================== +--- a/sshpubk.c ++++ b/sshpubk.c +@@ -67,7 +67,7 @@ + i += 4; + + /* Now the serious stuff. An ordinary SSH-1 public key. */ +- i += makekey(buf + i, len, key, NULL, 1); ++ i += makekey(buf + i, len - i, key, NULL, 1); + if (i < 0) + goto end; /* overran */ +