summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2018-08-17 12:28:26 +0100
committerColin Watson <cjwatson@debian.org>2018-08-17 12:31:27 +0100
commit4641c58a3279f6b118f9562babaa0ee050a38619 (patch)
tree87718b668ec8a737c1729ee568207c2a384f6d61
parentdaf34b85afe25c10fac13e9cff16b25c3e3914e9 (diff)
parentc4ca1497658e0508e8595ad74978c07bc92a18e3 (diff)
Fix user enumeration vulnerability
Apply upstream patch to delay bailout for invalid authenticating user until after the packet containing the request has been fully parsed. Closes: #906236
-rw-r--r--auth2-gss.c9
-rw-r--r--auth2-hostbased.c9
-rw-r--r--auth2-pubkey.c23
-rw-r--r--debian/.git-dpm4
-rw-r--r--debian/changelog8
-rw-r--r--debian/patches/series1
-rw-r--r--debian/patches/upstream-delay-bailout-for-invalid-authenticating-user.patch153
7 files changed, 189 insertions, 18 deletions
diff --git a/auth2-gss.c b/auth2-gss.c
index fd411d3a7..88bc3ae7b 100644
--- a/auth2-gss.c
+++ b/auth2-gss.c
@@ -104,9 +104,6 @@ userauth_gssapi(struct ssh *ssh)
104 u_int len; 104 u_int len;
105 u_char *doid = NULL; 105 u_char *doid = NULL;
106 106
107 if (!authctxt->valid || authctxt->user == NULL)
108 return (0);
109
110 mechs = packet_get_int(); 107 mechs = packet_get_int();
111 if (mechs == 0) { 108 if (mechs == 0) {
112 debug("Mechanism negotiation is not supported"); 109 debug("Mechanism negotiation is not supported");
@@ -137,6 +134,12 @@ userauth_gssapi(struct ssh *ssh)
137 return (0); 134 return (0);
138 } 135 }
139 136
137 if (!authctxt->valid || authctxt->user == NULL) {
138 debug2("%s: disabled because of invalid user", __func__);
139 free(doid);
140 return (0);
141 }
142
140 if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) { 143 if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
141 if (ctxt != NULL) 144 if (ctxt != NULL)
142 ssh_gssapi_delete_ctx(&ctxt); 145 ssh_gssapi_delete_ctx(&ctxt);
diff --git a/auth2-hostbased.c b/auth2-hostbased.c
index 8996f7e05..82a7dcdae 100644
--- a/auth2-hostbased.c
+++ b/auth2-hostbased.c
@@ -67,10 +67,6 @@ userauth_hostbased(struct ssh *ssh)
67 size_t alen, blen, slen; 67 size_t alen, blen, slen;
68 int r, pktype, authenticated = 0; 68 int r, pktype, authenticated = 0;
69 69
70 if (!authctxt->valid) {
71 debug2("%s: disabled because of invalid user", __func__);
72 return 0;
73 }
74 /* XXX use sshkey_froms() */ 70 /* XXX use sshkey_froms() */
75 if ((r = sshpkt_get_cstring(ssh, &pkalg, &alen)) != 0 || 71 if ((r = sshpkt_get_cstring(ssh, &pkalg, &alen)) != 0 ||
76 (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 || 72 (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 ||
@@ -118,6 +114,11 @@ userauth_hostbased(struct ssh *ssh)
118 goto done; 114 goto done;
119 } 115 }
120 116
117 if (!authctxt->valid || authctxt->user == NULL) {
118 debug2("%s: disabled because of invalid user", __func__);
119 goto done;
120 }
121
121 if ((b = sshbuf_new()) == NULL) 122 if ((b = sshbuf_new()) == NULL)
122 fatal("%s: sshbuf_new failed", __func__); 123 fatal("%s: sshbuf_new failed", __func__);
123 /* reconstruct packet */ 124 /* reconstruct packet */
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index 8024b1d6a..a9272b97f 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -89,19 +89,15 @@ userauth_pubkey(struct ssh *ssh)
89{ 89{
90 Authctxt *authctxt = ssh->authctxt; 90 Authctxt *authctxt = ssh->authctxt;
91 struct passwd *pw = authctxt->pw; 91 struct passwd *pw = authctxt->pw;
92 struct sshbuf *b; 92 struct sshbuf *b = NULL;
93 struct sshkey *key = NULL; 93 struct sshkey *key = NULL;
94 char *pkalg, *userstyle = NULL, *key_s = NULL, *ca_s = NULL; 94 char *pkalg = NULL, *userstyle = NULL, *key_s = NULL, *ca_s = NULL;
95 u_char *pkblob, *sig, have_sig; 95 u_char *pkblob = NULL, *sig = NULL, have_sig;
96 size_t blen, slen; 96 size_t blen, slen;
97 int r, pktype; 97 int r, pktype;
98 int authenticated = 0; 98 int authenticated = 0;
99 struct sshauthopt *authopts = NULL; 99 struct sshauthopt *authopts = NULL;
100 100
101 if (!authctxt->valid) {
102 debug2("%s: disabled because of invalid user", __func__);
103 return 0;
104 }
105 if ((r = sshpkt_get_u8(ssh, &have_sig)) != 0 || 101 if ((r = sshpkt_get_u8(ssh, &have_sig)) != 0 ||
106 (r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 || 102 (r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 ||
107 (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0) 103 (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0)
@@ -168,6 +164,11 @@ userauth_pubkey(struct ssh *ssh)
168 fatal("%s: sshbuf_put_string session id: %s", 164 fatal("%s: sshbuf_put_string session id: %s",
169 __func__, ssh_err(r)); 165 __func__, ssh_err(r));
170 } 166 }
167 if (!authctxt->valid || authctxt->user == NULL) {
168 debug2("%s: disabled because of invalid user",
169 __func__);
170 goto done;
171 }
171 /* reconstruct packet */ 172 /* reconstruct packet */
172 xasprintf(&userstyle, "%s%s%s", authctxt->user, 173 xasprintf(&userstyle, "%s%s%s", authctxt->user,
173 authctxt->style ? ":" : "", 174 authctxt->style ? ":" : "",
@@ -184,7 +185,6 @@ userauth_pubkey(struct ssh *ssh)
184#ifdef DEBUG_PK 185#ifdef DEBUG_PK
185 sshbuf_dump(b, stderr); 186 sshbuf_dump(b, stderr);
186#endif 187#endif
187
188 /* test for correct signature */ 188 /* test for correct signature */
189 authenticated = 0; 189 authenticated = 0;
190 if (PRIVSEP(user_key_allowed(ssh, pw, key, 1, &authopts)) && 190 if (PRIVSEP(user_key_allowed(ssh, pw, key, 1, &authopts)) &&
@@ -193,7 +193,6 @@ userauth_pubkey(struct ssh *ssh)
193 authenticated = 1; 193 authenticated = 1;
194 } 194 }
195 sshbuf_free(b); 195 sshbuf_free(b);
196 free(sig);
197 auth2_record_key(authctxt, authenticated, key); 196 auth2_record_key(authctxt, authenticated, key);
198 } else { 197 } else {
199 debug("%s: test pkalg %s pkblob %s%s%s", 198 debug("%s: test pkalg %s pkblob %s%s%s",
@@ -204,6 +203,11 @@ userauth_pubkey(struct ssh *ssh)
204 if ((r = sshpkt_get_end(ssh)) != 0) 203 if ((r = sshpkt_get_end(ssh)) != 0)
205 fatal("%s: %s", __func__, ssh_err(r)); 204 fatal("%s: %s", __func__, ssh_err(r));
206 205
206 if (!authctxt->valid || authctxt->user == NULL) {
207 debug2("%s: disabled because of invalid user",
208 __func__);
209 goto done;
210 }
207 /* XXX fake reply and always send PK_OK ? */ 211 /* XXX fake reply and always send PK_OK ? */
208 /* 212 /*
209 * XXX this allows testing whether a user is allowed 213 * XXX this allows testing whether a user is allowed
@@ -237,6 +241,7 @@ done:
237 free(pkblob); 241 free(pkblob);
238 free(key_s); 242 free(key_s);
239 free(ca_s); 243 free(ca_s);
244 free(sig);
240 return authenticated; 245 return authenticated;
241} 246}
242 247
diff --git a/debian/.git-dpm b/debian/.git-dpm
index 0f4069a2f..40345f1a3 100644
--- a/debian/.git-dpm
+++ b/debian/.git-dpm
@@ -1,6 +1,6 @@
1# see git-dpm(1) from git-dpm package 1# see git-dpm(1) from git-dpm package
260256f28189c3d0650a78e737eb0ca4753478a4b 2c4ca1497658e0508e8595ad74978c07bc92a18e3
360256f28189c3d0650a78e737eb0ca4753478a4b 3c4ca1497658e0508e8595ad74978c07bc92a18e3
4ed6ae9c1a014a08ff5db3d768f01f2e427eeb476 4ed6ae9c1a014a08ff5db3d768f01f2e427eeb476
5ed6ae9c1a014a08ff5db3d768f01f2e427eeb476 5ed6ae9c1a014a08ff5db3d768f01f2e427eeb476
6openssh_7.7p1.orig.tar.gz 6openssh_7.7p1.orig.tar.gz
diff --git a/debian/changelog b/debian/changelog
index 15024f76b..d9de16199 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
1openssh (1:7.7p1-4) UNRELEASED; urgency=high
2
3 * Apply upstream patch to delay bailout for invalid authenticating user
4 until after the packet containing the request has been fully parsed
5 (closes: #906236).
6
7 -- Colin Watson <cjwatson@debian.org> Fri, 17 Aug 2018 12:30:13 +0100
8
1openssh (1:7.7p1-3) unstable; urgency=medium 9openssh (1:7.7p1-3) unstable; urgency=medium
2 10
3 [ Colin Watson ] 11 [ Colin Watson ]
diff --git a/debian/patches/series b/debian/patches/series
index 9f89f7347..e1eb16773 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -25,3 +25,4 @@ seccomp-s390-flock-ipc.patch
25seccomp-getuid-geteuid.patch 25seccomp-getuid-geteuid.patch
26seccomp-s390-ioctl-ep11-crypto.patch 26seccomp-s390-ioctl-ep11-crypto.patch
27upstream-relax-checking-of-authorized_keys-environme.patch 27upstream-relax-checking-of-authorized_keys-environme.patch
28upstream-delay-bailout-for-invalid-authenticating-user.patch
diff --git a/debian/patches/upstream-delay-bailout-for-invalid-authenticating-user.patch b/debian/patches/upstream-delay-bailout-for-invalid-authenticating-user.patch
new file mode 100644
index 000000000..737a9f48d
--- /dev/null
+++ b/debian/patches/upstream-delay-bailout-for-invalid-authenticating-user.patch
@@ -0,0 +1,153 @@
1From c4ca1497658e0508e8595ad74978c07bc92a18e3 Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Tue, 31 Jul 2018 03:10:27 +0000
4Subject: upstream: delay bailout for invalid authenticating user
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9... until after the packet containing the request has been fully parsed.
10Reported by Dariusz Tytko and MichaƂ Sajdak; ok deraadt
11
12OpenBSD-Commit-ID: b4891882fbe413f230fe8ac8a37349b03bd0b70d
13
14Origin: backport, http://anongit.mindrot.org/openssh.git/commit/?id=74287f5df9966a0648b4a68417451dd18f079ab8
15Bug-Debian: https://bugs.debian.org/906236
16Last-Update: 2018-08-17
17
18Patch-Name: upstream-delay-bailout-for-invalid-authenticating-user.patch
19---
20 auth2-gss.c | 9 ++++++---
21 auth2-hostbased.c | 9 +++++----
22 auth2-pubkey.c | 23 ++++++++++++++---------
23 3 files changed, 25 insertions(+), 16 deletions(-)
24
25diff --git a/auth2-gss.c b/auth2-gss.c
26index fd411d3a7..88bc3ae7b 100644
27--- a/auth2-gss.c
28+++ b/auth2-gss.c
29@@ -104,9 +104,6 @@ userauth_gssapi(struct ssh *ssh)
30 u_int len;
31 u_char *doid = NULL;
32
33- if (!authctxt->valid || authctxt->user == NULL)
34- return (0);
35-
36 mechs = packet_get_int();
37 if (mechs == 0) {
38 debug("Mechanism negotiation is not supported");
39@@ -137,6 +134,12 @@ userauth_gssapi(struct ssh *ssh)
40 return (0);
41 }
42
43+ if (!authctxt->valid || authctxt->user == NULL) {
44+ debug2("%s: disabled because of invalid user", __func__);
45+ free(doid);
46+ return (0);
47+ }
48+
49 if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
50 if (ctxt != NULL)
51 ssh_gssapi_delete_ctx(&ctxt);
52diff --git a/auth2-hostbased.c b/auth2-hostbased.c
53index 8996f7e05..82a7dcdae 100644
54--- a/auth2-hostbased.c
55+++ b/auth2-hostbased.c
56@@ -67,10 +67,6 @@ userauth_hostbased(struct ssh *ssh)
57 size_t alen, blen, slen;
58 int r, pktype, authenticated = 0;
59
60- if (!authctxt->valid) {
61- debug2("%s: disabled because of invalid user", __func__);
62- return 0;
63- }
64 /* XXX use sshkey_froms() */
65 if ((r = sshpkt_get_cstring(ssh, &pkalg, &alen)) != 0 ||
66 (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 ||
67@@ -118,6 +114,11 @@ userauth_hostbased(struct ssh *ssh)
68 goto done;
69 }
70
71+ if (!authctxt->valid || authctxt->user == NULL) {
72+ debug2("%s: disabled because of invalid user", __func__);
73+ goto done;
74+ }
75+
76 if ((b = sshbuf_new()) == NULL)
77 fatal("%s: sshbuf_new failed", __func__);
78 /* reconstruct packet */
79diff --git a/auth2-pubkey.c b/auth2-pubkey.c
80index 8024b1d6a..a9272b97f 100644
81--- a/auth2-pubkey.c
82+++ b/auth2-pubkey.c
83@@ -89,19 +89,15 @@ userauth_pubkey(struct ssh *ssh)
84 {
85 Authctxt *authctxt = ssh->authctxt;
86 struct passwd *pw = authctxt->pw;
87- struct sshbuf *b;
88+ struct sshbuf *b = NULL;
89 struct sshkey *key = NULL;
90- char *pkalg, *userstyle = NULL, *key_s = NULL, *ca_s = NULL;
91- u_char *pkblob, *sig, have_sig;
92+ char *pkalg = NULL, *userstyle = NULL, *key_s = NULL, *ca_s = NULL;
93+ u_char *pkblob = NULL, *sig = NULL, have_sig;
94 size_t blen, slen;
95 int r, pktype;
96 int authenticated = 0;
97 struct sshauthopt *authopts = NULL;
98
99- if (!authctxt->valid) {
100- debug2("%s: disabled because of invalid user", __func__);
101- return 0;
102- }
103 if ((r = sshpkt_get_u8(ssh, &have_sig)) != 0 ||
104 (r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 ||
105 (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0)
106@@ -168,6 +164,11 @@ userauth_pubkey(struct ssh *ssh)
107 fatal("%s: sshbuf_put_string session id: %s",
108 __func__, ssh_err(r));
109 }
110+ if (!authctxt->valid || authctxt->user == NULL) {
111+ debug2("%s: disabled because of invalid user",
112+ __func__);
113+ goto done;
114+ }
115 /* reconstruct packet */
116 xasprintf(&userstyle, "%s%s%s", authctxt->user,
117 authctxt->style ? ":" : "",
118@@ -184,7 +185,6 @@ userauth_pubkey(struct ssh *ssh)
119 #ifdef DEBUG_PK
120 sshbuf_dump(b, stderr);
121 #endif
122-
123 /* test for correct signature */
124 authenticated = 0;
125 if (PRIVSEP(user_key_allowed(ssh, pw, key, 1, &authopts)) &&
126@@ -193,7 +193,6 @@ userauth_pubkey(struct ssh *ssh)
127 authenticated = 1;
128 }
129 sshbuf_free(b);
130- free(sig);
131 auth2_record_key(authctxt, authenticated, key);
132 } else {
133 debug("%s: test pkalg %s pkblob %s%s%s",
134@@ -204,6 +203,11 @@ userauth_pubkey(struct ssh *ssh)
135 if ((r = sshpkt_get_end(ssh)) != 0)
136 fatal("%s: %s", __func__, ssh_err(r));
137
138+ if (!authctxt->valid || authctxt->user == NULL) {
139+ debug2("%s: disabled because of invalid user",
140+ __func__);
141+ goto done;
142+ }
143 /* XXX fake reply and always send PK_OK ? */
144 /*
145 * XXX this allows testing whether a user is allowed
146@@ -237,6 +241,7 @@ done:
147 free(pkblob);
148 free(key_s);
149 free(ca_s);
150+ free(sig);
151 return authenticated;
152 }
153