Hi, attached is an NMU proposal to fix this bug just in case you have no time to fix this.
For this I needed to backport the patch cause it won't apply with the version in Debian. It will be also archived on: http://people.debian.org/~nion/nmu-diff/rsync-2.6.4-6_2.6.4-6.1.patch Kind regards Nico -- Nico Golde - http://www.ngolde.de - [EMAIL PROTECTED] - GPG: 0x73647CFF For security reasons, all text in this mail is double-rot13 encrypted.
diff -u rsync-2.6.4/rsyncd.conf.5 rsync-2.6.4/rsyncd.conf.5 --- rsync-2.6.4/rsyncd.conf.5 +++ rsync-2.6.4/rsyncd.conf.5 @@ -152,12 +152,15 @@ holes, but it has the disadvantages of requiring super-user privileges, of not being able to follow symbolic links that are either absolute or outside of the new root path, and of complicating the preservation of usernames and groups -(see below)\&. When \(lquse chroot\(rq is false, for security reasons, -symlinks may only be relative paths pointing to other files within the root -path, and leading slashes are removed from most absolute paths (options -such as \fB\-\-backup\-dir\fP, \fB\-\-compare\-dest\fP, etc\&. interpret an absolute path as -rooted in the module's \(lqpath\(rq dir, just as if chroot was specified)\&. -The default for \(lquse chroot\(rq is true\&. ++(see below)\&. When "use chroot" is false, rsync will: (1) munge symlinks by ++default for security reasons (see "munge symlinks" for a way to turn this ++off, but only if you trust your users), (2) substitute leading slashes in ++absolute paths with the module\&'s path (so that options such as ++\fB\-\-backup\-dir\fP, \fB\-\-compare\-dest\fP, etc\&. interpret an absolute path as ++rooted in the module\&'s "path" dir), and (3) trim "\&.\&." path elements from ++args if rsync believes they would escape the chroot\&. ++The default for "use chroot" is true, and is the safer choice (especially ++if the module is not read-only)\&. .IP In order to preserve usernames and groupnames, rsync needs to be able to use the standard library functions for looking up names and IDs (i\&.e\&. @@ -181,6 +184,41 @@ do this automatically, but you might as well specify both to be extra sure)\&. .IP +.IP "\fBmunge symlinks\fP" +The "munge symlinks" option tells rsync to modify +all incoming symlinks in a way that makes them unusable but recoverable +(see below)\&. This should help protect your files from user trickery when +your daemon module is writable\&. The default is disabled when "use chroot" +is on and enabled when "use chroot" is off\&. +.IP +If you disable this option on a daemon that is not read-only, there +are tricks that a user can play with uploaded symlinks to access +daemon-excluded items (if your module has any), and, if "use chroot" +is off, rsync can even be tricked into showing or changing data that +is outside the module\&'s path (as access-permissions allow)\&. +.IP +The way rsync disables the use of symlinks is to prefix each one with +the string "/rsyncd-munged/"\&. This prevents the links from being used +as long as that directory does not exist\&. When this option is enabled, +rsync will refuse to run if that path is a directory or a symlink to +a directory\&. When using the "munge symlinks" option in a chroot area, +you should add this path to the exclude setting for the module so that +the user can\&'t try to create it\&. +.IP +Note: rsync makes no attempt to verify that any pre-existing symlinks in +the hierarchy are as safe as you want them to be\&. If you setup an rsync +daemon on a new area or locally add symlinks, you can manually protect your +symlinks from being abused by prefixing "/rsyncd-munged/" to the start of +every symlink\&'s value\&. There is a perl script in the support directory +of the source code named "munge-symlinks" that can be used to add or remove +this prefix from your symlinks\&. +.IP +When this option is disabled on a writable module and "use chroot" is off, +incoming symlinks will be modified to drop a leading slash and to remove "\&.\&." +path elements that rsync believes will allow a symlink to escape the module\&'s +hierarchy\&. There are tricky ways to work around this, though, so you had +better trust your users if you choose this combination of options\&. +.IP .IP "\fBport\fP" You can override the default port the daemon will listen on by specifying this value (defaults to 873)\&. This is ignored if the daemon diff -u rsync-2.6.4/debian/changelog rsync-2.6.4/debian/changelog --- rsync-2.6.4/debian/changelog +++ rsync-2.6.4/debian/changelog @@ -1,3 +1,16 @@ +rsync (2.6.4-6.1) unstable; urgency=high + + * Non-maintainer upload by testing-security team. + * This update addresses the following security issues (Closes: #453652): + - When "use chroot" option is disabled, a programming error + can be exploited by a user to trick rsync into creating a + symlink that points outside the module's hierarchy. + - A programming error within the "exclude", "exclude from" and "filter" + options can be exploited via a symlink attack to gain access + to hidden files if the filename is known. + + -- Nico Golde <[EMAIL PROTECTED]> Fri, 30 Nov 2007 13:08:39 +0100 + rsync (2.6.4-6) unstable; urgency=high * Fixed grave bug: diff -u rsync-2.6.4/loadparm.c rsync-2.6.4/loadparm.c --- rsync-2.6.4/loadparm.c +++ rsync-2.6.4/loadparm.c @@ -123,6 +123,7 @@ BOOL read_only; BOOL write_only; BOOL list; + BOOL munge_symlinks; BOOL use_chroot; BOOL transfer_logging; BOOL ignore_errors; @@ -157,6 +158,7 @@ True, /* read only */ False, /* write only */ True, /* list */ + (BOOL)-1, /* munge symlinks */ True, /* use chroot */ False, /* transfer logging */ False, /* ignore errors */ @@ -304,6 +306,7 @@ {"transfer logging", P_BOOL, P_LOCAL, &sDefault.transfer_logging,NULL,0}, {"ignore errors", P_BOOL, P_LOCAL, &sDefault.ignore_errors,NULL,0}, {"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL, 0}, + {"munge symlinks", P_BOOL, P_LOCAL, &sDefault.munge_symlinks, NULL,0}, {"refuse options", P_STRING, P_LOCAL, &sDefault.refuse_options,NULL, 0}, {"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress,NULL, 0}, {NULL, P_BOOL, P_NONE, NULL, NULL, 0} @@ -370,6 +373,7 @@ FN_LOCAL_BOOL(lp_read_only, read_only) FN_LOCAL_BOOL(lp_write_only, write_only) FN_LOCAL_BOOL(lp_list, list) +FN_LOCAL_BOOL(lp_munge_symlinks, munge_symlinks) FN_LOCAL_BOOL(lp_use_chroot, use_chroot) FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging) FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors) diff -u rsync-2.6.4/clientserver.c rsync-2.6.4/clientserver.c --- rsync-2.6.4/clientserver.c +++ rsync-2.6.4/clientserver.c @@ -53,6 +53,7 @@ char *auth_user; int read_only = 0; int daemon_log_format_has_i = 0; +int munge_symlinks = 0; int daemon_log_format_has_o_or_i = 0; int module_id = -1; @@ -387,6 +388,18 @@ sanitize_paths = 1; } + if ((munge_symlinks = lp_munge_symlinks(i)) < 0) + munge_symlinks = !use_chroot; + if (munge_symlinks) { + STRUCT_STAT st; + if (stat(SYMLINK_PREFIX, &st) == 0 && S_ISDIR(st.st_mode)) { + rprintf(FLOG, "Symlink munging is unsupported when a %s directory exists.\n", + SYMLINK_PREFIX); + io_printf(f_out, "@ERROR: daemon security issue -- contact admin\n", name); + exit_cleanup(RERR_UNSUPPORTED); + } + } + if (am_root) { /* XXXX: You could argue that if the daemon is started * by a non-root user and they explicitly specify a diff -u rsync-2.6.4/proto.h rsync-2.6.4/proto.h --- rsync-2.6.4/proto.h +++ rsync-2.6.4/proto.h @@ -149,6 +149,7 @@ BOOL lp_read_only(int ); BOOL lp_write_only(int ); BOOL lp_list(int ); +BOOL lp_munge_symlinks(int ); BOOL lp_use_chroot(int ); BOOL lp_transfer_logging(int ); BOOL lp_ignore_errors(int ); only in patch2: unchanged: --- rsync-2.6.4.orig/support/munge-symlinks +++ rsync-2.6.4/support/munge-symlinks @@ -0,0 +1,60 @@ +#!/usr/bin/perl +# This script will either prefix all symlink values with the string +# "/rsyncd-munged/" or remove that prefix. + +use strict; +use Getopt::Long; + +my $SYMLINK_PREFIX = '/rsyncd-munged/'; + +my $munge_opt; + +&GetOptions( + 'munge' => sub { $munge_opt = 1 }, + 'unmunge' => sub { $munge_opt = 0 }, + 'all' => \( my $all_opt ), + 'help|h' => \( my $help_opt ), +) or &usage; + +&usage if $help_opt || !defined $munge_opt; + +my $munged_re = $all_opt ? qr/^($SYMLINK_PREFIX)+(?=.)/ : qr/^$SYMLINK_PREFIX(?=.)/; + +push(@ARGV, '.') unless @ARGV; + +open(PIPE, '-|', 'find', @ARGV, '-type', 'l') or die $!; + +while (<PIPE>) { + chomp; + my $lnk = readlink($_) or next; + if ($munge_opt) { + next if !$all_opt && $lnk =~ /$munged_re/; + $lnk =~ s/^/$SYMLINK_PREFIX/; + } else { + next unless $lnk =~ s/$munged_re//; + } + if (!unlink($_)) { + warn "Unable to unlink symlink: $_ ($!)\n"; + } elsif (!symlink($lnk, $_)) { + warn "Unable to recreate symlink: $_ -> $lnk ($!)\n"; + } else { + print "$_ -> $lnk\n"; + } +} + +close PIPE; +exit; + +sub usage +{ + die <<EOT; +Usage: munge-symlinks --munge|--unmunge [--all] [DIR|SYMLINK...] + +--munge Add the $SYMLINK_PREFIX prefix to symlinks if not already + present, or always when combined with --all. +--unmunge Remove one $SYMLINK_PREFIX prefix from symlinks or all + such prefixes with --all. + +See the "munge symlinks" option in the rsyncd.conf manpage for more details. +EOT +} only in patch2: unchanged: --- rsync-2.6.4.orig/la.patch +++ rsync-2.6.4/la.patch @@ -0,0 +1,67 @@ +--- rsync-2.6.9/rsyncd.conf.5 2006-11-06 20:39:52.000000000 -0800 ++++ ./rsyncd.conf.5 2007-11-27 13:15:23.000000000 -0800 +@@ -145,12 +145,15 @@ the advantage of extra protection agains + holes, but it has the disadvantages of requiring super-user privileges, + of not being able to follow symbolic links that are either absolute or outside + of the new root path, and of complicating the preservation of usernames and groups +-(see below)\&. When "use chroot" is false, for security reasons, +-symlinks may only be relative paths pointing to other files within the root +-path, and leading slashes are removed from most absolute paths (options +-such as \fB\-\-backup\-dir\fP, \fB\-\-compare\-dest\fP, etc\&. interpret an absolute path as +-rooted in the module\&'s "path" dir, just as if chroot was specified)\&. +-The default for "use chroot" is true\&. ++(see below)\&. When "use chroot" is false, rsync will: (1) munge symlinks by ++default for security reasons (see "munge symlinks" for a way to turn this ++off, but only if you trust your users), (2) substitute leading slashes in ++absolute paths with the module\&'s path (so that options such as ++\fB\-\-backup\-dir\fP, \fB\-\-compare\-dest\fP, etc\&. interpret an absolute path as ++rooted in the module\&'s "path" dir), and (3) trim "\&.\&." path elements from ++args if rsync believes they would escape the chroot\&. ++The default for "use chroot" is true, and is the safer choice (especially ++if the module is not read-only)\&. + .IP + In order to preserve usernames and groupnames, rsync needs to be able to + use the standard library functions for looking up names and IDs (i\&.e\&. +@@ -181,6 +184,41 @@ access to some of the excluded files ins + do this automatically, but you might as well specify both to be extra + sure)\&. + .IP ++.IP "\fBmunge symlinks\fP" ++The "munge symlinks" option tells rsync to modify ++all incoming symlinks in a way that makes them unusable but recoverable ++(see below)\&. This should help protect your files from user trickery when ++your daemon module is writable\&. The default is disabled when "use chroot" ++is on and enabled when "use chroot" is off\&. ++.IP ++If you disable this option on a daemon that is not read-only, there ++are tricks that a user can play with uploaded symlinks to access ++daemon-excluded items (if your module has any), and, if "use chroot" ++is off, rsync can even be tricked into showing or changing data that ++is outside the module\&'s path (as access-permissions allow)\&. ++.IP ++The way rsync disables the use of symlinks is to prefix each one with ++the string "/rsyncd-munged/"\&. This prevents the links from being used ++as long as that directory does not exist\&. When this option is enabled, ++rsync will refuse to run if that path is a directory or a symlink to ++a directory\&. When using the "munge symlinks" option in a chroot area, ++you should add this path to the exclude setting for the module so that ++the user can\&'t try to create it\&. ++.IP ++Note: rsync makes no attempt to verify that any pre-existing symlinks in ++the hierarchy are as safe as you want them to be\&. If you setup an rsync ++daemon on a new area or locally add symlinks, you can manually protect your ++symlinks from being abused by prefixing "/rsyncd-munged/" to the start of ++every symlink\&'s value\&. There is a perl script in the support directory ++of the source code named "munge-symlinks" that can be used to add or remove ++this prefix from your symlinks\&. ++.IP ++When this option is disabled on a writable module and "use chroot" is off, ++incoming symlinks will be modified to drop a leading slash and to remove "\&.\&." ++path elements that rsync believes will allow a symlink to escape the module\&'s ++hierarchy\&. There are tricky ways to work around this, though, so you had ++better trust your users if you choose this combination of options\&. ++.IP + .IP "\fBmax connections\fP" + The "max connections" option allows you to + specify the maximum number of simultaneous connections you will allow\&. + only in patch2: unchanged: --- rsync-2.6.4.orig/flist.c +++ rsync-2.6.4/flist.c @@ -47,6 +47,7 @@ extern int preserve_links; extern int preserve_hard_links; extern int preserve_perms; +extern int munge_symlinks; extern int preserve_devices; extern int preserve_uid; extern int preserve_gid; @@ -189,6 +190,11 @@ } return do_stat(path, buffer); } + if (munge_symlinks && am_sender && l > SYMLINK_PREFIX_LEN + && strncmp(linkbuf, SYMLINK_PREFIX, SYMLINK_PREFIX_LEN) == 0) { + memmove(linkbuf, linkbuf + SYMLINK_PREFIX_LEN, + l - SYMLINK_PREFIX_LEN + 1); + } } return 0; #else @@ -533,8 +539,7 @@ in_del_hier = 0; return NULL; } - - if (flags & XMIT_SAME_NAME) +if (flags & XMIT_SAME_NAME) l1 = read_byte(f); if (flags & XMIT_LONG_NAME) @@ -613,6 +618,8 @@ linkname_len - 1); overflow("receive_file_entry"); } + if (munge_symlinks) + linkname_len += SYMLINK_PREFIX_LEN; } else #endif @@ -676,10 +683,17 @@ #ifdef SUPPORT_LINKS if (linkname_len) { file->u.link = bp; + if (munge_symlinks) { + strlcpy(bp, SYMLINK_PREFIX, linkname_len); + bp += SYMLINK_PREFIX_LEN; + linkname_len -= SYMLINK_PREFIX_LEN; + } read_sbuf(f, bp, linkname_len - 1); - if (sanitize_paths) + if (sanitize_paths && !munge_symlinks) { sanitize_path(bp, bp, "", lastdir_depth); - bp += linkname_len; + bp += strlen(bp) + 1; + } else + bp += linkname_len; } #endif only in patch2: unchanged: --- rsync-2.6.4.orig/rsync.h +++ rsync-2.6.4/rsync.h @@ -33,6 +33,9 @@ #define DEFAULT_LOCK_FILE "/var/run/rsyncd.lock" #define URL_PREFIX "rsync://" +#define SYMLINK_PREFIX "/rsyncd-munged/" +#define SYMLINK_PREFIX_LEN ((int)sizeof SYMLINK_PREFIX - 1) + #define BACKUP_SUFFIX "~" /* a non-zero CHAR_OFFSET makes the rolling sum stronger, but is only in patch2: unchanged: --- rsync-2.6.4.orig/testsuite/rsync.fns +++ rsync-2.6.4/testsuite/rsync.fns @@ -204,6 +204,7 @@ pid file = $pidfile use chroot = no +munge symlinks = no hosts allow = localhost, 127.0.0.1 log file = $logfile exclude = foobar.baz only in patch2: unchanged: --- rsync-2.6.4.orig/rsyncd.conf.yo +++ rsync-2.6.4/rsyncd.conf.yo @@ -136,12 +136,15 @@ holes, but it has the disadvantages of requiring super-user privileges, of not being able to follow symbolic links that are either absolute or outside of the new root path, and of complicating the preservation of usernames and groups -(see below). When "use chroot" is false, for security reasons, -symlinks may only be relative paths pointing to other files within the root -path, and leading slashes are removed from most absolute paths (options -such as bf(--backup-dir), bf(--compare-dest), etc. interpret an absolute path as -rooted in the module's "path" dir, just as if chroot was specified). -The default for "use chroot" is true. +(see below). When "use chroot" is false, rsync will: (1) munge symlinks by +default for security reasons (see "munge symlinks" for a way to turn this +off, but only if you trust your users), (2) substitute leading slashes in +absolute paths with the module's path (so that options such as +bf(--backup-dir), bf(--compare-dest), etc. interpret an absolute path as +rooted in the module's "path" dir), and (3) trim ".." path elements from +args if rsync believes they would escape the chroot. +The default for "use chroot" is true, and is the safer choice (especially +if the module is not read-only). In order to preserve usernames and groupnames, rsync needs to be able to use the standard library functions for looking up names and IDs (i.e. @@ -165,6 +168,40 @@ do this automatically, but you might as well specify both to be extra sure). +dit(bf(munge symlinks)) The "munge symlinks" option tells rsync to modify +all incoming symlinks in a way that makes them unusable but recoverable +(see below). This should help protect your files from user trickery when +your daemon module is writable. The default is disabled when "use chroot" +is on and enabled when "use chroot" is off. + +If you disable this option on a daemon that is not read-only, there +are tricks that a user can play with uploaded symlinks to access +daemon-excluded items (if your module has any), and, if "use chroot" +is off, rsync can even be tricked into showing or changing data that +is outside the module's path (as access-permissions allow). + +The way rsync disables the use of symlinks is to prefix each one with +the string "/rsyncd-munged/". This prevents the links from being used +as long as that directory does not exist. When this option is enabled, +rsync will refuse to run if that path is a directory or a symlink to +a directory. When using the "munge symlinks" option in a chroot area, +you should add this path to the exclude setting for the module so that +the user can't try to create it. + +Note: rsync makes no attempt to verify that any pre-existing symlinks in +the hierarchy are as safe as you want them to be. If you setup an rsync +daemon on a new area or locally add symlinks, you can manually protect your +symlinks from being abused by prefixing "/rsyncd-munged/" to the start of +every symlink's value. There is a perl script in the support directory +of the source code named "munge-symlinks" that can be used to add or remove +this prefix from your symlinks. + +When this option is disabled on a writable module and "use chroot" is off, +incoming symlinks will be modified to drop a leading slash and to remove ".." +path elements that rsync believes will allow a symlink to escape the module's +hierarchy. There are tricky ways to work around this, though, so you had +better trust your users if you choose this combination of options. + dit(bf(port)) You can override the default port the daemon will listen on by specifying this value (defaults to 873). This is ignored if the daemon is being run by inetd, and is superseded by the bf(--port) command-line option.
pgpz5KmFTCKr8.pgp
Description: PGP signature