Symbolic Execution Mathy Vanhoef @vanhoefm HITB DXB 2018, Dubai, 27 - - PowerPoint PPT Presentation

β–Ά
symbolic execution
SMART_READER_LITE
LIVE PREVIEW

Symbolic Execution Mathy Vanhoef @vanhoefm HITB DXB 2018, Dubai, 27 - - PowerPoint PPT Presentation

Rooting Routers Using Symbolic Execution Mathy Vanhoef @vanhoefm HITB DXB 2018, Dubai, 27 November 2018 Overview Symbolic Execution 4-way handshake Handling Crypto Results 2 Overview Symbolic Execution 4-way handshake Handling Crypto


slide-1
SLIDE 1

Rooting Routers Using Symbolic Execution

Mathy Vanhoef β€” @vanhoefm HITB DXB 2018, Dubai, 27 November 2018

slide-2
SLIDE 2

Overview

2

Symbolic Execution Handling Crypto 4-way handshake Results

slide-3
SLIDE 3

Overview

3

Symbolic Execution Handling Crypto 4-way handshake Results

slide-4
SLIDE 4

Symbolic Execution

4

void recv(data, len) { if (data[0] != 1) return if (data[1] != len) return int num = len/data[2] ... }

Mark data as symbolic Symbolic branch

slide-5
SLIDE 5

Symbolic Execution

5

data[0] != 1 void recv(data, len) { if (data[0] != 1) return if (data[1] != len) return int num = len/data[2] ... } data[0] == 1 void recv(data, len) { if (data[0] != 1) return if (data[1] != len) return int num = len/data[2] ... }

slide-6
SLIDE 6

Symbolic Execution

6

data[0] == 1 data[0] != 1

Continue execution: if (data[1] != len)

PC = Path Constraint

slide-7
SLIDE 7

Symbolic Execution

7

data[0] != 1 Continue execution

data[0] == 1 && data[1] != len data[0] == 1 && data[1] == len

slide-8
SLIDE 8

Symbolic Execution

8

Can data[2] equal zero under the current PC? Yes! Bug detected!

data[0] == 1 && data[1] == len void recv(data, len) { if (data[0] != 1) return if (data[1] != len) return int num = len/data[2] ...

slide-9
SLIDE 9

Implementations

Practical limitations: β€Ί π‘žπ‘π‘’β„Žπ‘‘ = 2|π‘—π‘”βˆ’π‘‘π‘’π‘π‘’π‘“π‘›π‘“π‘œπ‘’π‘‘| β€Ί Infinite-length paths β€Ί SMT query complexity

9

We build upon KLEE β€Ί Works on LLVM bytecode β€Ί Actively maintained

slide-10
SLIDE 10

Overview

10

Symbolic Execution Handling Crypto 4-way handshake Results

slide-11
SLIDE 11

Motivating Example

11

void recv(data, len) { plain = decrypt(data, len) if (plain == NULL) return if (plain[0] == COMMAND) process_command(plain) else ... }

Mark data as symbolic Summarize crypto algo. (time consuming) Analyze crypto algo. (time consuming)

Won’t reach this function!

slide-12
SLIDE 12

Efficiently handling decryption?

Decrypted output = fresh symbolic variable

12

slide-13
SLIDE 13

Example

13

void recv(data, len) { plain = decrypt(data, len) if (plain == NULL) return if (plain[0] == COMMAND) process_command(plain) else ... }

Create fresh symbolic variable Normal analysis Mark data as symbolic

οƒ  Can now analyze code that parses decrypted data

slide-14
SLIDE 14

Other than handling decryption

Handling hash functions β€Ί Output = fresh symbolic variable β€Ί Also works for HMACs (Message Authentication Codes)

14

Tracking use of crypto primitives? β€Ί Record relationship between input & output β€Ί = Treat fresh variable as information flow taint

slide-15
SLIDE 15

Detecting Crypto Misuse

Timing side-channels β€Ί βˆ€(π‘žπ‘π‘’β„Žπ‘‘): all bytes of MAC in path constraint? β€Ί If not: comparison exits on first byte difference

15

Decryption oracles β€Ί Behavior depends on unauth. decrypted data β€Ί Decrypt data is in path constraint, but not in MAC

slide-16
SLIDE 16

Overview

16

Symbolic Execution Handling Crypto 4-way handshake Results

slide-17
SLIDE 17

The 4-way handshake

Used to connect to any protected Wi-Fi network

17

Negotiates fresh PTK: pairwise transient key Mutual authentication

slide-18
SLIDE 18

4-way handshake (simplified)

18

slide-19
SLIDE 19

4-way handshake (simplified)

19

slide-20
SLIDE 20

4-way handshake (simplified)

20

PTK = Combine(shared secret, ANonce, SNonce)

slide-21
SLIDE 21

4-way handshake (simplified)

21

slide-22
SLIDE 22

4-way handshake (simplified)

22

slide-23
SLIDE 23

4-way handshake (simplified)

23

Encrypted with PTK

slide-24
SLIDE 24

4-way handshake (simplified)

24

slide-25
SLIDE 25

4-way handshake (simplified)

25

slide-26
SLIDE 26

4-way handshake (simplified)

26

Authenticated with a MAC

slide-27
SLIDE 27

We focus on the client

Symbolic execution of

27

How to get these working under KLEE? Intel’s iwd deamon wpa_supplicant kernel driver

slide-28
SLIDE 28

Intel’s iwd

Avoid running full program under KLEE β€Ί Would need to model Wi-Fi stack symbolically Our approach β€Ί iwd contains unit test for the 4-way handshake β€Ί Reuse initialization code of unit test! β€Ί Symbolically execute only receive function

28

slide-29
SLIDE 29

wpa_supplicant

Unit test uses virtual Wi-Fi interface β€Ί Would again need to simulate Wi-Fi stack… Alternative approach: β€Ί Write unit test that isolates 4-way handshake like iwd β€Ί Then symbolically execute receive function! β€Ί Need to modify code of wpa_supplicant (non-trivial)

29

slide-30
SLIDE 30

MediaTek’s Driver

No unit tests & it’s a Linux driver β€Ί Symbolically executing the Linux kernel?! Inspired by previous cases β€Ί Write unit test & simulate used kernel functions in userspace β€Ί Verify that code is correctly simulated in userspace β€Ί Again symbolically execute receive function!

30

slide-31
SLIDE 31

Not all our unit tests have clean code

31

https://github.com/vanhoefm/woot2018

slide-32
SLIDE 32

Overview

32

Symbolic Execution Handling Crypto 4-way handshake Results

slide-33
SLIDE 33

Discovered Bugs I

33

Timing side-channels β€Ί Authenticity tag not checked in constant time β€Ί MediaTek and iwd are vulnerable Denial-of-service in iwd β€Ί Caused by integer underflow β€Ί Leads to huge malloc that fails

slide-34
SLIDE 34

Discovered Bugs II

Flawed AES unwrap crypto primitive β€Ί Also in MediaTek’s kernel driver β€Ί Manually discovered

34

Buffer overflow in MediaTek kernel module β€Ί Occurs when copying the group key β€Ί Remote code execution (details follow)

slide-35
SLIDE 35

Decryption oracle in wpa_supplicant

οƒ  Decrypt group key in Msg3 (details follow)

35

Decryption oracle: β€Ί Authenticity of Msg3 not checked β€Ί But decrypts and processes data

slide-36
SLIDE 36

Rooting Routers:

Buffer overflow in MediaTek kernel module

36

slide-37
SLIDE 37

MediaTek buffer overflow preconditions I

Triggered when the client processes Msg3 β€Ί Adversary needs password of network β€Ί Examples: Wi-Fi at conferences, hotels, etc.

37

slide-38
SLIDE 38

MediaTek buffer overflow preconditions II

Which clients use the MediaTek driver? β€Ί Not part of Linux kernel source tree β€Ί Used in repeater modes of routers

38

Our target: β€Ί RT-AC51U running Padavan firmware β€Ί Original firmware has no WPA2 repeater

slide-39
SLIDE 39

Popularity of Padavan firmware

39

slide-40
SLIDE 40

Popularity of Padavan firmware

40

We exploit this version

slide-41
SLIDE 41

The vulnerable code (simplified)

41

void RMTPParseEapolKeyData(pKeyData, KeyDataLen, MsgType) { UCHAR GTK[MAX_LEN_GTK]; if (MsgType == PAIR_MSG3 || MsgType == GROUP_MSG_1) { PKDE_HDR *pKDE = find_tlv(pKeyData, KeyDataLen, WPA2GTK); GTK_KDE *pKdeGtk = (GTK_KDE*)pKDE->octet; UCHAR GTKLEN = pKDE->Len – 6; NdisMoveMemory(GTK, pKdeGtk->GTK, GTKLEN); } APCliInstallSharedKey(GTK, GTKLEN); }

slide-42
SLIDE 42

The vulnerable code (simplified)

42

void RMTPParseEapolKeyData(pKeyData, KeyDataLen, MsgType) { UCHAR GTK[MAX_LEN_GTK]; if (MsgType == PAIR_MSG3 || MsgType == GROUP_MSG_1) { PKDE_HDR *pKDE = find_tlv(pKeyData, KeyDataLen, WPA2GTK); GTK_KDE *pKdeGtk = (GTK_KDE*)pKDE->octet; UCHAR GTKLEN = pKDE->Len – 6; NdisMoveMemory(GTK, pKdeGtk->GTK, GTKLEN); } APCliInstallSharedKey(GTK, GTKLEN); }

slide-43
SLIDE 43

The vulnerable code (simplified)

43

void RMTPParseEapolKeyData(pKeyData, KeyDataLen, MsgType) { UCHAR GTK[MAX_LEN_GTK]; if (MsgType == PAIR_MSG3 || MsgType == GROUP_MSG_1) { PKDE_HDR *pKDE = find_tlv(pKeyData, KeyDataLen, WPA2GTK); GTK_KDE *pKdeGtk = (GTK_KDE*)pKDE->octet; UCHAR GTKLEN = pKDE->Len – 6; NdisMoveMemory(GTK, pKdeGtk->GTK, GTKLEN); } APCliInstallSharedKey(GTK, GTKLEN); }

Len controlled by attacker Destination buffer 32 bytes

d
slide-44
SLIDE 44

Main exploitation steps

  • Code execution in kernel
  • Obtain a process context
  • Inject shellcode in process
  • Run injected shellcode

44

slide-45
SLIDE 45

Main exploitation steps

  • Code execution in kernel
  • Obtain a process context
  • Inject shellcode in process
  • Run injected shellcode

45

slide-46
SLIDE 46

Gaining kernel code execution

How to control return address & where to return? β€Ί Kernel doesn’t use stack canaries β€Ί Kernel stack has no address randomization β€Ί And the kernel stack is executable

46

Return to shellcode on stack & done?

slide-47
SLIDE 47

Gaining kernel code execution

How to control return address & where to return? β€Ί Kernel doesn’t use stack canaries β€Ί Kernel stack has no address randomization β€Ί And the kernel stack is executable

47

Return to shellcode on stack & done? Nope… our shellcode crashes

slide-48
SLIDE 48

Problem: cache incoherency on MIPS

Data cache

…

  • ld stack data

…

48

Memory

…

  • ld stack data

…

slide-49
SLIDE 49

Problem: cache incoherency on MIPS

Data cache

…

shellcode

…

49

Instruction cache

…

<no cached entry>

…

Memory

…

  • ld stack data

…

Fetch

slide-50
SLIDE 50

Problem: cache incoherency on MIPS

Data cache

…

shellcode

…

50

Instruction cache

…

  • ld stack data

…

Memory

…

  • ld stack data

…

Fetch

slide-51
SLIDE 51

Solution: flush cache after write

Data cache

…

shellcode

…

51

Instruction cache

…

<no cached entry>

…

Memory

…

  • ld stack data

…

Flush

slide-52
SLIDE 52

Solution: flush cache after write

Data cache

…

shellcode

…

52

Instruction cache

…

<no cached entry>

…

Memory

…

shellcode

…

Flush Fetch

slide-53
SLIDE 53

Solution: flush cache after write

Data cache

…

shellcode

…

53

Instruction cache

…

shellcode

…

Memory

…

shellcode

…

Flush Fetch

slide-54
SLIDE 54

How to flush the cache?

Execute kernel function to flush cache β€Ί Rely on Return Oriented Programming (ROP) β€Ί Use mipsrop tool of Craig Heffner

54

οƒ  Building ROP chain is tedious but doable

slide-55
SLIDE 55

Main exploitation steps

  • Code execution in kernel
  • Obtain a process context
  • Inject shellcode in process
  • Run injected shellcode

55

slide-56
SLIDE 56

Obtaining a process context

Code execution in kernel, let’s spawn a shell? β€Ί Tricky when in interrupt context β€Ί Easier in process context: access to address space

56

How to obtain a process context? β€Ί System calls run in process context … β€Ί … so intercept a close() system call

slide-57
SLIDE 57

Intercepting system calls

57

System call table:

sys_open sys_read sys_close …

sys_close normal code

slide-58
SLIDE 58

Intercepting system calls

58

System call table:

sys_open sys_read sys_close …

sys_close normal code Interceptor attackers code Jump to sys_close

slide-59
SLIDE 59

Main exploitation steps

  • Code execution in kernel
  • Obtain a process context
  • Inject shellcode in process
  • Run injected shellcode

59

slide-60
SLIDE 60

Hijacking a process

Kernel now executes in process context β€Ί Hijack unimportant detect_link process β€Ί Recognize by its predictable PID Now easy to inject shellcode in process:

  • 1. Call mprotect to mark process code writable
  • 2. Copy user space shellcode to return address
  • 3. Flush caches

60

slide-61
SLIDE 61

Main exploitation steps

  • Code execution in kernel
  • Obtain a process context
  • Inject shellcode in process
  • Run injected shellcode

61

slide-62
SLIDE 62

User space shellcode

When close() returns, shellcode is triggered β€Ί It runs β€œtelnetd –p 1337 –l /bin/sh” using execve β€Ί Adversary can now connect to router Important remaks: β€Ί Original process is killed, but causes no problems β€Ί Used telnetd to keep shellcode small

62

slide-63
SLIDE 63

Running the full exploit

Multi-chain exploit. Space for shellcode? β€Ί For initial stage we have 250 bytes β€Ί Handshake frame can transport ~2048 bytes β€Ί We can even use null bytes!

63

slide-64
SLIDE 64

Exploit recap & lessons learned

64

io.netgarage.org

___ / /\ /__/\ / /::\ \__\:\ / /:/\:\ / /::\ / /:/ \:\ __/ /:/\/ /__/:/ \__\:\ /__/\/:/~~ \ \:\ / /:/ \ \::/ \ \:\ /:/ \ \:\ \ \:\/:/ \__\/ \ \::/ \__\/

Debug with infinite loops

First test ideas in C Cache incoherence

slide-65
SLIDE 65

Decryption Oracle

65

slide-66
SLIDE 66

Recall: decryption oracle in wpa_supplicant

66

Decryption oracle: β€Ί Authenticity of Msg3 not checked β€Ί Does decrypt and process data

How can this be abused to leak data?

slide-67
SLIDE 67

Background: process ordinary Msg3

On reception of Msg3 the receiver:

  • 1. Decrypts the Key Data field

67

header Key Data

Encrypted and authenticated

slide-68
SLIDE 68

Background: process ordinary Msg3

On reception of Msg3 the receiver:

  • 1. Decrypts the Key Data field
  • 2. Parses the type-length-values elements

68

header

Encrypted and authenticated

slide-69
SLIDE 69

Background: process ordinary Msg3

On reception of Msg3 the receiver:

  • 1. Decrypts the Key Data field
  • 2. Parses the type-length-values elements

69

header 48 18 Type Len

Encrypted and authenticated

slide-70
SLIDE 70

Background: process ordinary Msg3

On reception of Msg3 the receiver:

  • 1. Decrypts the Key Data field
  • 2. Parses the type-length-values elements

70

header 48 18 π’›πŸ … π’›πŸπŸ– Type Len RSNE

Encrypted and authenticated

slide-71
SLIDE 71

Background: process ordinary Msg3

On reception of Msg3 the receiver:

  • 1. Decrypts the Key Data field
  • 2. Parses the type-length-values elements

71

header 48 18 π’›πŸ … π’›πŸπŸ– 221 38 Type Len RSNE Type Len

Encrypted and authenticated

slide-72
SLIDE 72

Background: process ordinary Msg3

On reception of Msg3 the receiver:

  • 1. Decrypts the Key Data field
  • 2. Parses the type-length-values elements

72

header 48 18 π’›πŸ … π’›πŸπŸ– 221 38 π’šπŸ … π’šπŸ’πŸ– Type Len RSNE Type Len GTK

Encrypted and authenticated

slide-73
SLIDE 73

Background: process ordinary Msg3

On reception of Msg3 the receiver:

  • 1. Decrypts the Key Data field
  • 2. Parses the type-length-values elements
  • 3. Extracts and installs the group key (GTK)

73

header 48 18 π’›πŸ … π’›πŸπŸ– 221 38 π’šπŸ … π’šπŸ’πŸ– Type Len RSNE Type Len GTK

Encrypted and authenticated

slide-74
SLIDE 74

How to turn parsing into an oracle?

74

slide-75
SLIDE 75

Constructing an oracle

75

header 221 38 π’šπŸ … π’šπŸ’πŸ– Type Len GTK

Encrypted Adversary knows type and length, but not GTK

slide-76
SLIDE 76

Constructing an oracle

76

header 221 36 π’šπŸ … π’šπŸ’πŸ– Type Len

Encrypted Adversary knows type and length, but not GTK.

  • 1. Reduce length by two
slide-77
SLIDE 77

Constructing an oracle

77

header 221 36 π’šπŸ … π’šπŸ’πŸ– Type Len

Encrypted Adversary knows type and length, but not GTK.

  • 1. Reduce length by two
  • 2. Parsing
slide-78
SLIDE 78

Constructing an oracle

78

header 221 36 π’šπŸ … π’šπŸ’πŸ– Type Len

Encrypted Adversary knows type and length, but not GTK.

  • 1. Reduce length by two
  • 2. Parsing
slide-79
SLIDE 79

Constructing an oracle

79

header 221 36 π’šπŸ … π’šπŸ’πŸ” π’šπŸ’πŸ• π’šπŸ’πŸ– Type Len GTK’

Encrypted Adversary knows type and length, but not GTK.

  • 1. Reduce length by two
  • 2. Parsing
slide-80
SLIDE 80

Constructing an oracle

80

header 221 36 π’šπŸ … π’šπŸ’πŸ” π’šπŸ’πŸ• π’šπŸ’πŸ– Type Len GTK’ Type Len

Encrypted Adversary knows type and length, but not GTK.

  • 1. Reduce length by two
  • 2. Parsing only succeeds if π’šπŸ’πŸ– equals zero
slide-81
SLIDE 81

Constructing an oracle

81

header 221 36 π’šπŸ … π’šπŸ’πŸ” π’šπŸ’πŸ• π’šπŸ’πŸ– Type Len GTK’ Type Len

Encrypted Adversary knows type and length, but not GTK.

  • 1. Reduce length by two
  • 2. Parsing only succeeds if π’šπŸ’πŸ– equals zero
  • 3. Keep flipping encrypted π’šπŸ’πŸ– until parsing succeeds
slide-82
SLIDE 82

Abusing the oracle in practice

  • 1. Guess the last byte (in our example π’šπŸ’πŸ–)
  • 2. XOR the ciphertext with the guessed value
  • 3. Correct guess: decryption of π’šπŸ’πŸ– is zero

Parsing succeeds & we get a reply

  • 4. Wrong guess: decryption of π’šπŸ’πŸ– is non-zero

Parsing fails, no reply

οƒ  Keep guessing last byte until parsing succeeds

82

slide-83
SLIDE 83

Practical aspects

Test against Debian 8 client: β€Ί Adversary can guess a value every 14 seconds β€Ί Decrypting 16-byte group key takes ~8 hours

83

Attack can be made faster by: β€Ί Attacking several clients simultaneously β€Ί Can brute-force the last 4 bytes

slide-84
SLIDE 84

The big picture

84

slide-85
SLIDE 85

The big picture

85

Although limitations remain, symbolic execution tools are now more usable & efficient.

slide-86
SLIDE 86

Future symbolic execution work

Short-term β€Ί Efficiently simulate reception of multiple packets β€Ί If 1st packet doesn’t affect state, stop exploring this path Long-term β€Ί Extract packet formats and state machine β€Ί Verify basic properties of protocol

86

slide-87
SLIDE 87

Conclusion

β€Ί Symbolic execution of protocols β€Ί Simple simulation of crypto β€Ί Root exploit & decryption oracle β€Ί Interesting future work

87

slide-88
SLIDE 88

Questions?

Thank you!