CVE-2013-4788 - Eglibc PTR MANGLE vulnerability
Description
This vulnerability was discovered in March 2013 while we were developing the RAF SSP technique.
The glibc vulnerability makes it easy to take advantage of common errors such as buffer overflows
allows in these cases redirect the execution flow and potentially execute arbitrary
code.
Impact
All statically linked applications compiled with glibc and eglibc are affected,
independent of the operating system distribution. Note that this problem is not solved by
only patching the eglibc, but it is also necessary to recompile all static executables.
As far I know there are a lot of routers, embedded systems etc., which use static linked
applications. Since the vulnerability is from the beginning of the PTR_MANGLE implementations
(years 2005-2006) there are a ton of vulnerable devices.
Vulnerable packages
The vulnerability has been propagated to all the static code compiled with all versions, on all
architectures, of glibc from 2.4 (06-Mar-2006) to 2.17 (Current version).
Vulnerability
The vulnerability is caused due to the non initialization to a random value (it is
always zero) of the "pointer guard" by the glibc only when generating static compiled
executables. Dynamic executables are not affected.
Pointer guard is used to mangle the content of sensible pointers (longjmp, signal
handlers, etc.), if the pointer guard value is zero (non-initialized) then it is not
effective.
An example:
Library functions like "setjmp()" or "longjmp()" use PTR_MANGLE and
PTR_DEMANGLE. These macros are used to protect structures like jmp_buf. Basically
consist on XOR-ing the pointer value with a random 32/64-bit value. Since the
pointer guard (random value) is 0x0 the attacker can easily calculate off-line the
value of a target address. By overwriting the "env" structure with the pre-computed
address the vulnerability is triggered when longjmp() is called and the execution
flow is redirected to attacker address.
Exploit
The vulnerability was tested with Debian 7.1 and Ubunu 12.04 LTS and 13.04).
I already created a proof of concept to exploit this vulnerability for
32 and 64 bits x86 architectures as well as ARM.
The proof of concept poc-bug-mangle.c redirect the execution flow to a
function which prompt a shell. This exploit can be compiled for i386,
x86_64 and ARM architectures. More architectures can be added easily by adding the
correspondent defines.
Compilation for i386:
$ gcc poc-bug-mangle.c -o poc-bug-mangle -static
Compilation for x86_64:
$ gcc poc-bug-mangle.c -o poc-bug-mangle_32 -static -m32
$ gcc poc-bug-mangle.c -o poc-bug-mangle_64 -static -m64
Execution output:
$ ./poc-bug-mangle_32
[+] Exploiting ...
[+] hacked !!
$
Compilation for ARM on x86:
$ arm-linux-gnueabi-gcc poc-bug-mangle.c -o poc-bug-mangle_arm -static
Execution output on non-native ARM:
$ qemu-arm ./poc-bug-mangle_arm
[+] Exploiting ...
[+] hacked !!
$
Note: Pointer mangling is not yet supported on ARM for eglibc <= 2.17
FIX
Note that the bug can not be fixed only by patching the eglibc. It is necessary
to recompile all static executables. I have created a non official patch for eglibc-2.17.
Patch for eglibc 2.17:
diff -rupN glibc-2.17/csu/libc-start.c glibc-2.17-mangle-fix/csu/libc-start.c
--- glibc-2.17/csu/libc-start.c 2012-12-25 04:02:13.000000000 +0100
+++ glibc-2.17-mangle-fix/csu/libc-start.c 2013-07-10 00:13:48.000000000 +0200
@@ -38,6 +38,12 @@ extern void __pthread_initialize_minimal
in thread local area. */
uintptr_t __stack_chk_guard attribute_relro;
# endif
+
+# ifndef THREAD_SET_POINTER_GUARD
+uintptr_t __pointer_chk_guard_local
+ attribute_relro attribute_hidden __attribute__ ((nocommon));
+# endif
+
#endif
#ifdef HAVE_PTR_NTHREADS
@@ -184,6 +190,14 @@ LIBC_START_MAIN (int (*main) (int, char
# else
__stack_chk_guard = stack_chk_guard;
# endif
+ uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,
+ stack_chk_guard);
+# ifdef THREAD_SET_POINTER_GUARD
+ THREAD_SET_POINTER_GUARD (pointer_chk_guard);
+# else
+ __pointer_chk_guard_local = pointer_chk_guard;
+# endif
+
#endif
/* Register the destructor of the dynamic linker if there is any. */
[ ptr_mangle-eglibc-2.17.patch ]
Patching eglibc-2.17:
$ wget http://hmarco.org/bugs/patches/ptr_mangle-eglibc-2.17.patch
$ cd glibc-2.17
$ patch -p1 < ../ptr_mangle-eglibc-2.17.patch
Discussion
Although this vulnerability is not exploitable by itself, the truth is that the PTR
Mangle encryption is useless. The goal of the protection technique is
not achieved.
This can be seen as the canary stack is set to 0x0, although is not exploitable
by itself is clearly an issue. What about whether the canary has been set to
zero from 2006 to today ? This is what happened with the pointers protected
with this mechanism.
According to Ulrich Drepper
to use "encryption pointers (instead of canaries) to protect structures
like jmp_buf is at least as secure and in addition faster". Following the
above and since the protection mechanism is useless from the first implementation,
the number of potentially affected systems could be huge.
Hector Marco - http://hmarco.org