Date: 18 Aug 2004 15:13:22 -0000 From: Rudolf Polzer <freebsd-dr@durchnull.de> To: FreeBSD-gnats-submit@FreeBSD.org Cc: bug-a2ps@gnu.org Subject: ports/70618: print/a2ps-* using "file -L %s" as shell argument --> dangerous to use it in world-writable directories Message-ID: <20040818151322.64321.qmail@durchnull.ath.cx> Resent-Message-ID: <200408181520.i7IFKQiO031557@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 70618 >Category: ports >Synopsis: print/a2ps-* using "file -L %s" as shell argument --> dangerous to use it in world-writable directories >Confidential: no >Severity: critical >Priority: high >Responsible: freebsd-ports-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Aug 18 15:20:26 GMT 2004 >Closed-Date: >Last-Modified: >Originator: Rudolf Polzer >Release: FreeBSD 5.2.1-RELEASE-p9 i386 >Organization: >Environment: System: FreeBSD katsuragi.durchnull.ath.cx 5.2.1-RELEASE-p9 FreeBSD 5.2.1-RELEASE-p9 #19: Thu Jul 1 11:20:21 CEST 2004 root@katsuragi.durchnull.ath.cx:/usr/src/sys/i386/compile/DIV0_KERNEL i386 >Description: a2ps builds a command line for file() containing an unescaped version of the file name, thus might call external programs described by the file name. Running a cronjob over a public writable directory a2ps-ing all files in it - or simply typing "a2ps *.txt" in /tmp - is therefore dangerous. >How-To-Repeat: rpolzer:/tmp 7> touch 'x`echo>&2 42`' rpolzer:/tmp 8> a2ps -o /dev/null 'x`echo>&2 42`' 42 [x`echo>&2 42` (plain): 0 pages on 0 sheets] [Total: 0 pages on 0 sheets] saved into the file `/dev/null' >Fix: Apply this patch (can be directly put into files/): diff -ru ../a2ps-4.13.orig/src/select.c ./src/select.c --- ../a2ps-4.13.orig/src/select.c Wed Aug 18 16:32:09 2004 +++ ./src/select.c Wed Aug 18 16:49:12 2004 @@ -131,6 +131,36 @@ return 1; } +/* escapes the name of a file so that the shell groks it in 'single' q.marks. + The resulting pointer has to be free()ed when not longer used. */ +char * +shell_escape(const char *fn) +{ + size_t len = 0; + const char *inp; + char *retval, *outp; + + for(inp = fn; *inp; ++inp) + switch(*inp) + { + case '\'': len += 4; break; + default: len += 1; break; + } + + outp = retval = malloc(len + 1); + if(!outp) + return ""; /* perhaps one should do better error handling here */ + for(inp = fn; *inp; ++inp) + switch(*inp) + { + case '\'': *outp++ = '\''; *outp++ = '\\'; *outp++ = '\'', *outp++ = '\''; break; + default: *outp++ = *inp; break; + } + *outp = 0; + + return retval; +} + /* What says file about the type of a file (result is malloc'd). NULL if could not be run. */ @@ -144,11 +174,13 @@ if (IS_EMPTY (job->file_command)) return NULL; + filename = shell_escape(filename); /* Call file(1) with the correct option */ - command = ALLOCA (char, (2 + command = ALLOCA (char, (4 + strlen (job->file_command) + ustrlen (filename))); - sprintf (command, "%s %s", job->file_command, (const char *) filename); + sprintf (command, "%s '%s'", job->file_command, (const char *) filename); + free(filename); message (msg_tool, (stderr, "Reading pipe: `%s'\n", command)); file_out = popen (command, "r"); >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040818151322.64321.qmail>