guarding vulnerable code: module 2: mitigation15 necessity of shadow stack* defenses without stack...

44
1 Guarding Vulnerable Code: Module 2: Mitigation Mathias Payer, Purdue University http://hexhive.github.io

Upload: others

Post on 12-Oct-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

1

Guarding Vulnerable Code:Module 2: Mitigation

Mathias Payer, Purdue Universityhttp://hexhive.github.io

Page 2: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

2

Defense: Testing vs. Mitigations

Mitigations● Stop exploitation● Always on● Low overhead

Software Testing● Discover bugs● Development tool● Result oriented

Page 3: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

3

* The Matter of Heartbleed. Zakir Durumeric, James Kasten, J. Alex Halderman, Michael Bailey, Frank Li, Nicholas Weaver, Bernhard Amann, Jethro Beekman, Mathias Payer, Vern Paxson. In ACM IMC'14 (best paper)

Heartbleed: reactive patching*

● 11% of servers remained vulnerable after 48 hours

● Patching plateaued at 4%

● Only 10% of vulnerable sites replaced certificates

● 15% of replaced cert's used vulnerable keys

Heartbleed vulnerable hosts

Update process is slow, incomplete, and faulty

Page 4: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

4https://en.wikipedia.org/wiki/Pwn2Own

Bugs are everywhere?

Page 5: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

5

Different threat models

Page 6: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

6

Problem: broken abstractions?

C/C++ void log(int a) { printf("Log: "); printf("%d", a);}void (*fun)(int) = &log;void init() { fun(15);}

ASMlog: ... fun: .quad loginit: ... movl $15, %edi movq fun(%rip), %rax call *%rax

Page 7: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

7

Control-FlowHijack Attack

Page 8: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

8

Attack scenario: code injection

● Force memory corruption to set up attack● Redirect control-flow to injected code

Code Heap Stack

Page 9: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

9

Attack scenario: code reuse

● Find addresses of gadgets● Force memory corruption to set up attack● Redirect control-flow to gadget chain

Code Heap Stack

Page 10: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

10

Attacker model: hijacking control-flow

Attacker may read/write arbitrary data– Code is read-only, vtables are read-only

– Code pointers remain writable!

Code Heap Stack

vtables

RX

R

RWRW

Page 11: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

11

Demo Time!

Page 12: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

12

Control-Flow Bending

● Attacker-controlled execution along valid CFG– Generalization of non-control-data attacks

● Each individual control-flow transfer is valid– Execution trace may not match non-exploit case

● Circumvents protection of CFI

Nicholas Carlini, Antonio Barresi, Mathias Payer, David Wagner, and Thomas R. Gross“Control-Flow Bending”, Usenix SEC'15

Page 13: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

13

What does a CFG look like?

system()

vuln()

Page 14: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

14

What does a CFG look like? Really?

system()

vuln()

memcpy()

Page 15: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

15

Necessity of shadow stack*

● Defenses without stack integrity are broken– Loop through two calls to the same function

– Choose any caller as return location

● Shadow stack enforces stack integrity– Attacker restricted to arbitrary targets on the stack

– Each target can only be called once, in sequence

* Control-Flow Bending: On the Effectiveness of Control-Flow Integrity. Nicholas Carlini, Antonio Barresi, Mathias Payer, David Wagner, and Thomas R. Gross. In Usenix SEC'15

void func() {…bar();… void bar() { … }bar();…

}

Page 16: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

16

CFB key lessons

● CFI without shadow stack is broken– Stateless defenses insufficient for stack attacks

● Turing-complete programming in most contexts– Bend execution to dispatcher/functional gadgets

– In case study CFI not effective for 5/6 vulnerabilities

● Attack is program-dependent, harder to pull off

Page 17: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

17

Counterfeit OO Programming

● OO-programs use vtables for inheritance

● Introduce fake objects– Use valid vtables

– Functions become gadgets

– Chaining functions gives Turing-completeness

● Stateless defenses struggle

Felix Schuster, Thomas Tendyck, Christopher Liebchen, Lucas Davi, Ahmed-Reza Sadeghi, and Thorsten Holz. Counterfeit Object-Oriented Programming, Oakland'15

Page 18: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

18

Mitigation space in a nutshell [SP13]

Memory/type safety

Integrity

Confidentiality

Flow Integrity

Bad things

C *C

&C

*&C

Corruption

Codecorruption

Control-flowhijack

C

&C

*&C

SoftBound [PLDI09, POPL12, ISCA12]; CCured [POPL02]; DShield/nC [2x AsiaCCS17]

Code Integrity [AMD06];SafeO [FSE03]; WIT [SP08]; CPI [OSDI14]; OTI [NDSS18]

ASLR [CCS03, 04, 10, 12]; DSR [DIMVA08]; PG [SEC03]; Diversity SoK [SP14];

CFI [CCS05]; MCFI [PLDI14]; FCFI [SEC14]; vTrust [NDSS17]; SoK [CSUR17]

Page 19: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

19

Attack classification

● Data-only attack– Overwriting arguments to exec()

● Non-control-data attack– Overwriting is_admin flag

● Control-Flow Bending– Modify function pointer to (valid) alternate target

Page 20: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

20

Control-Flow Integrity

Page 21: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

21

Control-Flow Integrity (CFI)*

● Restrict a program’s dynamic control-flow to the static control-flow graph– Requires static analysis

– Dynamic enforcement mechanism

* Control-Flow Integrity. Martin Abadi, Mihai Budiu, Ulfar Erlingsson, Jay Ligatti. CCS ‘05* Control-Flow Integrity: Protection, Security, and Performance. Nathan Burow, Scott A. Carr, Joseph Nash, Per Larsen, Michael Franz, Stefan Brunthaler, Mathias Payer. ACM CSUR ‘17

Page 22: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

22

Control-Flow Integrity (CFI)

CHECK(fn);(*fn)(x);

CHECK_RET();return 7;

Page 23: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

23

Three directions for CFI

Goal: minimize target sets, increase precision

Page 24: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

24

Enforce CFI in the kernel*

● Kernel protection crucial for system integrity● So far, kernel only coarsely protected (if at all)

● Enforce strict pointer propagation rules– Function pointers can only be assigned

– Data pointers to function pointers are forbidden

● Compiler enforces type system, instruments● High compatibility for hypervisors, kernels

* Fine-Grained Control-Flow Integrity for Kernel Software. Xinyang Ge, Nirupama Talele, Mathias Payer, and Trent Jaeger. In EuroS&P'16

Page 25: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

25

Lockdown*: enforce CFI for binaries

● Fine-grained CFI relies on source code● Coarse-grained CFI is imprecise

● Goal: enforce fine-grained CFI for binaries– Support legacy, binary code and modularity (libraries)

– Leverage precise, dynamic analysis

– Low performance overhead

● Binary translator runs online analysis, adds checks

* Fine-Grained Control-Flow Integrity through Binary HardeningMathias Payer, Antonio Barresi, and Thomas R. Gross. In DIMVA'15

Page 26: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

26

Enforce CFI for C++ applications*

● C++ applications are prone to Counterfeit Object-Oriented Programming (COOP)

● Virtual inheritance scatters code pointers

● Protect all virtual function calls– Enforce type check of prototype for virtual calls

– Sanitize VTable pointers before use

● Compiler encodes types and enforces checks

* VTrust: Regaining Trust on Your Virtual Calls. Chao Zhang, Scott A. Carr, Tongxin Li, Yu Ding, Chengyu Song, Mathias Payer, and Dawn Song. In NDSS'16

Page 27: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

27

CFI: analysis precision [CSUR17]

Greeter *o = new Greeter();o->sayHi(char *str); // o[0][1]();

Valid functions Arity

Prototype Class Hierarchy

ShrinkWrap [ACSAC15]; VTrust [NDSS17]; LLVM-CFI [head]

MCFI [CCS13, PLDI14]; RockJIT [CCS14]; PICFI [CCS15]; C-CFI [CCS15]; PathArmor [CCS15]; KCFI [EuroSP16]

CFI? [CCS05]; FCFI [SEC14]kBouncer [SEC13]; CCFIR [SP13]; binCFI [SEC13]; ROPecker [NDSS14]; DynCFI [DIMVA15]

Page 28: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

28

CFI: strength of analysis

Greeter *o = new Greeter();o->sayHi(char *str);

0xf000b400

int bar1(int b, int c, int d);

int bar2(char *str);

void bar3(char *str);

void B::foo(char *str);

class Greeter :: Base {... };void Base::bar5(char *str);

void Greeter::sayHi(char *str);

class Related :: Greeter {... };void Related::sayHi(char *str);

Page 29: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

29

Are we making progress?

2007

2017

Page 30: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

30

Class hierarchy depth

Impl. Count Chromium Firefox

[1-10] 13,751 (99.33%) 4,632 (99.90%)

>10 78 (0.57%) 47 (0.10%)

Max 78 107

CFI prohibits use of corrupted pointer.Can we do better?

Page 31: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

31

Summary: Control-Flow Integrity

● CFI restricts indirect control-flow to target set– Inherently stateless defense

– Effectiveness depends on precision of analysis and program functionality

– Low performance overhead

● Limitations– Large target sets, statelessness

– Backward edge often neglected

Page 32: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

32

Object-TypeIntegrity

Page 33: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

33

Two stages of control-flow hijacking

● Stage 1: corrupt a code pointer– Overwrite where with what?

● Stage 2: dereference the code pointer– Guide execution to dispatch

Page 34: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

34

Mitigation space in a nutshell [SP13]

Memory/type safety

Integrity

Confidentiality

Flow Integrity

Bad things

C *C

&C

*&C

Corruption

Codecorruption

Control-flowhijack

C

&C

*&C

SoftBound [PLDI09, POPL12, ISCA12]; CCured [POPL02]; DShield/nC [2x AsiaCCS17]

Code Integrity [AMD06];SafeO [FSE03]; WIT [SP08]; CPI [OSDI14]; OTI [NDSS18]

ASLR [CCS03, 04, 10, 12]; DSR [DIMVA08]; PG [SEC03]; Diversity SoK [SP14];

CFI [CCS05]; MCFI [PLDI14]; FCFI [SEC14]; vTrust [NDSS17]; SoK [CSUR17]

Page 35: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

35

Object Type Integrity (OTI)*

● Enforce integrity of vtable pointer– Relocate to safe area

– Use protected version for dispatch

* CFIXX: Object Type Integrity for C++ Virtual Dispatch. Nathan Burow, Derrick McKee, Scott A. Carr, and Mathias Payer. In ISOC NDSS '18

Code Heap Stack Safe memory area

vtables

Page 36: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

36

CFIXX instrumentation

● C++ dynamic dispatch has single target– Only constructor allowed to write vtable pointer

– Deallocation invalidates vtable pointer

– Dispatch uses vtable pointer

● Enforcing OTI protects against– VTable injection even with correct method signature

– Swap vtable even in the same hierarchy

– Fake object creation (COOP)

Page 37: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

37

CFIXX performance

● Chromium: 2.03% (Octane), 1.99% (Kraken)

Page 38: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

38

Future Directions

Page 39: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

39

Page 40: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

40

Future trends in software security

Memory/type safety

Integrity

Confidentiality

Flow Integrity

Bad things

C *C D *D

&C

*&C

&D

*&D

Memory/type corruption

Codecorruption

Data-onlyattack

Control-flowhijack

C

&C &D

*&C

Page 41: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

41

Defense: Testing vs. Mitigations

Mitigations● C++ type integrity● Data integrity● Compartments

Software Testing● Firmware fuzzing● Transform. fuzzing● Data-flow testing

Page 42: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

42

Conclusion

Page 43: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

43

● CFI makes attacks harder– Effectiveness depends on analysis and complexity

– Deployed in Microsoft Edge, Google Chrome

– Limitation: large equivalence classes

● Object Type Integrity (CFIXX)– Protect object instead of dispatch

– Single valid target per object

● Future direction: type check / overhead

Conclusion

Source: https://github.com/HexHive/CFIXX

Page 44: Guarding Vulnerable Code: Module 2: Mitigation15 Necessity of shadow stack* Defenses without stack integrity are broken – Loop through two calls to the same function – Choose any

44

Word Cloud

So

urce

: http

s://h

exhi

ve.g

ithub

.io