diff options
Diffstat (limited to 'meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-05.patch')
-rw-r--r-- | meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-05.patch | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-05.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-05.patch new file mode 100644 index 0000000000..0ddbdc68d4 --- /dev/null +++ b/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-05.patch | |||
@@ -0,0 +1,194 @@ | |||
1 | From a6cee3905edf070c0de135d3f2ee5b74da1dbd28 Mon Sep 17 00:00:00 2001 | ||
2 | From: "djm@openbsd.org" <djm@openbsd.org> | ||
3 | Date: Tue, 26 May 2020 01:26:58 +0000 | ||
4 | Subject: [PATCH 05/12] upstream: Restrict ssh-agent from signing web | ||
5 | challenges for FIDO | ||
6 | |||
7 | keys. | ||
8 | |||
9 | When signing messages in ssh-agent using a FIDO key that has an | ||
10 | application string that does not start with "ssh:", ensure that the | ||
11 | message being signed is one of the forms expected for the SSH protocol | ||
12 | (currently pubkey authentication and sshsig signatures). | ||
13 | |||
14 | This prevents ssh-agent forwarding on a host that has FIDO keys | ||
15 | attached granting the ability for the remote side to sign challenges | ||
16 | for web authentication using those keys too. | ||
17 | |||
18 | Note that the converse case of web browsers signing SSH challenges is | ||
19 | already precluded because no web RP can have the "ssh:" prefix in the | ||
20 | application string that we require. | ||
21 | |||
22 | ok markus@ | ||
23 | |||
24 | OpenBSD-Commit-ID: 9ab6012574ed0352d2f097d307f4a988222d1b19 | ||
25 | |||
26 | Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/0c111eb84efba7c2a38b2cc3278901a0123161b9] | ||
27 | CVE: CVE-2023-38408 | ||
28 | Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com> | ||
29 | --- | ||
30 | ssh-agent.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++----- | ||
31 | 1 file changed, 100 insertions(+), 10 deletions(-) | ||
32 | |||
33 | diff --git a/ssh-agent.c b/ssh-agent.c | ||
34 | index ceb348c..1794f35 100644 | ||
35 | --- a/ssh-agent.c | ||
36 | +++ b/ssh-agent.c | ||
37 | @@ -1,4 +1,4 @@ | ||
38 | -/* $OpenBSD: ssh-agent.c,v 1.255 2020/02/06 22:30:54 naddy Exp $ */ | ||
39 | +/* $OpenBSD: ssh-agent.c,v 1.258 2020/05/26 01:26:58 djm Exp $ */ | ||
40 | /* | ||
41 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | ||
42 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | ||
43 | @@ -77,6 +77,7 @@ | ||
44 | |||
45 | #include "xmalloc.h" | ||
46 | #include "ssh.h" | ||
47 | +#include "ssh2.h" | ||
48 | #include "sshbuf.h" | ||
49 | #include "sshkey.h" | ||
50 | #include "authfd.h" | ||
51 | @@ -167,6 +168,9 @@ static long lifetime = 0; | ||
52 | |||
53 | static int fingerprint_hash = SSH_FP_HASH_DEFAULT; | ||
54 | |||
55 | +/* Refuse signing of non-SSH messages for web-origin FIDO keys */ | ||
56 | +static int restrict_websafe = 1; | ||
57 | + | ||
58 | static void | ||
59 | close_socket(SocketEntry *e) | ||
60 | { | ||
61 | @@ -282,6 +286,80 @@ agent_decode_alg(struct sshkey *key, u_int flags) | ||
62 | return NULL; | ||
63 | } | ||
64 | |||
65 | +/* | ||
66 | + * This function inspects a message to be signed by a FIDO key that has a | ||
67 | + * web-like application string (i.e. one that does not begin with "ssh:". | ||
68 | + * It checks that the message is one of those expected for SSH operations | ||
69 | + * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges | ||
70 | + * for the web. | ||
71 | + */ | ||
72 | +static int | ||
73 | +check_websafe_message_contents(struct sshkey *key, | ||
74 | + const u_char *msg, size_t len) | ||
75 | +{ | ||
76 | + int matched = 0; | ||
77 | + struct sshbuf *b; | ||
78 | + u_char m, n; | ||
79 | + char *cp1 = NULL, *cp2 = NULL; | ||
80 | + int r; | ||
81 | + struct sshkey *mkey = NULL; | ||
82 | + | ||
83 | + if ((b = sshbuf_from(msg, len)) == NULL) | ||
84 | + fatal("%s: sshbuf_new", __func__); | ||
85 | + | ||
86 | + /* SSH userauth request */ | ||
87 | + if ((r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* sess_id */ | ||
88 | + (r = sshbuf_get_u8(b, &m)) == 0 && /* SSH2_MSG_USERAUTH_REQUEST */ | ||
89 | + (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* server user */ | ||
90 | + (r = sshbuf_get_cstring(b, &cp1, NULL)) == 0 && /* service */ | ||
91 | + (r = sshbuf_get_cstring(b, &cp2, NULL)) == 0 && /* method */ | ||
92 | + (r = sshbuf_get_u8(b, &n)) == 0 && /* sig-follows */ | ||
93 | + (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* alg */ | ||
94 | + (r = sshkey_froms(b, &mkey)) == 0 && /* key */ | ||
95 | + sshbuf_len(b) == 0) { | ||
96 | + debug("%s: parsed userauth", __func__); | ||
97 | + if (m == SSH2_MSG_USERAUTH_REQUEST && n == 1 && | ||
98 | + strcmp(cp1, "ssh-connection") == 0 && | ||
99 | + strcmp(cp2, "publickey") == 0 && | ||
100 | + sshkey_equal(key, mkey)) { | ||
101 | + debug("%s: well formed userauth", __func__); | ||
102 | + matched = 1; | ||
103 | + } | ||
104 | + } | ||
105 | + free(cp1); | ||
106 | + free(cp2); | ||
107 | + sshkey_free(mkey); | ||
108 | + sshbuf_free(b); | ||
109 | + if (matched) | ||
110 | + return 1; | ||
111 | + | ||
112 | + if ((b = sshbuf_from(msg, len)) == NULL) | ||
113 | + fatal("%s: sshbuf_new", __func__); | ||
114 | + cp1 = cp2 = NULL; | ||
115 | + mkey = NULL; | ||
116 | + | ||
117 | + /* SSHSIG */ | ||
118 | + if ((r = sshbuf_cmp(b, 0, "SSHSIG", 6)) == 0 && | ||
119 | + (r = sshbuf_consume(b, 6)) == 0 && | ||
120 | + (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* namespace */ | ||
121 | + (r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* reserved */ | ||
122 | + (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* hashalg */ | ||
123 | + (r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* H(msg) */ | ||
124 | + sshbuf_len(b) == 0) { | ||
125 | + debug("%s: parsed sshsig", __func__); | ||
126 | + matched = 1; | ||
127 | + } | ||
128 | + | ||
129 | + sshbuf_free(b); | ||
130 | + if (matched) | ||
131 | + return 1; | ||
132 | + | ||
133 | + /* XXX CA signature operation */ | ||
134 | + | ||
135 | + error("web-origin key attempting to sign non-SSH message"); | ||
136 | + return 0; | ||
137 | +} | ||
138 | + | ||
139 | /* ssh2 only */ | ||
140 | static void | ||
141 | process_sign_request2(SocketEntry *e) | ||
142 | @@ -314,14 +392,20 @@ process_sign_request2(SocketEntry *e) | ||
143 | verbose("%s: user refused key", __func__); | ||
144 | goto send; | ||
145 | } | ||
146 | - if (sshkey_is_sk(id->key) && | ||
147 | - (id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { | ||
148 | - if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, | ||
149 | - SSH_FP_DEFAULT)) == NULL) | ||
150 | - fatal("%s: fingerprint failed", __func__); | ||
151 | - notifier = notify_start(0, | ||
152 | - "Confirm user presence for key %s %s", | ||
153 | - sshkey_type(id->key), fp); | ||
154 | + if (sshkey_is_sk(id->key)) { | ||
155 | + if (strncmp(id->key->sk_application, "ssh:", 4) != 0 && | ||
156 | + !check_websafe_message_contents(key, data, dlen)) { | ||
157 | + /* error already logged */ | ||
158 | + goto send; | ||
159 | + } | ||
160 | + if ((id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { | ||
161 | + if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, | ||
162 | + SSH_FP_DEFAULT)) == NULL) | ||
163 | + fatal("%s: fingerprint failed", __func__); | ||
164 | + notifier = notify_start(0, | ||
165 | + "Confirm user presence for key %s %s", | ||
166 | + sshkey_type(id->key), fp); | ||
167 | + } | ||
168 | } | ||
169 | if ((r = sshkey_sign(id->key, &signature, &slen, | ||
170 | data, dlen, agent_decode_alg(key, flags), | ||
171 | @@ -1214,7 +1298,7 @@ main(int ac, char **av) | ||
172 | __progname = ssh_get_progname(av[0]); | ||
173 | seed_rng(); | ||
174 | |||
175 | - while ((ch = getopt(ac, av, "cDdksE:a:P:t:")) != -1) { | ||
176 | + while ((ch = getopt(ac, av, "cDdksE:a:O:P:t:")) != -1) { | ||
177 | switch (ch) { | ||
178 | case 'E': | ||
179 | fingerprint_hash = ssh_digest_alg_by_name(optarg); | ||
180 | @@ -1229,6 +1313,12 @@ main(int ac, char **av) | ||
181 | case 'k': | ||
182 | k_flag++; | ||
183 | break; | ||
184 | + case 'O': | ||
185 | + if (strcmp(optarg, "no-restrict-websafe") == 0) | ||
186 | + restrict_websafe = 0; | ||
187 | + else | ||
188 | + fatal("Unknown -O option"); | ||
189 | + break; | ||
190 | case 'P': | ||
191 | if (provider_whitelist != NULL) | ||
192 | fatal("-P option already specified"); | ||
193 | -- | ||
194 | 2.41.0 | ||