Defending against Memory Corruption Vulnerabilities and Advanced - - PowerPoint PPT Presentation

defending against memory corruption vulnerabilities and
SMART_READER_LITE
LIVE PREVIEW

Defending against Memory Corruption Vulnerabilities and Advanced - - PowerPoint PPT Presentation

Defending against Memory Corruption Vulnerabilities and Advanced Attacks Gang Tan Penn State University Spring 2019 CMPSC 447, Software Security * some slides adapted from those by Trent Jaeger Overflow Vulnerabilities Despite


slide-1
SLIDE 1

Defending against Memory‐ Corruption Vulnerabilities and Advanced Attacks

Gang Tan Penn State University Spring 2019

CMPSC 447, Software Security * some slides adapted from those by Trent Jaeger

slide-2
SLIDE 2

Overflow Vulnerabilities

 Despite knowledge of buffer overflows for over

40 years, they have not been eliminated

 This is partly due to the wide variety of exploit

  • ptions

 Variety of targets: can exploit more than return

addresses – any code addresses or data

 Variety of uses: can exploit on read and write  Variety of exploits: can inject or reuse code  Variety of workarounds: current defenses are

incomplete

slide-3
SLIDE 3

6

Defense

 We can take countermeasures at different

points in time

 before we even begin programming  during development  when testing  when code is running  Next we will discuss mostly two kinds  Detection and mitigation at runtime  Prevention during development

  • Defensive programming

 Prevention during compilation

slide-4
SLIDE 4

Detection: Stack Canaries

 AKA stack cookies  Introduced in StackGuard in gcc  A dummy (or random) value is written on the

stack in front of the return address and checked when function returns

 A careless stack overflow will overwrite the

canary, which can then be detected

 Assume sequential stack smashing

7

slide-5
SLIDE 5

Ways of Defeating StackGuard

 Overwrite the canary with the correct value  If the range of the random value is small, just

try every possibility

 Or perform a memory disclosure attack first

  • To learn the canary value on the stack

8

slide-6
SLIDE 6

9

StackGuard Limitations

 Big limitation: Disclosure attacks  By performing a buffer “overread”  Example is the famous Heartbleed attack against

SSL

 Why is this a problem for Stackguard canaries?

char packet[10]; … // suppose len is adversary controlled strncpy(buf, packet, len); send(fd, buf, len);

slide-7
SLIDE 7

 Big limitation: Disclosure attacks  By performing a buffer “overread”  Example is the famous Heartbleed

attack against SSL

 Why is this a problem for

Stackguard?

char packet[10]; … // suppose len is adversary controlled strncpy(buf, packet, len); send(fd, buf, len);

10

StackGuard Limitations

previous stack frame ret addr canary

  • ld rbp

packet

slide-8
SLIDE 8

11

StackGuard Limitations

 Big limitation: disclosure attacks  By performing a buffer “overread”  One may extract the canary values by reading

beyond the end of stack buffers

 Which would enable the adversary to learn the

(supposedly secret) canary value

slide-9
SLIDE 9

More Ways of Defeating StackGuard

 Sometimes no need to overwrite the return

address

 Can overflow

  • Security‐sensitive local variables
  • Heap overflow
  • Global data overflow

 Ultimately, an attacker only needs to hijack a

function pointer

12

slide-10
SLIDE 10

Example: Hijacking a function pointer

void foo () {...} void bar () {...} int main() { char buf [16]; void (*f) () = &foo; gets(buf); f(); }

 Assume no chance of overflowing the return address  Can overflow the buffer so that the function pointer

is modified to be the address of bar

 Then the function call will call bar instead of foo

13

slide-11
SLIDE 11

Other Ways of Hijacking Function Pointers

 Use heap overflows to hijack a function

pointer on the heap

 Hijacking global function pointers  Function pointers in Global Offset Table

(GOT)

 Used for dynamically linked functions

14

slide-12
SLIDE 12

Global Data Overflow

 Can attack buffer located in global data  may be located above program code  if has function pointer and vulnerable buffer  or adjacent process management tables  aim to overwrite function pointer later called

slide-13
SLIDE 13

Global Data Overflow Example

/* global static data - targeted for attack */ struct chunk { char inp[64]; /* input buffer */ void (*process)(char *); /* ptr to function */ } chunk; void showlen(char *buf) { int len; len = strlen(buf); printf("buffer6 read %d chars\n", len); } int main(int argc, char *argv[]) { setbuf(stdin, NULL); chunk.process = showlen; printf("Enter value: "); gets(chunk.inp); chunk.process(chunk.inp); printf("buffer6 done\n"); }

example by Stallings

slide-14
SLIDE 14

Detection: Guard Pages

 Can be thought of as extension of StackGuard  Place guard pages between critical regions of

memory

 flagged in MMU as illegal addresses  any access aborts process  Can even place between stack frames and

heap buffers

 at the cost of performance/memory overhead

slide-15
SLIDE 15

Runtime Mitigation: DEP (Data Execution Prevention)

 Computer architectures follow a Von‐Neumann

architecture

 Storing code as data  This allows an attacker to inject code into stack or

heap, which is supposed to store only data

 A Harvard architecture is better for security  Divide the virtual address space into a data region

and a code region

 The code region is readable (R) and executable (X)  The data region is readable (R) and writable (W)  No region is both writable and executable

  • An attacker can inject code into the stack, but cannot

execute it

slide-16
SLIDE 16

Runtime Mitigation: DEP (Data Execution Prevention)

 DEP prevents code‐injection attacks  AKA Nx‐bit (non executable bit), W ⊕ X  DEP is now supported by most OSes and ISAs

slide-17
SLIDE 17

Runtime Mitigation: DEP

 Issue: some legit apps support executable

code in the data region

 e.g., a JIT (Just‐In‐Time) compiler  Runtime code generation  need special provisions

slide-18
SLIDE 18

Defeating DEP: Code Reuse Attacks

 Idea: reuse code in the program itself  No need to inject code  Return‐to‐libc: replace return address with the

address of a dangerous library function

 attacker constructs suitable parameters on stack

above return address

  • On x64, need more work of setting up parameter‐passing

registers

 function returns and library function executes

  • e.g. execve(“/bin/sh”)

 can even chain two library calls

slide-19
SLIDE 19

Code Reuse: Return to libc

void foo () {...} int main() { char buf [16]; void (*f) () = &foo; gets(buf); f(); }

 Attack 1: changing f’s value to a libc system

function and put the arguments on the stack

 Attack 2: chain two calls of libc functions

22

stack frame for main esp ebp ret

  • ld ebp

f buffer

slide-20
SLIDE 20

Code Injection vs Code Reuse

 The difference is subtle, but significant  In code injection, we wrote the address of

execve into buffer on the stack and modified return address to start executing at buffer

  • I.e., we are executing in the stack memory region

 In code reuse, we can modify the return

address to point to execve directly, so we continue to execute code

  • Reusing available code to do what the adversary

wants

slide-21
SLIDE 21

Code Injection vs Code Reuse

stack frame for main ret execve (“/bin/sh”) code injection code reuse stack frame for main ret buffer execve (“/bin/sh”) existing code

slide-22
SLIDE 22

Code Reuse

 In many attacks, a code reuse attack is used

as a first step to disable DEP

 Goal is to allow execution of stack memory  There’s a system call for that

int mprotect(void *addr, size_t len, int prot);

 Sets protection for region of memory starting

at address

 Invoke this system call to allow execution on

stack and then start executing from the injected code

slide-23
SLIDE 23

Code Reuse: ROP

 Return‐Oriented Programming (ROP)  [Shacham et al], 2008  Arbitrary behavior without code injection  Combine snippets of existing code (gadgets)  A set of Turing‐complete gadgets and a way of

chaining these gadgets

 People have shown that in small programs (e.g.,

16KB), they can find a turing‐complete set of gadgets

slide-24
SLIDE 24

ROP: Illustrated

 Use gadgets to

perform general programming

 arithmetics;  arbitrary

control flow: jumps; loops; …

27

movl $0x006f6d2e,(%eax,%ebx) movl 0xd4(%ebp),%eax movl %eax,(%esp) calll 0x0008ba11 addl $0x1f,%eax andl $0xf0,%eax subl %eax,%esp leal 0x20(%esp),%edx movl %edx,0xb4(%ebp) jmp 0x0006d8b4 incl 0xd4(%ebp) movl 0xd4(%ebp),%eax movzbl (%eax),%ecx cmpb $0x3a,%cl je 0x0006d8b1 testb %cl,%cl movl 0xb4(%ebp),%ebx jne 0x0006d8db movb $0x43,(%ebx) movb $0x00,0x01(%ebx) jmp 0x0006d90d movb %cl,(%ebx) incl %ebx incl 0xd4(%ebp) movl 0xd4(%ebp),%eax movzbl (%eax),%ecx testb %cl,%cl setne %dl cmpb $0x3a,%cl setne %al testb %al,%dl jne 0x0006d8cf movb $0x00,(%ebx) cmpl $0x01,0x0008a780 jne 0x0006d90d movl 0xb4(%ebp),%edx movl $0x0000002f,0x04(%esp) movl %edx,(%esp) calll 0x0008b9e9 testl %eax,%eax jne 0x0006d8b4 movl 0xb4(%ebp),%esi movl $0x00000002,%ecx movl $0x0007e270,%edi cld repz/cmpsb (%esi),(%edi) movl $0x00000000,%eax je 0x0006d92e movzbl 0xff(%esi),%eax movzbl 0xff(%edi),%ecx subl %ecx,%eax testl %eax,%eax jel 0x0006da53 movl 0xb4(%ebp),%esi movl $0x00070bbb,%edi movl $0x00000006,%ecx repz/cmpsb (%esi),(%edi) movl $0x00000000,%edx je 0x0006d956 movzbl 0xff(%esi),%edx movzbl 0xff(%edi),%ecx subl %ecx,%edx testl %edx,%edx

ROP’s control stack (just data)

slide-25
SLIDE 25

Return-Oriented Programming

28

*The following slides are by Dr. Shacham

slide-26
SLIDE 26

29

ROP Thesis

slide-27
SLIDE 27

Machine Instructions

slide-28
SLIDE 28

ROP Execution

slide-29
SLIDE 29

32

Code Reuse in General

 Code reuse attacks can be employed more

generally to enable adversaries to execute existing code under their control

 Termed “return‐oriented attacks”

ROP Example

  • Use ESP as program counter

– E.g., Store 5 at address 0x8048000 (without introducing new code)

%eax = %ebx = 0x8048000 = Registers Memory Code Stack

G1 5 jmp G2 Return Address

buf

0x8048000 jump G3 . . .

pop %eax ret pop %ebx ret movl %eax, (%ebx) ret

G2: G2 G3 G1: G3:

slide-30
SLIDE 30

Code Reuse in General

 Code reuse attacks can be employed more

generally to enable adversaries to execute existing code under their control

 Termed “return‐oriented attacks”

ROP Example

  • Use ESP as program counter

– E.g., Store 5 at address 0x8048000 (without introducing new code)

%eax = %ebx = 0x8048000 = Registers Memory Code Stack

G1 5 jmp G2 Return Address

buf

0x8048000 jump G3 . . .

pop %eax ret pop %ebx ret movl %eax, (%ebx) ret

G2: G2 G3 G1: G3:

5

slide-31
SLIDE 31

34

Code Reuse in General

 Code reuse attacks can be employed more

generally to enable adversaries to execute existing code under their control

 Termed “return‐oriented attacks”

ROP Example

  • Use ESP as program counter

– E.g., Store 5 at address 0x8048000 (without introducing new code)

%eax = %ebx = 0x8048000 = Registers Memory Code Stack

G1 5 jmp G2 Return Address

buf

0x8048000 jump G3 . . .

pop %eax ret pop %ebx ret movl %eax, (%ebx) ret

G2: G2 G3 G1: G3:

5

slide-32
SLIDE 32

35

Code Reuse in General

 Code reuse attacks can be employed more

generally to enable adversaries to execute existing code under their control

 Termed “return‐oriented attacks”

ROP Example

  • Use ESP as program counter

– E.g., Store 5 at address 0x8048000 (without introducing new code)

%eax = %ebx = 0x8048000 = Registers Memory Code Stack

G1 5 jmp G2 Return Address

buf

0x8048000 jump G3 . . .

pop %eax ret pop %ebx ret movl %eax, (%ebx) ret

G2: G2 G3 G1: G3:

5 0x8048000

slide-33
SLIDE 33

36

Code Reuse in General

 Code reuse attacks can be employed more

generally to enable adversaries to execute existing code under their control

 Termed “return‐oriented attacks”

ROP Example

  • Use ESP as program counter

– E.g., Store 5 at address 0x8048000 (without introducing new code)

%eax = %ebx = 0x8048000 = Registers Memory Code Stack

G1 5 jmp G2 Return Address

buf

0x8048000 jump G3 . . .

pop %eax ret pop %ebx ret movl %eax, (%ebx) ret

G2: G2 G3 G1: G3:

5 0x8048000

ROP Example

  • Use ESP as program counter

– E.g., Store 5 at address 0x8048000 (without introducing new code)

%eax = %ebx = 0x8048000 = Registers Memory Code Stack

G1 5 jmp G2 Return Address

buf

0x8048000 jump G3 . . .

pop %eax ret pop %ebx ret movl %eax, (%ebx) ret

G2: G2 G3 G1: G3:

5 0x8048000

slide-34
SLIDE 34

37

Code Reuse in General

 Code reuse attacks can be employed more

generally to enable adversaries to execute existing code under their control

 Termed “return‐oriented attacks”

ROP Example

  • Use ESP as program counter

– E.g., Store 5 at address 0x8048000 (without introducing new code)

%eax = %ebx = 0x8048000 = Registers Memory Code Stack

G1 5 jmp G2 Return Address

buf

0x8048000 jump G3 . . .

pop %eax ret pop %ebx ret movl %eax, (%ebx) ret

G2: G2 G3 G1: G3:

5 0x8048000

slide-35
SLIDE 35

38

Code Reuse in General

 Code reuse attacks can be employed more

generally to enable adversaries to execute existing code under their control

 Termed “return‐oriented attacks”

ROP Example

  • Use ESP as program counter

– E.g., Store 5 at address 0x8048000 (without introducing new code)

%eax = %ebx = 0x8048000 = Registers Memory Code Stack

G1 5 jmp G2 Return Address

buf

0x8048000 jump G3 . . .

pop %eax ret pop %ebx ret movl %eax, (%ebx) ret

G2: G2 G3 G1: G3:

5 0x8048000 5

slide-36
SLIDE 36

Building ROP Functionality

slide-37
SLIDE 37

Building ROP Functionality

slide-38
SLIDE 38

Building ROP Functionality

41

slide-39
SLIDE 39

Return‐oriented Programming

 What can we do with return‐oriented

programming?

 Anything any other program can do  How do we know?

slide-40
SLIDE 40

Return‐oriented Programming

 What can we do with return‐oriented

programming?

 Anything any other program can do  How do we know? Turing completeness  A language is Turing complete if it has

(loosely)

 Conditional branching  Can change memory arbitrarily  Both are possible in ROP

slide-41
SLIDE 41

Protection against ROP

 ROP works by changing the control flow of the

program

 Control‐flow integrity (CFI)  Take a vulnerable program and a pre‐

determined a control‐flow graph

 Insert checks into the program so that it stops

working if an illegal control flow transfer happens during runtime

  • Via compiler changes or binary rewriting

 More on this later

44

slide-42
SLIDE 42

Runtime Mitigation: Randomization

 Exploits requires knowing code/data addresses  E.g., the start address of a buffer  E.g., the address of a library function  Idea: introduce artificial diversity (randomization)  Make addresses unpredictable for attackers  Many ways of doing randomization  Randomize location of the stack, location of key data

structures on the heap, and location of library functions

 Randomly pad stack frames  At compile time, randomize code generation for

defending against ROP

45

slide-43
SLIDE 43

Implementation of Randomization

 Can be performed  At compile time  At link time  Or at runtime (e.g., via dynamic binary

rewriting)

46

slide-44
SLIDE 44

Linux Address‐Space Layout Randomization (ASLR)

 For a position‐independent executable (PIE),

randomize

 The base address of the executable  All libraries are PIE  So their base addresses are randomized  Main executables may not be PIE  May not be protected by PIE  A form of coarse‐grained randomization  Only the base address is randomized  Relative distances between memory objects are

not changed

47

slide-45
SLIDE 45

Ways of Defeating ASLR

 Perform an exhaustive search, if the random

space is small

 E.g., Linux provides 16‐bit of randomness

  • It can be defeated by an exhaustive search in

about 200s

 ASLR often defeated by memory disclosure  E.g., if the attacker can read the value of a

pointer to the stack

  • Then he can use it to discover where the stack is

48

slide-46
SLIDE 46

Summary

 Defenses  Stack Guard  DEP  ASLR  Advanced attacks  Memory disclosure (e.g., via buffer overread)  Code reuse

  • Return to libc
  • ROP

49