From 35d5917652106aede47621bb3f64044604164043 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Thu, 4 Sep 2025 00:29:09 +0000 Subject: [PATCH] upstream: Improve rules for %-expansion of username. Usernames passed on the commandline will no longer be subject to % expansion. Some tools invoke ssh with connection information (i.e. usernames and host names) supplied from untrusted sources. These may contain % expansion sequences which could yield unexpected results. Since openssh-9.6, all usernames have been subject to validity checking. This change tightens the validity checks by refusing usernames that include control characters (again, these can cause surprises when supplied adversarially). This change also relaxes the validity checks in one small way: usernames supplied via the configuration file as literals (i.e. include no % expansion characters) are not subject to these validity checks. This allows usernames that contain arbitrary characters to be used, but only via configuration files. This is done on the basis that ssh's configuration is trusted. Pointed out by David Leadbeater, ok deraadt@ OpenBSD-Commit-ID: e2f0c871fbe664aba30607321575e7c7fc798362 CVE: CVE-2025-61984 Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/35d5917652106aede47621bb3f64044604164043] Signed-off-by: Hitendra Prajapati --- ssh.c | 11 +++++++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/ssh.c b/ssh.c index 82ed15f..d4e2040 100644 --- a/ssh.c +++ b/ssh.c @@ -634,6 +634,8 @@ valid_ruser(const char *s) if (*s == '-') return 0; for (i = 0; s[i] != 0; i++) { + if (iscntrl((u_char)s[i])) + return 0; if (strchr("'`\";&<>|(){}", s[i]) != NULL) return 0; /* Disallow '-' after whitespace */ @@ -655,6 +657,7 @@ main(int ac, char **av) struct ssh *ssh = NULL; int i, r, opt, exit_status, use_syslog, direct, timeout_ms; int was_addr, config_test = 0, opt_terminated = 0, want_final_pass = 0; + int user_on_commandline = 0, user_was_default = 0, user_expanded = 0; char *p, *cp, *line, *argv0, *logfile, *host_arg; char cname[NI_MAXHOST], thishost[NI_MAXHOST]; struct stat st; @@ -995,8 +998,10 @@ main(int ac, char **av) } break; case 'l': - if (options.user == NULL) + if (options.user == NULL) { options.user = optarg; + user_on_commandline = 1; + } break; case 'L': @@ -1099,6 +1104,7 @@ main(int ac, char **av) if (options.user == NULL) { options.user = tuser; tuser = NULL; + user_on_commandline = 1; } free(tuser); if (options.port == -1 && tport != -1) @@ -1113,6 +1119,7 @@ main(int ac, char **av) if (options.user == NULL) { options.user = p; p = NULL; + user_on_commandline = 1; } *cp++ = '\0'; host = xstrdup(cp); @@ -1265,8 +1272,10 @@ main(int ac, char **av) if (fill_default_options(&options) != 0) cleanup_exit(255); - if (options.user == NULL) + if (options.user == NULL) { + user_was_default = 1; options.user = xstrdup(pw->pw_name); + } /* * If ProxyJump option specified, then construct a ProxyCommand now. -- 2.50.1