3b77217
From: Russ Allbery <rra@debian.org>
3b77217
Date: Thu, 17 Jan 2019 19:21:40 -0800
3b77217
Subject: Verify scp command options
3b77217
3b77217
ESnet discovered a security vulnerability in the scp backend for
3b77217
rssh.  Since the arguments to scp on the server side were not
3b77217
checked, the client could pass in arbitrary scp command-line flags,
3b77217
including setting arbitrary scp options.  This allows setting the
3b77217
option PKCS11Provider, which loads and executes code from a shared
3b77217
module.
3b77217
3b77217
Even if the -o flag is blocked, this is still possible via -F to
3b77217
load an already-uploaded ssh configuration file, or, if .ssh/config
3b77217
is writable, by just uploading that configuration file directly
3b77217
first.
3b77217
3b77217
Attempt to protect against this attack by checking the command line
3b77217
of scp and only allowing the options that are passed to the server
f4e6b2d
end of the connection.  Require either -f or -t be given, which
f4e6b2d
disables scp's attempts to connect to a remote host.  Allow these as
f4e6b2d
-pf and -pt, which are sent by libssh2.
3b77217
3b77217
Debian Bug#919623
3b77217
---
f4e6b2d
 util.c | 44 ++++++++++++++++++++++++++++++++++++++++++--
f4e6b2d
 1 file changed, 42 insertions(+), 2 deletions(-)
3b77217
3b77217
diff --git a/util.c b/util.c
f4e6b2d
index dc8c8fb..4203eac 100644
3b77217
--- a/util.c
3b77217
+++ b/util.c
f4e6b2d
@@ -266,6 +266,43 @@ static int rsync_okay( char **vec )
3b77217
 }
3b77217
 
3b77217
 
3b77217
+/*
3b77217
+ * scp_okay() - take the command line and check that it is a hopefully-safe scp
3b77217
+ *		server command line, accepting only very specific options.
3b77217
+ *		Returns FALSE if the command line should not be allowed, TRUE
3b77217
+ *		if it is okay.
3b77217
+ */
3b77217
+static int scp_okay( char **vec )
3b77217
+{
f4e6b2d
+	int saw_f_or_t = FALSE;
3b77217
+
3b77217
+	for ( vec++; vec && *vec; vec++ ){
3b77217
+		/* Allowed options. */
f4e6b2d
+		if ( strcmp(*vec, "-v") == 0 ) continue;
f4e6b2d
+		if ( strcmp(*vec, "-r") == 0 ) continue;
f4e6b2d
+		if ( strcmp(*vec, "-p") == 0 ) continue;
f4e6b2d
+		if ( strcmp(*vec, "-d") == 0 ) continue;
f4e6b2d
+		if ( strcmp(*vec, "-f") == 0 || strcmp(*vec, "-pf") == 0 ){
f4e6b2d
+			saw_f_or_t = TRUE;
f4e6b2d
+			continue;
3b77217
+		}
f4e6b2d
+		if ( strcmp(*vec, "-t") == 0 || strcmp(*vec, "-pt") == 0 ){
f4e6b2d
+			saw_f_or_t = TRUE;
3b77217
+			continue;
3b77217
+		}
3b77217
+
f4e6b2d
+		/* End of arguments. */
f4e6b2d
+		if ( strcmp(*vec, "--") == 0 ) break;
f4e6b2d
+
f4e6b2d
+		/* Any other argument is not allowed. */
f4e6b2d
+		if ( *vec[0] == '-' ) return FALSE;
3b77217
+	}
3b77217
+
f4e6b2d
+	/* Either -f or -t must have been given. */
f4e6b2d
+	return saw_f_or_t;
3b77217
+}
3b77217
+
3b77217
+
3b77217
 /*
3b77217
  * check_command_line() - take the command line passed to rssh, and verify
3b77217
  *			  that the specified command is one the user is
f4e6b2d
@@ -281,8 +318,11 @@ char *check_command_line( char **cl, ShellOptions_t *opts )
3b77217
 		return PATH_SFTP_SERVER;
3b77217
 
3b77217
 	if ( check_command(*cl, opts, PATH_SCP, RSSH_ALLOW_SCP) ){
3b77217
-		/* filter -S option */
3b77217
-		if ( opt_filter(cl, 'S') ) return NULL;
3b77217
+		if ( !scp_okay(cl) ){
3b77217
+			fprintf(stderr, "\ninsecure scp option not allowed.");
3b77217
+			log_msg("insecure scp option in scp command line");
3b77217
+			return NULL;
3b77217
+		}
3b77217
 		return PATH_SCP;
3b77217
 	}
3b77217