diff options
author | Colin Watson <cjwatson@debian.org> | 2018-08-17 12:28:26 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2018-08-17 12:31:27 +0100 |
commit | 4641c58a3279f6b118f9562babaa0ee050a38619 (patch) | |
tree | 87718b668ec8a737c1729ee568207c2a384f6d61 | |
parent | daf34b85afe25c10fac13e9cff16b25c3e3914e9 (diff) | |
parent | c4ca1497658e0508e8595ad74978c07bc92a18e3 (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.c | 9 | ||||
-rw-r--r-- | auth2-hostbased.c | 9 | ||||
-rw-r--r-- | auth2-pubkey.c | 23 | ||||
-rw-r--r-- | debian/.git-dpm | 4 | ||||
-rw-r--r-- | debian/changelog | 8 | ||||
-rw-r--r-- | debian/patches/series | 1 | ||||
-rw-r--r-- | debian/patches/upstream-delay-bailout-for-invalid-authenticating-user.patch | 153 |
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 |
2 | 60256f28189c3d0650a78e737eb0ca4753478a4b | 2 | c4ca1497658e0508e8595ad74978c07bc92a18e3 |
3 | 60256f28189c3d0650a78e737eb0ca4753478a4b | 3 | c4ca1497658e0508e8595ad74978c07bc92a18e3 |
4 | ed6ae9c1a014a08ff5db3d768f01f2e427eeb476 | 4 | ed6ae9c1a014a08ff5db3d768f01f2e427eeb476 |
5 | ed6ae9c1a014a08ff5db3d768f01f2e427eeb476 | 5 | ed6ae9c1a014a08ff5db3d768f01f2e427eeb476 |
6 | openssh_7.7p1.orig.tar.gz | 6 | openssh_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 @@ | |||
1 | openssh (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 | |||
1 | openssh (1:7.7p1-3) unstable; urgency=medium | 9 | openssh (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 | |||
25 | seccomp-getuid-geteuid.patch | 25 | seccomp-getuid-geteuid.patch |
26 | seccomp-s390-ioctl-ep11-crypto.patch | 26 | seccomp-s390-ioctl-ep11-crypto.patch |
27 | upstream-relax-checking-of-authorized_keys-environme.patch | 27 | upstream-relax-checking-of-authorized_keys-environme.patch |
28 | upstream-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 @@ | |||
1 | From c4ca1497658e0508e8595ad74978c07bc92a18e3 Mon Sep 17 00:00:00 2001 | ||
2 | From: "djm@openbsd.org" <djm@openbsd.org> | ||
3 | Date: Tue, 31 Jul 2018 03:10:27 +0000 | ||
4 | Subject: upstream: delay bailout for invalid authenticating user | ||
5 | MIME-Version: 1.0 | ||
6 | Content-Type: text/plain; charset=UTF-8 | ||
7 | Content-Transfer-Encoding: 8bit | ||
8 | |||
9 | ... until after the packet containing the request has been fully parsed. | ||
10 | Reported by Dariusz Tytko and MichaĆ Sajdak; ok deraadt | ||
11 | |||
12 | OpenBSD-Commit-ID: b4891882fbe413f230fe8ac8a37349b03bd0b70d | ||
13 | |||
14 | Origin: backport, http://anongit.mindrot.org/openssh.git/commit/?id=74287f5df9966a0648b4a68417451dd18f079ab8 | ||
15 | Bug-Debian: https://bugs.debian.org/906236 | ||
16 | Last-Update: 2018-08-17 | ||
17 | |||
18 | Patch-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 | |||
25 | diff --git a/auth2-gss.c b/auth2-gss.c | ||
26 | index 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); | ||
52 | diff --git a/auth2-hostbased.c b/auth2-hostbased.c | ||
53 | index 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 */ | ||
79 | diff --git a/auth2-pubkey.c b/auth2-pubkey.c | ||
80 | index 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 | |||