Merge commit from fork
unzip: reject absolute or traversing symlink targets
This commit is contained in:
1 file changed
+19
-3
+19
-3
@@ -741,6 +741,14 @@ recheck:
|
||||
error("close('%s')", *path);
|
||||
}
|
||||
|
||||
static int
|
||||
pathname_is_insecure(const char* pathname)
|
||||
{
|
||||
return (pathname[0] == '/' ||
|
||||
strncmp(pathname, "../", 3) == 0 ||
|
||||
strstr(pathname, "/../") != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract a zipfile entry: first perform some sanity checks to ensure
|
||||
* that it is either a directory or a regular file and that the path is
|
||||
@@ -760,6 +768,7 @@ static void
|
||||
extract(struct archive *a, struct archive_entry *e)
|
||||
{
|
||||
char *pathname, *realpathname;
|
||||
const char *linktarget;
|
||||
mode_t filetype;
|
||||
char *p, *q;
|
||||
|
||||
@@ -771,15 +780,22 @@ extract(struct archive *a, struct archive_entry *e)
|
||||
filetype = archive_entry_filetype(e);
|
||||
|
||||
/* sanity checks */
|
||||
if (pathname[0] == '/' ||
|
||||
strncmp(pathname, "../", 3) == 0 ||
|
||||
strstr(pathname, "/../") != NULL) {
|
||||
if (pathname_is_insecure(pathname)) {
|
||||
warningx("skipping insecure entry '%s'", pathname);
|
||||
ac(archive_read_data_skip(a));
|
||||
free(pathname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (S_ISLNK(filetype) &&
|
||||
((linktarget = archive_entry_symlink(e)) != NULL) &&
|
||||
pathname_is_insecure(linktarget)) {
|
||||
warningx("skipping insecure symlink '%s' to '%s'", pathname, linktarget);
|
||||
ac(archive_read_data_skip(a));
|
||||
free(pathname);
|
||||
return;
|
||||
}
|
||||
|
||||
/* I don't think this can happen in a zipfile.. */
|
||||
if (!S_ISDIR(filetype) && !S_ISREG(filetype) && !S_ISLNK(filetype)) {
|
||||
warningx("skipping non-regular entry '%s'", pathname);
|
||||
|
||||
Reference in new issue
Block a user