Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


Presentation on theme: "Format String Protection David Brumley Sam Wu June 12 th, 2002."— Presentation transcript:

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

2 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)

3 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.

4 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 version foo() { int a; printf(“%d %d %n”); } main() { foo(); } -Also possible: double return, multiple returns attack

5 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…

6 “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

7 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 % directives that eventually would lead you to write an abitrary location on the stack frame… Canary Actual arguments Crafted IP Saved FP int

8 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….

9 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

10 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

11 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.out before x: 0 @ 0xbffffa04 j: 0 @ 0xbffffa04 abcd: 2 after x: 0x7 @ 0xbffffa04

12 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

13 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.

14 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…

15 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

16 Canary Protection (cont’d) Example pseudo code: #define va_arg(x, type) tmp = real_va_arg(x, type) if (tmp == canary) { set perm error return 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

17 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

18 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

19 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

20 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

21 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

22 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)


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

Similar presentations


Ads by Google