CVE-2015-1191 (published 2015-01-21T18:59Z)

Multiple directory traversal vulnerabilities in pigz 2.3.1 allow remote attackers to write to arbitrary files via a (1) full pathname or (2) .. (dot dot) in an archive.

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:N/I:P/A:N)

Weakness information:
cwe_id: CWE-22
cwe_name: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
description: The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
extended_description: 
            Many file operations are intended to take place within a restricted directory. By using special elements such as ".." and "/" separators, attackers can escape outside of the restricted location to access files or directories that are elsewhere on the system. One of the most common special elements is the "../" sequence, which in most modern operating systems is interpreted as the parent directory of the current location. This is referred to as relative path traversal. Path traversal also covers the use of absolute pathnames such as "/usr/local/bin" to access unexpected files. This is referred to as absolute path traversal.
         
         

Fix information:
repo_url: https://github.com/madler/pigz
commit_details: repo_url: https://github.com/madler/pigz
author: Mark Adler
author_date: 2015-01-11 20:21:24-08:00
msg: When decompressing with -N or -NT, strip any path from header name.

This uses the path of the compressed file combined with the name
from the header as the name of the decompressed output file.  Any
path information in the header name is stripped.  This avoids a
possible vulnerability where absolute or descending paths are put
in the gzip header.
repository: repo_url: https://github.com/madler/pigz
repo_name: madler/pigz
description: A parallel implementation of gzip for modern multi-processor, multi-core machines.
repo_language: C
owner: madler
file_changes: filename: pigz.c
change_type: ModificationType.MODIFY
diff: @@ -3520,26 +3520,35 @@ local void process(char *path)
                  " (use -f to force)");
     }
     else {
-        char *to, *repl;
-
-        /* use header name for output when decompressing with -N */
-        to = g.inf;
-        if (g.decode && (g.headis & 1) != 0 && g.hname != NULL) {
-            to = g.hname;
-            len = strlen(g.hname);
+        char *to = g.inf, *sufx = "";
+        size_t pre = 0;
+
+        /* select parts of the output file name */
+        if (g.decode) {
+            /* for -dN or -dNT, use the path from the input file and the name
+               from the header, stripping any path in the header name */
+            if ((g.headis & 1) != 0 && g.hname != NULL) {
+                pre = justname(g.inf) - g.inf;
+                to = justname(g.hname);
+                len = strlen(to);
+            }
+            /* for -d or -dNn, replace abbreviated suffixes */
+            else if (strcmp(to + len, ".tgz") == 0)
+                sufx = ".tar";
         }
-
-        /* replace .tgz with .tar when decoding */
-        repl = g.decode && strcmp(to + len, ".tgz") ? "" : ".tar";
+        else
+            /* add appropriate suffix when compressing */
+            sufx = g.sufx;
 
         /* create output file and open to write */
-        g.outf = MALLOC(len + (g.decode ? strlen(repl) : strlen(g.sufx)) + 1);
+        g.outf = MALLOC(pre + len + strlen(sufx) + 1);
         if (g.outf == NULL)
             bail("not enough memory", "");
-        memcpy(g.outf, to, len);
-        strcpy(g.outf + len, g.decode ? repl : g.sufx);
+        memcpy(g.outf, g.inf, pre);
+        memcpy(g.outf + pre, to, len);
+        strcpy(g.outf + pre + len, sufx);
         g.outd = open(g.outf, O_CREAT | O_TRUNC | O_WRONLY |
-                             (g.force ? 0 : O_EXCL), 0600);
+                              (g.force ? 0 : O_EXCL), 0600);
 
         /* if exists and not -f, give user a chance to overwrite */
         if (g.outd < 0 && errno == EEXIST && isatty(0) && g.verbosity) {

programming_language: Markdown