From: abbotti Date: Sat, 11 Jan 2003 20:12:35 +0000 (-0800) Subject: [svn] Fix for FTP directory traversal vulnerability (at least for Unix). X-Git-Tag: v1.13~1740 X-Git-Url: http://sjero.net/git/?p=wget;a=commitdiff_plain;h=0410411939779406b26f5b06ff25213c28d1b75c [svn] Fix for FTP directory traversal vulnerability (at least for Unix). Based on a patch by Red Hat. Published in <85u02vg4hukbc2fltdd51uds5oq14rd92f@farscape.privy.mev.co.uk>. --- diff --git a/src/ChangeLog b/src/ChangeLog index 13436c66..4dcc6d62 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,15 @@ +2003-01-11 Ian Abbott + + * ftp.c (ftp_retrieve_glob): Reject insecure filenames as determined + by calling new function has_insecure_name_p. This is based on a + patch by Red Hat. + + * fnmatch.c (has_insecure_name_p): New function: returns non-zero + if filename starts with `/' or contains `../' and is therefore + considered insecure. + + * fnmatch.h: Declare has_insecure_name_p(). + 2002-08-03 Hrvoje Niksic * init.c (cmd_file): Allocate RESULT correctly. diff --git a/src/fnmatch.c b/src/fnmatch.c index 6689a1be..39bf6e01 100644 --- a/src/fnmatch.c +++ b/src/fnmatch.c @@ -35,6 +35,11 @@ so, delete this exception statement from your version. */ #include #include "wget.h" +#ifdef HAVE_STRING_H +# include +#else +# include +#endif /* HAVE_STRING_H */ #include "fnmatch.h" /* Match STRING against the filename pattern PATTERN, returning zero @@ -198,6 +203,19 @@ fnmatch (const char *pattern, const char *string, int flags) return (FNM_NOMATCH); } +/* Return non-zero if S has a leading '/' or contains '../' */ +int +has_insecure_name_p (const char *s) +{ + if (*s == '/') + return 1; + + if (strstr(s, "../") != 0) + return 1; + + return 0; +} + /* Return non-zero if S contains globbing wildcards (`*', `?', `[' or `]'). */ int diff --git a/src/fnmatch.h b/src/fnmatch.h index d134672e..a3449aaa 100644 --- a/src/fnmatch.h +++ b/src/fnmatch.h @@ -40,6 +40,7 @@ so, delete this exception statement from your version. */ #define FNM_NOMATCH 1 int fnmatch PARAMS ((const char *, const char *, int)); +int has_insecure_name_p PARAMS ((const char *s)); int has_wildcards_p PARAMS ((const char *)); #endif /* FNMATCH_H */ diff --git a/src/ftp.c b/src/ftp.c index 2ffd1c17..c49f25e9 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -1593,7 +1593,7 @@ Not descending to `%s' as it is excluded/not-included.\n"), newdir); static uerr_t ftp_retrieve_glob (struct url *u, ccon *con, int action) { - struct fileinfo *orig, *start; + struct fileinfo *f, *orig, *start; uerr_t res; con->cmd |= LEAVE_PENDING; @@ -1606,8 +1606,7 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action) opt.accepts and opt.rejects. */ if (opt.accepts || opt.rejects) { - struct fileinfo *f = orig; - + f = orig; while (f) { if (f->type != FT_DIRECTORY && !acceptable (f->name)) @@ -1619,13 +1618,25 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action) f = f->next; } } + /* Remove all files with possible harmful names */ + f = orig; + while (f) + { + if (has_insecure_name_p(f->name)) + { + logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name); + f = delelement (f, &start); + } + else + f = f->next; + } /* Now weed out the files that do not match our globbing pattern. If we are dealing with a globbing pattern, that is. */ if (*u->file && (action == GLOBALL || action == GETONE)) { int matchres = 0; - struct fileinfo *f = start; + f = start; while (f) { matchres = fnmatch (u->file, f->name, 0);