Top Banner
Format String Protection David Brumley Sam Wu June 12 th , 2002
22

Format String Protection David Brumley Sam Wu June 12 th, 2002.

Dec 21, 2015

Download

Documents

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Format String Protection David Brumley Sam Wu June 12 th, 2002.

Format String Protection

David BrumleySam Wu

June 12th, 2002

Page 2: Format String Protection David Brumley Sam Wu June 12 th, 2002.

Format String Attack Basis Similar to buffer overflow attacks, it

relies on altering flow of control to attacking code

Unlike buffer overflow attacks, it takes advantage of C variable argument macros e.g. printf(“%d %n”, a, b) vs

printf(“%d %n”, a)

Page 3: Format String Protection David Brumley Sam Wu June 12 th, 2002.

Expected Contributions of our proposal

A Metric: Previous work has been ad-hoc, and does not generalize

well. General Variatic Solutions:

We propose a generalized solution to dealing with variatic arguments that rely upon ideas first investigated by StackGuard.

Application Specific Protection: We detail statically inserting dynamic checks into format

string specifiers. Thus, coders who don’t want to pay the price of full pointer safety can pay a smaller price for a different safety guarantee.

Page 4: Format String Protection David Brumley Sam Wu June 12 th, 2002.

Actual arguments

Saved IP for main

Saved FP for main

a

Foo’s frame:

Actual arguments

Custom IP (“/bin/sh”)

Saved FP for main

a

Metric: Different Levels of Attacks Level 1: Common

misuse of printf like functions to rewrite return address or frame pointer

e.g. a simplified versionfoo() {

int a;printf(“%d %d %n”);

}main() {

foo();}

-Also possible: double return, multiple returns attack

Page 5: Format String Protection David Brumley Sam Wu June 12 th, 2002.

Guarding Level 1 Attacks Statically:

Type inferencing: Tainted/untainted

analysis Dynamically:

StackGuard: protect the saved

IP and FP from being overwritten by using a random canary

However…….

a

Actual arguments

Saved IP

Canary

Saved FP

with StackGuard…

Page 6: Format String Protection David Brumley Sam Wu June 12 th, 2002.

“Hello World”

Actual arguments

Saved IP

Saved FP

(buf2[5])

“%d %n”

Actual arguments

Saved IP

Saved FP

“abcde”

“%d %n”

Actual arguments

Crafted IP

Saved FP

“abcde”

Level 2 Attacks Also called a “hybrid

attack” Using buffer overflow to

taint the format string specifier

e.g.int main(int argc, char argv[])

{char buf1[] = “Hello World”;char buf2[5];strcpy(buf2, argv[1]);printf(buf1);

}Tainted/untainted analysis says fine

Page 7: Format String Protection David Brumley Sam Wu June 12 th, 2002.

How StackGuard fails… Consider just a

simple format string: printf(“%d %d

%d %n”, a, b, c);

Canary

Actual arguments

Saved IP

Saved FP

int

In theory, you can have any number of % directivesthat eventually would lead you to write anabitrary location on the stack frame…

Canary

Actual arguments

Crafted IP

Saved FP

int

Page 8: Format String Protection David Brumley Sam Wu June 12 th, 2002.

Guarding Level 2 Attacks LibSafe:

Intercepts most library calls and makes sure all buffer writes are within frame bounds

e.g. strcpy, strcat, getwd, gets, fscanf, scanf, realpath, sprintf…

LibVerify: Wraps all functions such

that the integrity of the return address is checked upon function entry and exit

argc, argv[]

Saved IP

Saved FP

Locals for Main

Actual Arguments

IP for Main

FP for Main

Locals for Foo

main:

foo:LibSafe:Writable area

Locals for Main

Actual Arguments

LibVerify:Check integrity

IP for Main

FP for Main

Still yet….

Page 9: Format String Protection David Brumley Sam Wu June 12 th, 2002.

p

argv[]

Saved IP

Saved FP

(buf[30])

p’

argv[]

Saved IP

Saved FP

(buf[30])

Level 3 Attacks An attacker can

construct an arbitrary pointer during run-time

e.g.int func(char argv[]) {

char *p;char buf[30];p = buf;printf(arg[1]);strncpy(p, arg[2], 29);

}

-can set p’ points to the global offset table (GOT) and change printf() to system(), so executing printf(“/bin/sh”) becomes system(“/bin/sh”)

-demonstrates the ability to alter program control flow to an arbitrary execution point

Page 10: Format String Protection David Brumley Sam Wu June 12 th, 2002.

Guarding Level 3 Attacks

However, in the context of dynamic format string, which allows overwriting of (almost) any arbitrary memory location, point-to analysis cannot conclude anything, since any pointer could be rewritten to point to any other data in memory

Bottom line: Dynamic checking is necessary for ensuring

security integrity

Requires full inter-procedural point-to analysis

Page 11: Format String Protection David Brumley Sam Wu June 12 th, 2002.

A Possible Exploit (where LibSafe failed…)

void foo(int c, char *s, …) {int i;char *j;va_list va;

va_start(va, s);j = va_arg(va, char*);printf(“j: %#x @ %#x\n”, *j, j);printf(“abcd: %d%n\n”, 2, j);va_end(va);

}

int main(int argc, char **argv) {int x=0;printf(“before x: %#x @ %#x\n”, x, &x);foo(4, argv[1]);printf(“after x: %#x @ %#x\n”, x, &x);return 0;

}Running yields:[root]./a.outbefore x: 0 @ 0xbffffa04j: 0 @ 0xbffffa04abcd: 2after x: 0x7 @ 0xbffffa04

Page 12: Format String Protection David Brumley Sam Wu June 12 th, 2002.

A Possible Exploit (cont’d)void foo(int c, char *s, …) {

int i;char *j;va_list va;va_start(va, s);j = va_arg(va, char*);printf(“j: %#x @ %#x\n”, *j, j);printf(“abcd: %d%n\n”, 2, j);va_end(va);

}

int main(int argc, char **argv) {int x=0;printf(“before x: %#x @ %#x\n”, x, &x);foo(4, argv[1]);printf(“after x: %#x @ %#x\n”, x, &x);return 0;

}

argc, **argv

Saved IP

Saved FP

x = 0

main:

s = &(argv[1])

c = 4

IP for Main

FP for Main

foo:

Locals for Foo

argc, **argv

Saved IP

Saved FP

x = 7

main:

va

Locals for Foo

j

Page 13: Format String Protection David Brumley Sam Wu June 12 th, 2002.

Recall: the va_list mechanism Recall (as defined in stdarg.h):

void va_start(va_list ap, arg) Sets up ap to point to first variatic argument (aka.

anonymous arguments) placed upon the stack type va_arg(va_list ap, type)

Returns current values pointed to by ap, then advanc ap by sizeof(type)

void va_end(va_list ap) Cleans up ap

This mechanism allows one function body to work with multiple arguments without code duplication.

Page 14: Format String Protection David Brumley Sam Wu June 12 th, 2002.

Our Proposal

Our motivations and goals: To fix variatic functions such that the program is able

to determine at run time where the end of the variatic arguments actually are.

Finer grained than libsafe because it protects against local variables that may be involved in a level 3 attack (recall previous exploit)

Provide a richer functionality than FormatGuard by eliminating attacks in functions that take va_list

Previous work: Has not solved the generic variatic argument and

va_list problem; they instead focused on eliminating format string exploits found in practice

Three potential solutions…

Page 15: Format String Protection David Brumley Sam Wu June 12 th, 2002.

Canary Protection Canary protection:

Push onto the stack a canary value before pushing the function actuals onto the stack. Thus function arguments are guarded up the stack by the canary, and down the stack by the start of the anonymous arguments (i.e. what returned by va_start)

Since both values are known at compile time, the va_arg macro can be modified to insert a dynamic check to make sure all accesses are within these bounds

Page 16: Format String Protection David Brumley Sam Wu June 12 th, 2002.

Canary Protection (cont’d) Example pseudo code:

#define va_arg(x, type) tmp = real_va_arg(x, type)

if (tmp == canary) {set perm errorreturn error

}else

return tmp

Locals

Canary

Actual arguments

Saved FP

Saved IP

Cons :the false canary problem:two pointers check per va_arg

Pros :access via format string (va_list ultimately) is guarded to only the actuals

Page 17: Format String Protection David Brumley Sam Wu June 12 th, 2002.

Add total size of variatic args Redefine variatic arguments to include a total

size of arguments passed to the function as the first paramter

For va_start, this means also returns the total number of bytes in the va_arg

Page 18: Format String Protection David Brumley Sam Wu June 12 th, 2002.

Add total size of variatic args (cont’d)

Pseudo code:#define va_start(x, y) x = va_list(y); va_arg(y);

$non_anonymous_args

3

2

$total_size

1

Pros :allows precise bounding of the anonymous argument total size :no false canary problem

Cons :recompilation of source, as stack offset is now changed

Page 19: Format String Protection David Brumley Sam Wu June 12 th, 2002.

Reorder the stack Change function invocation to push the

functions actuals onto the stack after the saved IP and FP

Pros :one check per va_arg access

Cons :does not protect local variables from misuse

Page 20: Format String Protection David Brumley Sam Wu June 12 th, 2002.

Plans of Actions Require

a protected libc implementation a compiler that emits the proper code

for the bounds check; which we believe to be a medium-hard fix to gcc

a set of tests indicating the performance difference between the three approaches

Page 21: Format String Protection David Brumley Sam Wu June 12 th, 2002.

Related Work Type Qualifiers (e.g. tainted/untainted static analysis)

Detecting possible flow of tainted buffer to supposedly untainted buffer

Require manual annotations and access to source code FormatGuard

Statically insert code to check dynamically number of % directives with the number of actual arguments to printf functions

Does not support vprintf like functions (or functions that use va_list), does not handle pointer to printf functions, does not check type of % directives

Metal Static analysis to find bugs in program Unsound and incomplete: finding bugs is important to security

applications, but is orthogonal to insuring security safety

Page 22: Format String Protection David Brumley Sam Wu June 12 th, 2002.

Related Work (cont’d) StackGuard

Ensure return address integrity by using a random canary Run time overhead and require access to source code, and

possibly recompilation LibSafe

Intercepting and redirecting common string functions to safe versions, thus enforcing buffer write within stack frame bound

Does not prevent the exploit previously presented Fails to protect programs compiled with -fomit-frame-pointer or -

static, functions not defined in libsafe, kernel code, programs that do not have return address followed by frame pointer

LibVerify Wrap all functions and compare return address on function entry

and exit to ensure integrity Require duplication for each function defined (modified function

stored on heap)