Beyond stack smashing: recent advances in exploiting buffer overruns

Download Report

Transcript Beyond stack smashing: recent advances in exploiting buffer overruns

Beyond Stack Smashing: Recent
Advances In Exploiting Buffer
Overruns
Jonathan Pincus and Brandon Baker
Microsoft Researchers
IEEE Security and Privacy , Vol 2, no.4, July 2004.
Presented by
Meenakshi Lakshmikanthan on 03/25/2010
Introduction



Buffer overflows have been the most common form
of security vulnerability for the last ten years.
If buffer overflow vulnerabilities could be effectively
eliminated, a very large portion of the most serious
security threats would also be eliminated.
Buffer overflow vulnerability presents the attacker
the ability to inject and execute attack code.
Buffer Overflow




Buffer Overflow vulnerabilities and attacks come in a variety
of forms.
The traditional approach to exploiting buffer overruns is Stack
Smashing.
Discussions of buffer overrun exploitation in literature
typically concentrate on stack-smashing attacks.
However, over the decade, hackers have developed several
additional approaches to exploit buffer overruns.
Buffer Overflow Types



Stack Smashing
Arc Injection
Pointer Subterfuge





Function Pointer Clobbering
Data Pointer Modification
Exception Handler Hijacking
VPTR Smashing
Heap Smashing
Stack Smashing



Changing the return address of a function thereby
changing the flow of execution of the program.
Execute some code (potentially supplied by the
attacker).
Stack smashing relies on the fact that most C
compilers store the saved return address on the same
stack used for local variables.
Stack Smashing
Void f1a(void * arg, size_t len) {
char buff[100];
memcpy(buff, arg, len);
/* ... */
Return Address
return;
Modification
}

* Buffer overrun if len > 100 *
Arc Injection



Arc injection (return-into-libc), involves transferring control
to code that already exists in the program's memory space.
In other words, the exploit just inserts a new arc (control flow
transfer) into the program’s control flow graph, as opposed to
code injection exploits.
A straightforward version of arc injection is to use a stack
buffer overrun to modify the saved return address to point to a
location already in the program’s address space.
Arc Injection – Example Program
Void system(char * arg) {
check_validity(arg);
R = arg;
target:
execl(R, ...)
}


If an attacker can arrange for R to point to an attacker supplied string and
then jump directly to the location target, thus bypassing the validity check
and assignment, the system will treat the attacker-supplied string as a
command line and execute it.
Void f1a(void * arg, size_t len) {
char buff[100];
Buff > 100
memcpy(buff, arg, len);
/* ... */
return;
}

Assuming Register R contains the address of arg or buff then
Void system(char * arg) {
check_validity(arg);
R = arg;
target:
execl(R, ...)
}

Buffer
Overflow
Return
Address
Arc Injection Cont’

Arc-injection exploits are especially useful when the
program has memory protection which prevents any
area of memory from being simultaneously writeable
and executable.

Because no attacker-supplied code is executed, these
mitigations do not prevent arc injection exploits.
Pointer Subterfuge

A pointer is a variable that contains the address of a
function, array element, or other data structure.

Pointer subterfuge is a general term for exploits that
involve modifying a pointer’s value.

Four varieties of Pointer Subterfuge exist.
Function Pointer Clobbering (Method 1)



Function pointers can be overwritten to transfer
control to attacker-supplied code.
Clobbering a function pointer allows an attacker to
directly transfer control to arbitrary, attacker-supplied
code
When the program executes a call via the function
pointer, the attacker’s code is executed instead of the
originally intended code.
Function Point Clobbering : Example Program








void f2a(void * arg, size_t len) {
char buff[100];
void (*f)() = ...;
memcpy(buff, arg, len); // Buffer Overrun//
Calls the
f();
malicious code
/* ... */
return;
}
Data Pointer Modification (Method 2)



Data pointers can be modified by an attacker when
exploiting a buffer overflow vulnerability.
If a data pointer is used as a target for a subsequent
assignment, attackers can control the address to
modify other memory locations.
In other words, Arbitrary Memory Write occurs
when an attacker can control an address to modify
other memory locations.
Data Pointers – Example Program
void f2b(void * arg, size_t len) {
char buff[100];
long val = ...;
long *ptr = ...;
extern void (*f)();
External Function Pointer
memcpy(buff, arg, len); // Buffer Overrun//
*ptr = val;
f();
/* ... */
return;
}



By overflowing the buffer, an attacker can overwrite ptr and val.
When *ptr = val is evaluated (line 6), an arbitrary memory write is
performed.
Exception Handler Hijacking (Method 3)



Several variations of exploit techniques target the Microsoft
Windows Structured Exception Handling mechanism.
When an exception is generated, Windows examines a linked
list of exception handlers and invokes one of them via a
function pointer stored in the list entry.
Because the list entries are stored on the stack, it is possible to
replace the exception-handler function pointer via buffer
overflow, thus allowing an attacker to transfer control to an
arbitrary location
VPTR Smashing (Method 4)

A virtual function is a function member of a class, declared
using the virtual keyword.

Most C++ compilers implement virtual functions via a virtual
function table (VTBL) associated with each class.

VTBL is a list of function pointers to the virtual functions.

VPTR is the pointer to the VTBL.
VPTR Smashing – Example Program







void f4(void * arg, size_t len) {
char *buff = new char[100];
C *ptr = new C;  New object of class C
memcpy(buff, arg, len); /* buffer overrun! */
ptr->vf(); // Call to a virtual function
return;
}
Heap Smashing

A buffer overrun is characterized as a stack buffer overrun or
heap buffer overrun depending on what memory gets overrun.

Heaps, refer to any dynamic memory implementations such as
the C standard library’s malloc, C++’s new/delete etc.

The key insight behind heap smashing is to exploit the
implementation of the dynamic memory allocator by violating
some assumed invariants.
Heap Smashing Example Program







void f1b(void * arg, size_t len) {
char * ptr = malloc(100);
if (ptr == NULL) return;
memcpy(ptr, arg, len); /* buffer overrun if len >
100 */
/* ... */
return;
}
Heap Smashing - Problems



The attacker typically does not know the heap block’s
location ahead of time and hence it might be difficult
to exploit the heap.
Also, it is difficult to predict when the heap free
operation will occur.
Finally, in some situations, it is difficult to predict
whether the next block has been allocated at the time
the overrun occurs.
Contributions





This paper has attempted to explain the different types of
buffer overflows.
Stack Smashing is the traditional approach which works by
modifying the return address to transfer the control flow.
Heap Smashing works by exploiting the dynamic memory
allocator.
Arc Injection transfers the control to code that already exists
in the program’s memory space.
Pointer Subterfuge methods involve the exploits that modify
a pointer’s value.
Weakness

Heap Smashing Techniques have not been
dealt in detail.

Lot of mismatch between references to the
figure and content.
Thank You!!!!!!!