MFH: r494837
shells/rssh: Apply fixes for basename(3) handling and some security issues basename(3) has been changed to be POSIX compliant in r308264. This implies that it can possibly write to the passed string. shells/rssh passes a const string, so it always crashes on invocation with FreeBSD 12 and later. The new patches remedy this issue. [1] [2] During further tests and research came to light that there were also recently discovered security issues with the parsing of rsync/scp command line arguments and insufficient sanitization of environment variables when using rysnc. The corresponding fixes have been incorporated to the new patches and the already existing patch for the RSYNC option has been tightened for the argument parsing. Please note that with this patch the scp option "-3" can no longer be used. [3] Furthermore, another patch was applied to make this port a bit more secure. That patch handles a buffer allocation issue for an error message. [4] PR: 235121 Submitted by: topical@gmx.net (first version) [1], Jason Harris (maintainer) [2] Approved by: tcberner (mentor) Obtained from: Debian [3] [4] Security: d193aa9f-3f8c-11e9-9a24-6805ca0b38e8 Differential Revision: https://reviews.freebsd.org/D19474 Approved by: ports-secteam (riggs), mentors implicit
This commit is contained in:
parent
95208cea70
commit
49d8789e48
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/branches/2019Q1/; revision=494951
@ -3,7 +3,7 @@
|
||||
|
||||
PORTNAME= rssh
|
||||
PORTVERSION= 2.3.4
|
||||
PORTREVISION= 1
|
||||
PORTREVISION= 2
|
||||
CATEGORIES= shells security
|
||||
MASTER_SITES= SF
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
--- util.c.orig 2012-11-27 12:14:49.000000000 +1100
|
||||
+++ util.c 2013-01-09 17:52:54.000000000 +1100
|
||||
Verifies the command line options for rysnc. This is an updated version that
|
||||
tightens the argument checking and requires to run rsync in server mode.
|
||||
Taken from Debian ("0007-Verify-rsync-command-options").
|
||||
--- util.c.orig 2012-11-27 01:14:49 UTC
|
||||
+++ util.c
|
||||
@@ -56,6 +56,7 @@
|
||||
#ifdef HAVE_LIBGEN_H
|
||||
#include <libgen.h>
|
||||
@ -8,18 +11,16 @@
|
||||
|
||||
/* LOCAL INCLUDES */
|
||||
#include "pathnames.h"
|
||||
@@ -198,6 +199,73 @@
|
||||
@@ -198,6 +199,71 @@ bool check_command( char *cl, ShellOptions_t *opts, ch
|
||||
|
||||
|
||||
/*
|
||||
+ * rsync_e_okay() - take the command line passed to rssh and look for an -e
|
||||
+ * option. If one is found, make sure --server is provided
|
||||
+ * and the option contains only the protocol information.
|
||||
+ * Also check for and reject any --rsh option. Returns FALSE
|
||||
+ * if the command line should not be allowed, TRUE if it is
|
||||
+ * okay.
|
||||
+ * rsync_okay() - require --server on all rsh command lines, check that -e
|
||||
+ * contains only protocol information, and reject any --rsh,
|
||||
+ * --config, or --daemon option. Returns FALSE if the command
|
||||
+ * line should not be allowed, TRUE if it is okay.
|
||||
+ */
|
||||
+static int rsync_e_okay( char **vec )
|
||||
+static int rsync_okay( char **vec )
|
||||
+{
|
||||
+ regex_t re;
|
||||
+ int server = FALSE;
|
||||
@ -48,18 +49,19 @@
|
||||
+ * could be hidden from the server as an argument to some other
|
||||
+ * option.
|
||||
+ */
|
||||
+ if ( vec && vec[0] && vec[1] && strcmp(vec[1], "--server") == 0 ){
|
||||
+ server = TRUE;
|
||||
+ }
|
||||
+ if ( !(vec && vec[0] && vec[1] && strcmp(vec[1], "--server") == 0) )
|
||||
+ return FALSE;
|
||||
+
|
||||
+ /* Check the remaining options for -e or --rsh. */
|
||||
+ if ( regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB) != 0 ){
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ while (vec && *vec){
|
||||
+ if ( strcmp(*vec, "--") == 0 ) break;
|
||||
+ if ( strcmp(*vec, "--rsh") == 0
|
||||
+ || strncmp(*vec, "--rsh=", strlen("--rsh=")) == 0 ){
|
||||
+ || strcmp(*vec, "--daemon") == 0
|
||||
+ || strcmp(*vec, "--config") == 0
|
||||
+ || strncmp(*vec, "--rsh=", strlen("--rsh=")) == 0
|
||||
+ || strncmp(*vec, "--config=", strlen("--config=")) == 0 ){
|
||||
+ regfree(&re);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
@ -73,7 +75,6 @@
|
||||
+ vec++;
|
||||
+ }
|
||||
+ regfree(&re);
|
||||
+ if ( e_found && !server ) return FALSE;
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
@ -82,10 +83,11 @@
|
||||
* check_command_line() - take the command line passed to rssh, and verify
|
||||
* that the specified command is one the user is
|
||||
* allowed to run and validate the arguments. Return the
|
||||
@@ -230,14 +298,10 @@
|
||||
@@ -229,16 +295,27 @@ char *check_command_line( char **cl, ShellOptions_t *o
|
||||
}
|
||||
|
||||
if ( check_command(*cl, opts, PATH_RSYNC, RSSH_ALLOW_RSYNC) ){
|
||||
/* filter -e option */
|
||||
- /* filter -e option */
|
||||
- if ( opt_filter(cl, 'e') ) return NULL;
|
||||
- while (cl && *cl){
|
||||
- if ( strstr(*cl, "--rsh" ) ){
|
||||
@ -94,10 +96,27 @@
|
||||
- return NULL;
|
||||
- }
|
||||
- cl++;
|
||||
+ if ( !rsync_e_okay(cl) ){
|
||||
+ fprintf(stderr, "\ninsecure -e or --rsh option not allowed.");
|
||||
+ log_msg("insecure -e or --rsh option in rsync command line!");
|
||||
+ if ( !rsync_okay(cl) ){
|
||||
+ fprintf(stderr, "\ninsecure rsync options not allowed.");
|
||||
+ log_msg("insecure rsync options in rsync command line!");
|
||||
+ return NULL;
|
||||
}
|
||||
+
|
||||
+ /*
|
||||
+ * rsync is linked with popt, which recognizes a configuration
|
||||
+ * file ~/.popt that can, among other things, define aliases.
|
||||
+ * If someone can write to the home directory of the rssh
|
||||
+ * user, they can upload a ~/.popt file that contains
|
||||
+ * something like "rsync alias --server --rsh" and then
|
||||
+ * execute commands they upload. popt does not try to read
|
||||
+ * its configuration file if HOME is not set, so unset HOME to
|
||||
+ * disable this behavior.
|
||||
+ */
|
||||
+ if ( unsetenv("HOME") < 0 ){
|
||||
+ log_msg("cannot unsetenv() HOME");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
return PATH_RSYNC;
|
||||
}
|
||||
/* No match, return NULL */
|
||||
|
22
shells/rssh/files/patch-log.c
Normal file
22
shells/rssh/files/patch-log.c
Normal file
@ -0,0 +1,22 @@
|
||||
Workaround for basename(3) that is POSIX compliant since r308264 in FreeBSD 12
|
||||
--- log.c.orig 2012-11-27 00:25:13 UTC
|
||||
+++ log.c
|
||||
@@ -93,10 +93,14 @@ char *log_make_ident( const char *name )
|
||||
}
|
||||
/* assign new value to ident from name */
|
||||
if ( !name ) return (ident = NULL);
|
||||
- ident = strdup(basename((char*)name));
|
||||
- /* remove leading '-' from ident, if there is one */
|
||||
- if ( ident[0] == '-' ){
|
||||
- temp = strdup(ident + 1);
|
||||
+ /* clone name in case basename() is POSIX-compliant */
|
||||
+ temp = strdup ((char *) name);
|
||||
+ /* always pass writeable string to basename() */
|
||||
+ ident = strdup (basename (temp));
|
||||
+ free (temp);
|
||||
+ /* safely remove leading '-' from ident, if there is one */
|
||||
+ if ((ident != NULL) && (ident[0] == '-')){
|
||||
+ temp = strdup(&ident[1]);
|
||||
free(ident);
|
||||
ident = temp;
|
||||
}
|
29
shells/rssh/files/patch-rssh__chroot__helper.c
Normal file
29
shells/rssh/files/patch-rssh__chroot__helper.c
Normal file
@ -0,0 +1,29 @@
|
||||
Workaround for basename(3) that is POSIX compliant since r308264 in FreeBSD 12
|
||||
|
||||
Incorporates also a patch to check the command line after chroot. Taken from
|
||||
Debian ("0010-Check-command-line-after-chroot.patch")
|
||||
|
||||
--- rssh_chroot_helper.c.orig 2006-12-21 22:22:35 UTC
|
||||
+++ rssh_chroot_helper.c
|
||||
@@ -159,7 +159,7 @@ int main( int argc, char **argv )
|
||||
opts.chroot_path = NULL;
|
||||
|
||||
/* figure out our name, and give it to the log module */
|
||||
- progname = strdup(log_make_ident(basename(argv[0])));
|
||||
+ progname = strdup(log_make_ident(basename(strdup (argv[0]))));
|
||||
|
||||
/* get user's passwd info */
|
||||
if ( (temp = getpwuid(getuid())) ){
|
||||
@@ -217,6 +217,12 @@ int main( int argc, char **argv )
|
||||
if ( !(argvec = build_arg_vector(argv[2], 0)) )
|
||||
ch_fatal_error("build_arg_vector()", argv[2],
|
||||
"bad expansion");
|
||||
+
|
||||
+ /* check the command for safety */
|
||||
+ if ( !check_command_line(argvec, &opts) ){
|
||||
+ fprintf(stderr, "\n");
|
||||
+ exit(1);
|
||||
+ }
|
||||
|
||||
/*
|
||||
* This is the old way to figure out what program to run. Since we're
|
105
shells/rssh/files/patch-util.c
Normal file
105
shells/rssh/files/patch-util.c
Normal file
@ -0,0 +1,105 @@
|
||||
Workaround for basename(3) that is POSIX compliant since r308264 in FreeBSD 12
|
||||
|
||||
Fixes buffer allocation for the fail message. Taken from Debian
|
||||
("0003-Fix-buffer-allocation-buffer-for-fail-message").
|
||||
|
||||
Tightens the check for scp command line arguments that fixes also
|
||||
"CVE-2019-1000018". Taken from Debian ("0009-Verify-scp-command-options").
|
||||
Please note that with this patch the scp option "-3" can no longer be used.
|
||||
|
||||
--- util.c.orig 2012-11-27 01:14:49 UTC
|
||||
+++ util.c
|
||||
@@ -84,7 +84,7 @@ void fail( int flags, int argc, char **argv )
|
||||
/* create msg indicating what is allowed */
|
||||
if ( !size ) cmd = "This user is locked out.";
|
||||
else {
|
||||
- size += 18;
|
||||
+ size += 18 + 1;
|
||||
if ( !(cmd = (char *)malloc(size)) ){
|
||||
log_msg("fatal error: out of mem allocating log msg");
|
||||
exit(1);
|
||||
@@ -165,6 +165,7 @@ bool check_command( char *cl, ShellOptions_t *opts, ch
|
||||
{
|
||||
char *prog; /* basename of cmd */
|
||||
char *tmp = cl;
|
||||
+ char *tmp2 = NULL;
|
||||
bool need_free = FALSE;
|
||||
bool rc = FALSE;
|
||||
int i;
|
||||
@@ -186,11 +187,17 @@ bool check_command( char *cl, ShellOptions_t *opts, ch
|
||||
}
|
||||
|
||||
/* compare tmp to cmd and prog for match */
|
||||
- prog = basename(cmd);
|
||||
+ tmp2 = strdup (cmd);
|
||||
+ if (tmp2 == NULL) {
|
||||
+ log_msg ("strdup() failed in check_command()");
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ prog = basename(tmp2);
|
||||
if ( !(strcmp(tmp, cmd)) || !(strcmp(tmp, prog))){
|
||||
log_msg("cmd '%s' approved", prog);
|
||||
rc = TRUE;
|
||||
}
|
||||
+ free (tmp2);
|
||||
}
|
||||
if (need_free) free(tmp);
|
||||
return rc;
|
||||
@@ -198,6 +205,43 @@ bool check_command( char *cl, ShellOptions_t *opts, ch
|
||||
|
||||
|
||||
/*
|
||||
+ * scp_okay() - take the command line and check that it is a hopefully-safe scp
|
||||
+ * server command line, accepting only very specific options.
|
||||
+ * Returns FALSE if the command line should not be allowed, TRUE
|
||||
+ * if it is okay.
|
||||
+ */
|
||||
+static int scp_okay( char **vec )
|
||||
+{
|
||||
+ int saw_f_or_t = FALSE;
|
||||
+
|
||||
+ for ( vec++; vec && *vec; vec++ ){
|
||||
+ /* Allowed options. */
|
||||
+ if ( strcmp(*vec, "-v") == 0 ) continue;
|
||||
+ if ( strcmp(*vec, "-r") == 0 ) continue;
|
||||
+ if ( strcmp(*vec, "-p") == 0 ) continue;
|
||||
+ if ( strcmp(*vec, "-d") == 0 ) continue;
|
||||
+ if ( strcmp(*vec, "-f") == 0 || strcmp(*vec, "-pf") == 0 ){
|
||||
+ saw_f_or_t = TRUE;
|
||||
+ continue;
|
||||
+ }
|
||||
+ if ( strcmp(*vec, "-t") == 0 || strcmp(*vec, "-pt") == 0 ){
|
||||
+ saw_f_or_t = TRUE;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* End of arguments. */
|
||||
+ if ( strcmp(*vec, "--") == 0 ) break;
|
||||
+
|
||||
+ /* Any other argument is not allowed. */
|
||||
+ if ( *vec[0] == '-' ) return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ /* Either -f or -t must have been given. */
|
||||
+ return saw_f_or_t;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
* check_command_line() - take the command line passed to rssh, and verify
|
||||
* that the specified command is one the user is
|
||||
* allowed to run and validate the arguments. Return the
|
||||
@@ -212,8 +256,11 @@ char *check_command_line( char **cl, ShellOptions_t *o
|
||||
return PATH_SFTP_SERVER;
|
||||
|
||||
if ( check_command(*cl, opts, PATH_SCP, RSSH_ALLOW_SCP) ){
|
||||
- /* filter -S option */
|
||||
- if ( opt_filter(cl, 'S') ) return NULL;
|
||||
+ if ( !scp_okay(cl) ){
|
||||
+ fprintf(stderr, "\ninsecure scp option not allowed.");
|
||||
+ log_msg("insecure scp option in scp command line");
|
||||
+ return NULL;
|
||||
+ }
|
||||
return PATH_SCP;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user