summaryrefslogtreecommitdiffstats
path: root/meta/recipes-connectivity/openssh/openssh/CVE-2023-38408-05.patch
diff options
context:
space:
mode:
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.patch194
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 @@
+From a6cee3905edf070c0de135d3f2ee5b74da1dbd28 Mon Sep 17 00:00:00 2001
+From: "djm@openbsd.org" <djm@openbsd.org>
+Date: Tue, 26 May 2020 01:26:58 +0000
+Subject: [PATCH 05/12] upstream: Restrict ssh-agent from signing web
+ challenges for FIDO
+
+keys.
+
+When signing messages in ssh-agent using a FIDO key that has an
+application string that does not start with "ssh:", ensure that the
+message being signed is one of the forms expected for the SSH protocol
+(currently pubkey authentication and sshsig signatures).
+
+This prevents ssh-agent forwarding on a host that has FIDO keys
+attached granting the ability for the remote side to sign challenges
+for web authentication using those keys too.
+
+Note that the converse case of web browsers signing SSH challenges is
+already precluded because no web RP can have the "ssh:" prefix in the
+application string that we require.
+
+ok markus@
+
+OpenBSD-Commit-ID: 9ab6012574ed0352d2f097d307f4a988222d1b19
+
+Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/0c111eb84efba7c2a38b2cc3278901a0123161b9]
+CVE: CVE-2023-38408
+Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
+---
+ ssh-agent.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 100 insertions(+), 10 deletions(-)
+
+diff --git a/ssh-agent.c b/ssh-agent.c
+index ceb348c..1794f35 100644
+--- a/ssh-agent.c
++++ b/ssh-agent.c
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: ssh-agent.c,v 1.255 2020/02/06 22:30:54 naddy Exp $ */
++/* $OpenBSD: ssh-agent.c,v 1.258 2020/05/26 01:26:58 djm Exp $ */
+ /*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+@@ -77,6 +77,7 @@
+
+ #include "xmalloc.h"
+ #include "ssh.h"
++#include "ssh2.h"
+ #include "sshbuf.h"
+ #include "sshkey.h"
+ #include "authfd.h"
+@@ -167,6 +168,9 @@ static long lifetime = 0;
+
+ static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
+
++/* Refuse signing of non-SSH messages for web-origin FIDO keys */
++static int restrict_websafe = 1;
++
+ static void
+ close_socket(SocketEntry *e)
+ {
+@@ -282,6 +286,80 @@ agent_decode_alg(struct sshkey *key, u_int flags)
+ return NULL;
+ }
+
++/*
++ * This function inspects a message to be signed by a FIDO key that has a
++ * web-like application string (i.e. one that does not begin with "ssh:".
++ * It checks that the message is one of those expected for SSH operations
++ * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges
++ * for the web.
++ */
++static int
++check_websafe_message_contents(struct sshkey *key,
++ const u_char *msg, size_t len)
++{
++ int matched = 0;
++ struct sshbuf *b;
++ u_char m, n;
++ char *cp1 = NULL, *cp2 = NULL;
++ int r;
++ struct sshkey *mkey = NULL;
++
++ if ((b = sshbuf_from(msg, len)) == NULL)
++ fatal("%s: sshbuf_new", __func__);
++
++ /* SSH userauth request */
++ if ((r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* sess_id */
++ (r = sshbuf_get_u8(b, &m)) == 0 && /* SSH2_MSG_USERAUTH_REQUEST */
++ (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* server user */
++ (r = sshbuf_get_cstring(b, &cp1, NULL)) == 0 && /* service */
++ (r = sshbuf_get_cstring(b, &cp2, NULL)) == 0 && /* method */
++ (r = sshbuf_get_u8(b, &n)) == 0 && /* sig-follows */
++ (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* alg */
++ (r = sshkey_froms(b, &mkey)) == 0 && /* key */
++ sshbuf_len(b) == 0) {
++ debug("%s: parsed userauth", __func__);
++ if (m == SSH2_MSG_USERAUTH_REQUEST && n == 1 &&
++ strcmp(cp1, "ssh-connection") == 0 &&
++ strcmp(cp2, "publickey") == 0 &&
++ sshkey_equal(key, mkey)) {
++ debug("%s: well formed userauth", __func__);
++ matched = 1;
++ }
++ }
++ free(cp1);
++ free(cp2);
++ sshkey_free(mkey);
++ sshbuf_free(b);
++ if (matched)
++ return 1;
++
++ if ((b = sshbuf_from(msg, len)) == NULL)
++ fatal("%s: sshbuf_new", __func__);
++ cp1 = cp2 = NULL;
++ mkey = NULL;
++
++ /* SSHSIG */
++ if ((r = sshbuf_cmp(b, 0, "SSHSIG", 6)) == 0 &&
++ (r = sshbuf_consume(b, 6)) == 0 &&
++ (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* namespace */
++ (r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* reserved */
++ (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* hashalg */
++ (r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* H(msg) */
++ sshbuf_len(b) == 0) {
++ debug("%s: parsed sshsig", __func__);
++ matched = 1;
++ }
++
++ sshbuf_free(b);
++ if (matched)
++ return 1;
++
++ /* XXX CA signature operation */
++
++ error("web-origin key attempting to sign non-SSH message");
++ return 0;
++}
++
+ /* ssh2 only */
+ static void
+ process_sign_request2(SocketEntry *e)
+@@ -314,14 +392,20 @@ process_sign_request2(SocketEntry *e)
+ verbose("%s: user refused key", __func__);
+ goto send;
+ }
+- if (sshkey_is_sk(id->key) &&
+- (id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
+- if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
+- SSH_FP_DEFAULT)) == NULL)
+- fatal("%s: fingerprint failed", __func__);
+- notifier = notify_start(0,
+- "Confirm user presence for key %s %s",
+- sshkey_type(id->key), fp);
++ if (sshkey_is_sk(id->key)) {
++ if (strncmp(id->key->sk_application, "ssh:", 4) != 0 &&
++ !check_websafe_message_contents(key, data, dlen)) {
++ /* error already logged */
++ goto send;
++ }
++ if ((id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
++ if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
++ SSH_FP_DEFAULT)) == NULL)
++ fatal("%s: fingerprint failed", __func__);
++ notifier = notify_start(0,
++ "Confirm user presence for key %s %s",
++ sshkey_type(id->key), fp);
++ }
+ }
+ if ((r = sshkey_sign(id->key, &signature, &slen,
+ data, dlen, agent_decode_alg(key, flags),
+@@ -1214,7 +1298,7 @@ main(int ac, char **av)
+ __progname = ssh_get_progname(av[0]);
+ seed_rng();
+
+- while ((ch = getopt(ac, av, "cDdksE:a:P:t:")) != -1) {
++ while ((ch = getopt(ac, av, "cDdksE:a:O:P:t:")) != -1) {
+ switch (ch) {
+ case 'E':
+ fingerprint_hash = ssh_digest_alg_by_name(optarg);
+@@ -1229,6 +1313,12 @@ main(int ac, char **av)
+ case 'k':
+ k_flag++;
+ break;
++ case 'O':
++ if (strcmp(optarg, "no-restrict-websafe") == 0)
++ restrict_websafe = 0;
++ else
++ fatal("Unknown -O option");
++ break;
+ case 'P':
+ if (provider_whitelist != NULL)
+ fatal("-P option already specified");
+--
+2.41.0