ROP, heap attacks, CFI, integer overflows Nadia Heninger and Deian - - PowerPoint PPT Presentation

rop heap attacks cfi integer overflows
SMART_READER_LITE
LIVE PREVIEW

ROP, heap attacks, CFI, integer overflows Nadia Heninger and Deian - - PowerPoint PPT Presentation

CSE 127: Computer Security ROP, heap attacks, CFI, integer overflows Nadia Heninger and Deian Stefan Some slides adopted from Kirill Levchenko, Stefan Savage, Stephen Checkoway, Hovav Shacham, Raluca Popal, and David Wagner Review: calling and


slide-1
SLIDE 1

CSE 127: Computer Security

ROP, heap attacks, CFI, integer

  • verflows

Nadia Heninger and Deian Stefan

Some slides adopted from Kirill Levchenko, Stefan Savage, Stephen Checkoway, Hovav Shacham, Raluca Popal, and David Wagner

slide-2
SLIDE 2

Review: calling and returning

main’s locals %esp %ebp

main()

  • > foo(1,2,3)

——> bar(4)

slide-3
SLIDE 3

Review: calling and returning

main’s locals 3 %esp

main()

  • > foo(1,2,3)

——> bar(4)

%ebp

slide-4
SLIDE 4

Review: calling and returning

main’s locals 3 2 1 %esp

main()

  • > foo(1,2,3)

——> bar(4)

%ebp

slide-5
SLIDE 5

Review: calling and returning

main’s locals 3 2 1 %eip in main %esp

main()

  • > foo(1,2,3)

——> bar(4)

%ebp

slide-6
SLIDE 6

Review: calling and returning

main’s locals 3 2 1 %eip in main main’s %ebp %esp

main()

  • > foo(1,2,3)

——> bar(4)

%ebp

slide-7
SLIDE 7

Review: calling and returning

main’s locals 3 2 1 %eip in main main’s %ebp %esp %ebp

main()

  • > foo(1,2,3)

——> bar(4)

slide-8
SLIDE 8

Review: calling and returning

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals %esp %ebp

main()

  • > foo(1,2,3)

——> bar(4)

slide-9
SLIDE 9

Review: calling and returning

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %esp %ebp

main()

  • > foo(1,2,3)

——> bar(4)

slide-10
SLIDE 10

Review: calling and returning

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo %esp %ebp

main()

  • > foo(1,2,3)

——> bar(4)

slide-11
SLIDE 11

Review: calling and returning

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp %esp %ebp

main()

  • > foo(1,2,3)

——> bar(4)

slide-12
SLIDE 12

Review: calling and returning

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp %esp %ebp

main()

  • > foo(1,2,3)

——> bar(4)

slide-13
SLIDE 13

Review: calling and returning

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp bar’s locals %esp %ebp

main()

  • > foo(1,2,3)

——> bar(4)

slide-14
SLIDE 14

Review: calling and returning

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp bar’s locals %esp %ebp

main()

  • > foo(1,2,3)

——> bar(4)

mov %ebp, %esp pop %ebp leave =

slide-15
SLIDE 15

Review: calling and returning

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp bar’s locals %esp %ebp

main()

  • > foo(1,2,3)

——> bar(4)

mov %ebp, %esp pop %ebp leave =

slide-16
SLIDE 16

Review: calling and returning

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp bar’s locals %esp %ebp

main()

  • > foo(1,2,3)

——> bar(4)

mov %ebp, %esp pop %ebp leave =

slide-17
SLIDE 17

Review: calling and returning

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp bar’s locals %esp %ebp

main()

  • > foo(1,2,3)

——> bar(4)

ret = pop %eip

slide-18
SLIDE 18

Review: calling and returning

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp bar’s locals %esp %ebp

main()

  • > foo(1,2,3)

——> bar(4)

slide-19
SLIDE 19

Review: calling and returning

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp bar’s locals %esp %ebp

main()

  • > foo(1,2,3)

——> bar(4)

mov %ebp, %esp pop %ebp leave =

slide-20
SLIDE 20

Review: calling and returning

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp bar’s locals %esp

main()

  • > foo(1,2,3)

——> bar(4)

mov %ebp, %esp pop %ebp leave =

%ebp

slide-21
SLIDE 21

Review: calling and returning

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp bar’s locals %esp

main()

  • > foo(1,2,3)

——> bar(4)

ret = pop %eip

%ebp

slide-22
SLIDE 22

Review: calling and returning

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp bar’s locals %esp

main()

  • > foo(1,2,3)

——> bar(4)

%ebp

slide-23
SLIDE 23

Suppose bar had overflow

  • Our goal: call system(“/bin/sh”)
  • Need to set up stack frame that looks like a

normal call to system:
 
 


  • But we're not going to use call instruction to

jump to system; we're going to use ret

cmd=“/bin/sh” &cmd saved %eip %esp

slide-24
SLIDE 24

Suppose bar had overflow

  • Our goal: call system(“/bin/sh”)
  • Need to set up stack frame that looks like a

normal call to system:
 
 


  • But we're not going to use call instruction to

jump to system; we're going to use ret

cmd=“/bin/sh” &cmd &exit %esp

slide-25
SLIDE 25

Hijacking control flow

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp bar’s locals %esp %ebp cmd=“/bin/sh” &cmd &exit &system

slide-26
SLIDE 26

Hijacking control flow

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp bar’s locals %ebp cmd=“/bin/sh” &cmd &exit &system

leave

%esp

slide-27
SLIDE 27

Hijacking control flow

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp bar’s locals cmd=“/bin/sh” &cmd &exit &system %esp %ebp

ret

slide-28
SLIDE 28

Hijacking control flow

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp bar’s locals cmd=“/bin/sh” &cmd &exit &system %ebp %esp

slide-29
SLIDE 29

Hijacking control flow

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp bar’s locals cmd=“/bin/sh” &cmd &exit &system %ebp %esp

slide-30
SLIDE 30

Hijacking control flow

main’s locals 3 2 1 %eip in main main’s %ebp foo’s locals 4 %eip in foo foo’s %ebp bar’s locals cmd=“/bin/sh” &cmd &exit &system %ebp %esp

points to nonsense, but doesn't matter; system just saves it

slide-31
SLIDE 31

Hijacking control flow

cmd=“/bin/sh” &cmd &exit %ebp %esp

  • Stack frame that looks like a normal call to

system:

slide-32
SLIDE 32

Today

  • Advanced modern attack techniques

➤ ROP ➤ Heap-based attacks

  • Control flow integrity
  • Integer overflow attacks
slide-33
SLIDE 33
slide-34
SLIDE 34

What if there is no code that does what we want?

slide-35
SLIDE 35

ret Steve Checkoway ret Dino Dai Zovi

slide-36
SLIDE 36

The Geometry of Innocent Flesh on the Bone: Return-into-libc without Function Calls (on the x86)

Hovav Shacham∗ hovav@cs.ucsd.edu

slide-37
SLIDE 37

Return-Oriented Programming

slide-38
SLIDE 38

Return-Oriented Programming

  • Idea: make shellcode out of existing code
  • Gadgets: code sequences ending in ret instruction

➤ Overwrite saved %eip on stack to pointer to first

gadget, then second gadget, etc.

slide-39
SLIDE 39

Return-Oriented Programming

  • Idea: make shellcode out of existing code
  • Gadgets: code sequences ending in ret instruction

➤ Overwrite saved %eip on stack to pointer to first

gadget, then second gadget, etc.

  • Where do you often find ret instructions?
slide-40
SLIDE 40

Return-Oriented Programming

  • Idea: make shellcode out of existing code
  • Gadgets: code sequences ending in ret instruction

➤ Overwrite saved %eip on stack to pointer to first

gadget, then second gadget, etc.

  • Where do you often find ret instructions?

➤ End of function (inserted by compiler)

slide-41
SLIDE 41

Return-Oriented Programming

  • Idea: make shellcode out of existing code
  • Gadgets: code sequences ending in ret instruction

➤ Overwrite saved %eip on stack to pointer to first

gadget, then second gadget, etc.

  • Where do you often find ret instructions?

➤ End of function (inserted by compiler) ➤ Any sequence of executable memory ending in 0xc3

slide-42
SLIDE 42
slide-43
SLIDE 43

x86 instructions

  • Variable length!
  • Can begin on any byte boundary!
slide-44
SLIDE 44

b8 01 00 00 00 5b c9 c3 mov $0x1,%eax pop %ebx leave ret

One ret, multiple gadgets

=

slide-45
SLIDE 45

b8 01 00 00 00 5b c9 c3 add %al,(%eax) pop %ebx leave ret

=

One ret, multiple gadgets

slide-46
SLIDE 46

b8 01 00 00 00 5b c9 c3 add %bl,-0x37(%eax) ret

=

One ret, multiple gadgets

slide-47
SLIDE 47

b8 01 00 00 00 5b c9 c3 pop %ebx leave ret

=

One ret, multiple gadgets

slide-48
SLIDE 48

b8 01 00 00 00 5b c9 c3 leave ret

=

One ret, multiple gadgets

slide-49
SLIDE 49

b8 01 00 00 00 5b c9 c3 ret

=

One ret, multiple gadgets

slide-50
SLIDE 50

What does this gadget do?

%esp v1 pop %edx ret

slide-51
SLIDE 51

%esp 0xdeadbeef 0x08049bbc 0x08049bbc: pop %edx 0x08049bbd: ret 0x08049b62: nop 0x08049b63: ret ... %eip %edx = 0x00000000

relevant register(s): relevant code: relevant stack:

slide-52
SLIDE 52

%esp 0xdeadbeef 0x08049bbc 0x08049bbc: pop %edx 0x08049bbd: ret 0x08049b62: nop 0x08049b63: ret ... %eip %edx = 0x00000000

relevant register(s): relevant code: relevant stack:

slide-53
SLIDE 53

%esp 0xdeadbeef 0x08049bbc 0x08049bbc: pop %edx 0x08049bbd: ret 0x08049b62: nop 0x08049b63: ret ... %eip %edx = 0x00000000

relevant register(s): relevant code: relevant stack:

slide-54
SLIDE 54

%esp 0xdeadbeef 0x08049bbc 0x08049bbc: pop %edx 0x08049bbd: ret 0x08049b62: nop 0x08049b63: ret ... %eip %edx = 0xdeadbeef

relevant register(s): relevant code: relevant stack:

slide-55
SLIDE 55

What does this gadget do?

%esp v1 pop %edx ret

%edx = v1 mov v1, %edx

slide-56
SLIDE 56
  • Overflow the stack with values and addresses to

such gadgets to express your program

  • E.g., if shellcode needs to write a value to %edx,

use the previous gadget
 
 
 


v1

How dow you use this as an attacker?

%esp pop %edx ret

slide-57
SLIDE 57

v2 v1

What does this gadget do?

%esp pop %eax ret pop %ebx ret mov %eax, %(ebx) ret

slide-58
SLIDE 58

0x08049b90 0xbadcaffe 0x08049b63 0xdeadbeef 0x08049bbc %esp 0x08049bbc: pop %eax 0x08049bbd: ret 0x08049b63: pop %ebx 0x08049b64: ret ... %eip %eax = 0x00000000 %ebx = 0x00000000

relevant register(s): relevant code: relevant stack:

0x08049b90: mov %eax, %(ebx) 0x08049b91: ret ...

relevant memory:

0x08049b00: ret ... 0xbadcaffe: 0x00000000

slide-59
SLIDE 59

0x08049b90 0xbadcaffe 0x08049b63 0xdeadbeef 0x08049bbc %esp 0x08049bbc: pop %eax 0x08049bbd: ret 0x08049b63: pop %ebx 0x08049b64: ret ... %eip %eax = 0x00000000 %ebx = 0x00000000

relevant register(s): relevant code: relevant stack:

0x08049b90: mov %eax, %(ebx) 0x08049b91: ret ...

relevant memory:

0x08049b00: ret ... 0xbadcaffe: 0x00000000

slide-60
SLIDE 60

0x08049b90 0xbadcaffe 0x08049b63 0xdeadbeef 0x08049bbc %esp 0x08049bbc: pop %eax 0x08049bbd: ret 0x08049b63: pop %ebx 0x08049b64: ret ... %eip %eax = 0xdeadbeef %ebx = 0x00000000

relevant register(s): relevant code: relevant stack:

0x08049b90: mov %eax, %(ebx) 0x08049b91: ret ...

relevant memory:

0x08049b00: ret ... 0xbadcaffe: 0x00000000

slide-61
SLIDE 61

0x08049b90 0xbadcaffe 0x08049b63 0xdeadbeef 0x08049bbc %esp 0x08049bbc: pop %eax 0x08049bbd: ret 0x08049b63: pop %ebx 0x08049b64: ret ... %eip %eax = 0xdeadbeef %ebx = 0x00000000

relevant register(s): relevant code: relevant stack:

0x08049b90: mov %eax, %(ebx) 0x08049b91: ret ...

relevant memory:

0x08049b00: ret ... 0xbadcaffe: 0x00000000

slide-62
SLIDE 62

0x08049b90 0xbadcaffe 0x08049b63 0xdeadbeef 0x08049bbc %esp 0x08049bbc: pop %eax 0x08049bbd: ret 0x08049b63: pop %ebx 0x08049b64: ret ... %eip %eax = 0xdeadbeef %ebx = 0xbadcaffe

relevant register(s): relevant code: relevant stack:

0x08049b90: mov %eax, %(ebx) 0x08049b91: ret ...

relevant memory:

0x08049b00: ret ... 0xbadcaffe: 0x00000000

slide-63
SLIDE 63

0x08049b90 0xbadcaffe 0x08049b63 0xdeadbeef 0x08049bbc %esp 0x08049bbc: pop %eax 0x08049bbd: ret 0x08049b63: pop %ebx 0x08049b64: ret ... %eip %eax = 0xdeadbeef %ebx = 0xbadcaffe

relevant register(s): relevant code: relevant stack:

0x08049b90: mov %eax, %(ebx) 0x08049b91: ret ...

relevant memory:

0x08049b00: ret ... 0xbadcaffe: 0x00000000

slide-64
SLIDE 64

0x08049b90 0xbadcaffe 0x08049b63 0xdeadbeef 0x08049bbc %esp 0x08049bbc: pop %eax 0x08049bbd: ret 0x08049b63: pop %ebx 0x08049b64: ret ... %eip %eax = 0xdeadbeef %ebx = 0xbadcaffe

relevant register(s): relevant code: relevant stack:

0x08049b90: mov %eax, %(ebx) 0x08049b91: ret ... 0xbadcaffe: 0xdeadbeef

relevant memory:

0x08049b00: ret ...

slide-65
SLIDE 65

v2 v1

What does this gadget do?

%esp pop %eax ret pop %ebx ret mov %eax, %(ebx) ret

mem[v2] = v1 mov v2, %ebx mov v1, %(%ebx)

slide-66
SLIDE 66

Can express arbitrary programs

slide-67
SLIDE 67

Can find gadgets automatically

slide-68
SLIDE 68

Return-Oriented Programming

not even really about “returns”…

slide-69
SLIDE 69

Today

  • Advanced modern attack techniques

➤ ROP ➤ Heap-based attacks

  • Control flow integrity
  • Integer overflow attacks
slide-70
SLIDE 70

Handling heap-allocated memory can be just as error-prone as the stack

  • We may:

➤ Write/read memory we shouldn’t have access to ➤ Forget to free memory ➤ Free already freed objects ➤ Use pointers that point to freed object

  • What if the attacker can cause the program to

use freed objects?

slide-71
SLIDE 71

Heap corruption

  • Can bypass security checks (data-only attacks)

➤ E.g., isAuthenticated, buffer_size, isAdmin, etc.

  • Can overwrite function pointers

➤ Direct transfer of control when function is called ➤ C++ virtual tables are especially good targets

slide-72
SLIDE 72

vtables

  • Each object contains pointer

to vtable

  • Array of function pointers

➤ one entry per function

  • Call looks up entry in vtable

Q: What does bar() compile to? A: *(obj->vtable[0])(obj)

class Base { public: virtual void foo() { cout << “Hi\n”; } }; class Derived: public Base { public: void foo() {cout << "Bye\n";} }; void bar(Base* obj) { obj->foo(); } int main(int argc, char* argv[]) { Base *b = new Base(); Derived *d = new Derived(); bar(b); bar(d); }

slide-73
SLIDE 73

What does a use after free (UAF) attack look like?

Victim: Free object: free(obj); Attacker: Overwrite the vtable of the object so entry (e.g., obj->vtable[0]) points to attacker gadget Victim: Use dangling pointer: obj->foo()

slide-74
SLIDE 74

Today

  • Advanced modern attack techniques

➤ ROP ➤ Heap-based attacks

  • Control flow integrity
  • Integer overflow attacks
slide-75
SLIDE 75

Control Flow Integrity

  • In almost all the attacks we looked at, the

attacker is overwriting jump targets that are in memory (return addresses on the stack and function pointers on the stack/heap)

  • Idea: don’t try to stop the memory writes.

Instead: restrict control flow to legitimate paths

➤ I.e., ensure that jumps, calls, and returns can only go

to allowed target destinations

slide-76
SLIDE 76

Restrict indirect transfers of control

slide-77
SLIDE 77
  • Why do we not need to do anything about direct

transfer of control flow (i.e., direct jumps/calls)?

Restrict indirect transfers of control

slide-78
SLIDE 78
  • Why do we not need to do anything about direct

transfer of control flow (i.e., direct jumps/calls)?

➤ Address is hard-coded in instruction. Not under

attacker control

Restrict indirect transfers of control

slide-79
SLIDE 79

Restrict indirect transfers of control

slide-80
SLIDE 80

Restrict indirect transfers of control

  • What are the ways to transfer control indirectly?
slide-81
SLIDE 81

Restrict indirect transfers of control

  • What are the ways to transfer control indirectly?
  • Forward path: jumping to (or calling function at)

an address in register or memory

➤ E.g., qsort, interrupt handlers, virtual calls, etc.

  • Reverse path: returning from function (uses

address on stack)

slide-82
SLIDE 82

What’s a legitimate target?

Look at the program control-flow graph (CFG)!

void sort2(int a[],int b[], int len {
 sort(a, len, lt);
 sort(b, len, gt);
 }
 
 bool lt(int x, int y) { return x < y; }
 
 bool gt(int x, int y) { return x > y; }

slide-83
SLIDE 83

call sort call sort ret sort2()

What’s a legitimate target?

Look at the program control-flow graph (CFG)!

void sort2(int a[],int b[], int len {
 sort(a, len, lt);
 sort(b, len, gt);
 }
 
 bool lt(int x, int y) { return x < y; }
 
 bool gt(int x, int y) { return x > y; }

slide-84
SLIDE 84

call sort call sort ret sort2() sort() ret

call arg$3

What’s a legitimate target?

Look at the program control-flow graph (CFG)!

void sort2(int a[],int b[], int len {
 sort(a, len, lt);
 sort(b, len, gt);
 }
 
 bool lt(int x, int y) { return x < y; }
 
 bool gt(int x, int y) { return x > y; }

slide-85
SLIDE 85

call sort call sort ret sort2() ret lt() ret gt() sort() ret

call arg$3

What’s a legitimate target?

Look at the program control-flow graph (CFG)!

void sort2(int a[],int b[], int len {
 sort(a, len, lt);
 sort(b, len, gt);
 }
 
 bool lt(int x, int y) { return x < y; }
 
 bool gt(int x, int y) { return x > y; }

slide-86
SLIDE 86

call sort call sort ret sort2() ret lt() ret gt() sort() ret

call arg$3

What’s a legitimate target?

Look at the program control-flow graph (CFG)!

void sort2(int a[],int b[], int len {
 sort(a, len, lt);
 sort(b, len, gt);
 }
 
 bool lt(int x, int y) { return x < y; }
 
 bool gt(int x, int y) { return x > y; }

direct call indirect call return

slide-87
SLIDE 87

call sort call sort ret sort2() ret lt() ret gt() sort() ret

call arg$3

What’s a legitimate target?

Look at the program control-flow graph (CFG)!

void sort2(int a[],int b[], int len {
 sort(a, len, lt);
 sort(b, len, gt);
 }
 
 bool lt(int x, int y) { return x < y; }
 
 bool gt(int x, int y) { return x > y; }

direct call indirect call return

slide-88
SLIDE 88

call sort call sort ret sort2() ret lt() ret gt() sort() ret

call arg$3

What’s a legitimate target?

Look at the program control-flow graph (CFG)!

void sort2(int a[],int b[], int len {
 sort(a, len, lt);
 sort(b, len, gt);
 }
 
 bool lt(int x, int y) { return x < y; }
 
 bool gt(int x, int y) { return x > y; }

direct call indirect call return

slide-89
SLIDE 89

call sort call sort ret sort2() ret lt() ret gt() sort() ret

call arg$3

What’s a legitimate target?

Look at the program control-flow graph (CFG)!

void sort2(int a[],int b[], int len {
 sort(a, len, lt);
 sort(b, len, gt);
 }
 
 bool lt(int x, int y) { return x < y; }
 
 bool gt(int x, int y) { return x > y; }

direct call indirect call return

slide-90
SLIDE 90

call sort call sort ret sort2() ret lt() ret gt() sort() ret

call arg$3

What’s a legitimate target?

Look at the program control-flow graph (CFG)!

void sort2(int a[],int b[], int len {
 sort(a, len, lt);
 sort(b, len, gt);
 }
 
 bool lt(int x, int y) { return x < y; }
 
 bool gt(int x, int y) { return x > y; }

direct call indirect call return

slide-91
SLIDE 91

call sort call sort ret sort2() ret lt() ret gt() sort() ret

call arg$3

What’s a legitimate target?

Look at the program control-flow graph (CFG)!

void sort2(int a[],int b[], int len {
 sort(a, len, lt);
 sort(b, len, gt);
 }
 
 bool lt(int x, int y) { return x < y; }
 
 bool gt(int x, int y) { return x > y; }

direct call indirect call return

slide-92
SLIDE 92

How do we restrict jumps to CFG?

  • Assign labels to all indirect jumps and their targets
  • Before taking an indirect jump, validate that target

label matches jump site

➤ Like stack canaries, but for for control flow target

  • Need hardware support

➤ Otherwise trade off precision for performance

slide-93
SLIDE 93

Fine grained CFI (Abadi et al.)

  • Statically compute CFG
  • Dynamically ensure program never deviates

➤ Assign label to each target of indirect transfer ➤ Instrument indirect transfers to compare label of

destination with the expected label to ensure it's valid

slide-94
SLIDE 94

call sort call sort ret sort2() ret lt() ret gt() sort() ret

call arg$3

void sort2(int a[],int b[], int len {
 sort(a, len, lt);
 sort(b, len, gt);
 }
 
 bool lt(int x, int y) { return x < y; }
 
 bool gt(int x, int y) { return x > y; }

direct call indirect call return

Fine grained CFI (Abadi et al.)

slide-95
SLIDE 95

call sort call sort ret sort2() ret lt() ret gt() sort() ret

call arg$3

void sort2(int a[],int b[], int len {
 sort(a, len, lt);
 sort(b, len, gt);
 }
 
 bool lt(int x, int y) { return x < y; }
 
 bool gt(int x, int y) { return x > y; }

direct call indirect call return

label 1 label 1

Fine grained CFI (Abadi et al.)

slide-96
SLIDE 96

call sort call sort ret sort2() ret lt() ret gt() sort() ret

call arg$3

void sort2(int a[],int b[], int len {
 sort(a, len, lt);
 sort(b, len, gt);
 }
 
 bool lt(int x, int y) { return x < y; }
 
 bool gt(int x, int y) { return x > y; }

direct call indirect call return

label 1 label 1

check 1 then

Fine grained CFI (Abadi et al.)

slide-97
SLIDE 97

call sort call sort ret sort2() ret lt() ret gt() sort() ret

call arg$3

void sort2(int a[],int b[], int len {
 sort(a, len, lt);
 sort(b, len, gt);
 }
 
 bool lt(int x, int y) { return x < y; }
 
 bool gt(int x, int y) { return x > y; }

direct call indirect call return

label 2 label 1 label 1

check 1 then

Fine grained CFI (Abadi et al.)

slide-98
SLIDE 98

call sort call sort ret sort2() ret lt() ret gt() sort() ret

call arg$3

void sort2(int a[],int b[], int len {
 sort(a, len, lt);
 sort(b, len, gt);
 }
 
 bool lt(int x, int y) { return x < y; }
 
 bool gt(int x, int y) { return x > y; }

direct call indirect call return

label 2 label 1 label 1

check 1 then

check 2 then check 2 then

Fine grained CFI (Abadi et al.)

slide-99
SLIDE 99

call sort call sort ret sort2() ret lt() ret gt() sort() ret

call arg$3

void sort2(int a[],int b[], int len {
 sort(a, len, lt);
 sort(b, len, gt);
 }
 
 bool lt(int x, int y) { return x < y; }
 
 bool gt(int x, int y) { return x > y; }

direct call indirect call return

label 2 label 3 label 3 label 1 label 1

check 1 then

check 2 then check 2 then

Fine grained CFI (Abadi et al.)

slide-100
SLIDE 100

call sort call sort ret sort2() ret lt() ret gt() sort() ret

call arg$3

void sort2(int a[],int b[], int len {
 sort(a, len, lt);
 sort(b, len, gt);
 }
 
 bool lt(int x, int y) { return x < y; }
 
 bool gt(int x, int y) { return x > y; }

direct call indirect call return

label 2 label 3 label 3 label 1 label 1

check 1 then

check 2 then check 2 then check 3 then

Fine grained CFI (Abadi et al.)

slide-101
SLIDE 101

Coarse-grained CFI (bin-CFI)

  • Label for destination of

indirect calls

➤ Make sure that every

indirect call lands on function entry

  • Label for destination of

rets and indirect jumps

➤ Make sure every

indirect jump lands at start of BB

call sort call sort ret sort2() ret lt() ret gt() sort() ret

call arg$3

slide-102
SLIDE 102

Coarse-grained CFI (bin-CFI)

  • Label for destination of

indirect calls

➤ Make sure that every

indirect call lands on function entry

  • Label for destination of

rets and indirect jumps

➤ Make sure every

indirect jump lands at start of BB

call sort call sort ret sort2() ret lt() ret gt() sort() ret

call arg$3

check then ret-label ret-label ret-label func-label func-label

check then

check then check then

slide-103
SLIDE 103

How else can you choose labels?

slide-104
SLIDE 104

How else can you choose labels?

WebAssembly does it by looking at function type

slide-105
SLIDE 105

What do labels look like?

Original code

slide-106
SLIDE 106

What do labels look like?

Original code Instrumented code

slide-107
SLIDE 107

What do labels look like?

Original code Instrumented code Abuse an x86 assembly instruction to insert “12345678” tag into the binary

slide-108
SLIDE 108

What do labels look like?

Original code Instrumented code Abuse an x86 assembly instruction to insert “12345678” tag into the binary Jump to the destination only if the tag is equal to “12345678”

slide-109
SLIDE 109

CFI limitations

  • Overhead

➤ Runtime: every indirect branch instruction ➤ Size: code before indirect branch + encode label at

destination

  • Scope

➤ CFI does not protect against data-only attacks ➤ Needs reliable W^X

slide-110
SLIDE 110
  • Imprecision can allow for control-flow hijacking

➤ Can jump to functions that have same label

➤ E.g., even if we use Wasm’s labels int

system(char*) and int myFunc(char*) share the same label

➤ Can return to many more sites

➤ But, real way to do backward edge CFI is to use a

shadow stack. (This is actually great!)

How can you defeat CFI?

slide-111
SLIDE 111

Today

  • Advanced modern attack techniques

➤ ROP ➤ Heap-based attacks

  • Control flow integrity
  • Integer overflow attacks
slide-112
SLIDE 112

What’s wrong with this program?

void vulnerable(int len, char *data) { char buf[64]; if (len > 64) return; memcpy(buf, data, len); }

slide-113
SLIDE 113

What’s wrong with this program?

void vulnerable(int len, char *data) { char buf[64]; if (len > 64) return; memcpy(buf, data, len); }

slide-114
SLIDE 114

What’s wrong with this program?

void vulnerable(int len, char *data) { char buf[64]; if (len > 64) return; memcpy(buf, data, len); }

slide-115
SLIDE 115

What’s wrong with this program?

void vulnerable(int len = 0xffffffff, char *data) { char buf[64]; if (len = -1 > 64) return; memcpy(buf, data, len = 0xffffffff); }

slide-116
SLIDE 116

Is this program safe?

void f(size_t len, char *data) { char *buf = malloc(len+2); if (buf == NULL) return; memcpy(buf, data, len); buf[len] = ‘\n'; buf[len+1] = ‘\0'; }

slide-117
SLIDE 117

Is this program safe?

void f(size_t len = 0xffffffff, char *data) { char *buf = malloc(len+2 = 0x000000001); if (buf == NULL) return; memcpy(buf, data, len = 0xffffffff); buf[len] = ‘\n'; buf[len+1] = ‘\0'; }

No!

slide-118
SLIDE 118

Still relevant classes of bugs

slide-119
SLIDE 119

Three flavors of integer overflows

  • Truncation bugs

➤ E.g., assigning an int64_t into in32_t (3rd ex)

  • Arithmetic overflow bugs

➤ E.g., adding huge unsigned number (2nd ex)

  • Signedness bugs

➤ E.g., treating signed number as unsigned (1st ex)

slide-120
SLIDE 120

Today

  • Advanced modern attack techniques

➤ ROP ➤ Heap-based attacks

  • Control flow integrity
  • Integer overflow attacks
slide-121
SLIDE 121

What does this all tell us?

If you’re trying to build secure systems, use a memory safe language.