0% found this document useful (0 votes)
9 views45 pages

CSE351 L15 Buffoverflow - 20sp Ink

The document discusses buffer overflows, a common security vulnerability in programming, particularly in C, where unchecked array bounds can lead to overwriting memory. It outlines the memory layout in x86-64 Linux and explains how stack and heap memory can be exploited through buffer overflows. The document also highlights the importance of proper input handling and the risks associated with certain Unix functions that do not limit input size.

Uploaded by

Menberu Munye
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views45 pages

CSE351 L15 Buffoverflow - 20sp Ink

The document discusses buffer overflows, a common security vulnerability in programming, particularly in C, where unchecked array bounds can lead to overwriting memory. It outlines the memory layout in x86-64 Linux and explains how stack and heap memory can be exploited through buffer overflows. The document also highlights the importance of proper input handling and the risks associated with certain Unix functions that do not limit input size.

Uploaded by

Menberu Munye
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 45

L15: Buffer Overflows CSE351, Spring 2020

Buffer Overflows
CSE 351 Spring 2020
Instructor: Teaching Assistants:
Ruth Anderson Alex Olshanskyy Callum Walker Chin Yeoh
Connie Wang Diya Joy Edan Sneh
Eddy (Tianyi) Zhou Eric Fan Jeffery Tian
Jonathan Chen Joseph Schafer Melissa Birchfield
Millicent Li Porter Jones Rehaan Bhimani

http://xkcd.com/2291/
L15: Buffer Overflows CSE351, Spring 2020

Administrivia
 Lab 2 (x86‐64) due TONIGHT, Friday (5/01)
 Since you are submitting a text file (defuser.txt), there
won’t be any Gradescope autograder output this time
 Extra credit needs to be submitted to the extra credit
assignment
 Unit Summary #2, due Friday (5/08)
 Lab 3 coming soon!
 You will have everything you need by the end of this lecture
 You must log on with your @uw google account to access!!
 Google doc for 11:30 Lecture: https://tinyurl.com/351‐05‐01A
 Google doc for 2:30 Lecture: https://tinyurl.com/351‐05‐01B

2
L15: Buffer Overflows CSE351, Spring 2020

Buffer Overflows
 Address space layout (more details!)
 Input buffers on the stack
 Overflowing buffers and injecting code
 Defenses against buffer overflows

3
L15: Buffer Overflows CSE351, Spring 2020

not drawn to scale


Review: General Memory Layout
2N‐1
 Stack Stack
 Local variables (procedure context)
 Heap
 Dynamically allocated as needed
 malloc(), calloc(), new, … Heap

 Statically allocated Data


 Read/write: global variables (Static Data) Static Data
 Read‐only: string literals (Literals)
 Code/Instructions Literals

 Executable machine instructions


Instructions
 Read‐only 0
4
L15: Buffer Overflows CSE351, Spring 2020

This is extra (non‐testable) material


x86‐64 Linux Memory Layout
0x00007FFFFFFFFFFF
Stack
 Stack
 Runtime stack has 8 MiB limit
 Heap Heap
 Dynamically allocated as needed
 malloc(), calloc(), new, …
 Statically allocated data (Data) Shared
Libraries
 Read‐only: string literals
 Read/write: global arrays and variables
 Code / Shared Libraries
Heap
 Executable machine instructions
Data
 Read‐only Instructions
Hex Address 0x400000
0x000000 5
L15: Buffer Overflows CSE351, Spring 2020

not drawn to scale


Memory Allocation Example
char big_array[1L<<24]; /* 16 MB */ Stack
char huge_array[1L<<31]; /* 2 GB */

int global = 0;
Heap
int useless() { return 0; }

int main()
{
void *p1, *p2, *p3, *p4; Shared
int local = 0; Libraries
p1 = malloc(1L << 28); /* 256 MB */
p2 = malloc(1L << 8); /* 256 B */
p3 = malloc(1L << 32); /* 4 GB */
p4 = malloc(1L << 8); /* 256 B */ Heap
/* Some print statements ... */
} Data
Instructions
Where does everything go?
6
L15: Buffer Overflows CSE351, Spring 2020

not drawn to scale


Memory Allocation Example
char big_array[1L<<24]; /* 16 MB */ Stack
char huge_array[1L<<31]; /* 2 GB */

int global = 0;
Heap
int useless() { return 0; }

int main()
{
void *p1, *p2, *p3, *p4; Shared
int local = 0; Libraries
p1 = malloc(1L << 28); /* 256 MB */
p2 = malloc(1L << 8); /* 256 B */
p3 = malloc(1L << 32); /* 4 GB */
p4 = malloc(1L << 8); /* 256 B */ Heap
/* Some print statements ... */
} Data
Instructions
Where does everything go?
7
L15: Buffer Overflows CSE351, Spring 2020

What Is a Buffer?
 A buffer is an array used to temporarily store data

 You’ve probably seen “video buffering…”


 The video is being written into a buffer before being played

 Buffers can also store user input

8
L15: Buffer Overflows CSE351, Spring 2020

Reminder: x86‐64/Linux Stack Frame


Higher Addresses
 Caller’s Stack Frame
 Arguments (if > 6 args) for this call
 Current/ Callee Stack Frame Caller
Frame
 Return address Arguments
• Pushed by call instruction 7, 8, …
 Old frame pointer (optional) Frame pointer Return Addr
 Caller‐saved pushed before setting up %rbp Old %rbp
(Optional)
arguments for a function call Saved
 Callee‐saved pushed before using Registers
long‐term registers +
 Local variables Local
Variables
(if can’t be kept in registers)
 “Argument build” area Argument
(Need to call a function with >6 Stack pointer Build
arguments? Put them here) %rsp (Optional)
Lower Addresses 9
L15: Buffer Overflows CSE351, Spring 2020

Buffer Overflow in a Nutshell


 C does not check array bounds
 Many Unix/Linux/C functions don’t check argument sizes
 Allows overflowing (writing past the end) of buffers (arrays)

 “Buffer Overflow” = Writing past the end of an array

 Characteristics of the traditional Linux memory layout


provide opportunities for malicious programs
 Stack grows “backwards” in memory
 Data and instructions both stored in the same memory

10
L15: Buffer Overflows CSE351, Spring 2020

Higher Addresses
Buffer Overflow in a Nutshell 00
00
 Stack grows down towards lower 00

addresses Return 00
Address 00
40
 Buffer grows up towards higher dd
addresses bf
buf[7]

 If we write past the end of the '\0'


array, we overwrite data on the 'o'

stack! 'l'
'l'
Enter input: hello 'e'
buf[0] 'h'
No overflow  Lower Addresses 11
L15: Buffer Overflows CSE351, Spring 2020

Higher Addresses
Buffer Overflow in a Nutshell 00
00
 Stack grows down towards lower 00

addresses Return 00
Address 00
40
 Buffer grows up towards higher dd
addresses bf
buf[7]

 If we write past the end of the


array, we overwrite data on the
stack!
Enter input: helloabcdef
buf[0]
Lower Addresses 12
L15: Buffer Overflows CSE351, Spring 2020

Higher Addresses
Buffer Overflow in a Nutshell 00
00
 Stack grows down towards lower 00

addresses Return 00
Address '\0'
'f'
 Buffer grows up towards higher 'e'
addresses 'd'
buf[7] 'c'
'b'
 If we write past the end of the 'a'
array, we overwrite data on the 'o'

stack! 'l'
'l'
Enter input: helloabcdef 'e'
buf[0] 'h'
Buffer overflow!  Lower Addresses 13
L15: Buffer Overflows CSE351, Spring 2020

Buffer Overflow in a Nutshell


 Buffer overflows on the stack can overwrite
“interesting” data
 Attackers just choose the right inputs

 Simplest form (sometimes called “stack smashing”)


 Unchecked length on string input into bounded array causes
overwriting of stack data
 Try to change the return address of the current procedure

 Why is this a big deal?


 It was the #1 technical cause of security vulnerabilities
• #1 overall cause is social engineering / user ignorance
14
L15: Buffer Overflows CSE351, Spring 2020

String Library Code


 Implementation of Unix function gets()
/* Get string from stdin */
char* gets(char* dest) {
int c = getchar();
char* p = dest; pointer to start
while (c != EOF && c != '\n') { of an array
*p++ = c;
c = getchar();
} same as:
*p = '\0'; *p = c;
return dest;
} p++;
 What could go wrong in this code?

15
L15: Buffer Overflows CSE351, Spring 2020

String Library Code


 Implementation of Unix function gets()
/* Get string from stdin */
char* gets(char* dest) {
int c = getchar();
char* p = dest;
while (c != EOF && c != '\n') {
*p++ = c;
c = getchar();
}
*p = '\0';
return dest;
}
 No way to specify limit on number of characters to read
 Similar problems with other Unix functions:
 strcpy: Copies string of arbitrary length to a dst
 scanf, fscanf, sscanf, when given %s specifier 16
L15: Buffer Overflows CSE351, Spring 2020

Vulnerable Buffer Code


/* Echo Line */
void echo() {
char buf[8]; /* Way too small! */
gets(buf);
puts(buf);
}

void call_echo() {
echo();
}

unix> ./buf-nsp
Enter string: 123456789012345
123456789012345

unix> ./buf-nsp unix> ./buf-nsp


Enter string: 1234567890123456 Enter string: 12345678901234567
Illegal instruction Segmentation Fault
17
L15: Buffer Overflows CSE351, Spring 2020

Buffer Overflow Disassembly (buf-nsp)


echo:
0000000000400597 <echo>:
400597: 48 83 ec 18 sub $0x18,%rsp
... ... calls printf ...
4005aa: 48 8d 7c 24 08 lea 0x8(%rsp),%rdi
4005af: e8 d6 fe ff ff callq 400480 <gets@plt>
4005b4: 48 89 7c 24 08 lea 0x8(%rsp),%rdi
4005b9: e8 b2 fe ff ff callq 4004a0 <puts@plt>
4005be: 48 83 c4 18 add $0x18,%rsp
4005c2: c3 retq

call_echo:
00000000004005c3 <call_echo>:
4005c3: 48 83 ec 08 sub $0x8,%rsp
4005c7: b8 00 00 00 00 mov $0x0,%eax
4005cc: e8 c6 ff ff ff callq 400597 <echo>
4005d1: 48 83 c4 08 add $0x8,%rsp
4005d5: c3 retq
return address 18
L15: Buffer Overflows CSE351, Spring 2020

Buffer Overflow Stack


Before call to gets
/* Echo Line */
Stack frame for void echo()
call_echo {
char buf[8]; /* Way too small! */
gets(buf);
Return address puts(buf);
(8 bytes) }

8 bytes unused echo:


subq $24, %rsp
[7] [6] [5] [4] ...
leaq 8(%rsp), %rdi
[3] [2] [1] [0] buf call gets
...
8 bytes unused
⟵%rsp

Note: addresses increasing right‐to‐left, bottom‐to‐top

19
L15: Buffer Overflows CSE351, Spring 2020

Buffer Overflow Example


Before call to gets
void echo() echo:
Stack frame for { subq $24, %rsp
call_echo char buf[8]; ...
gets(buf); leaq 8(%rsp), %rdi
. . . call gets
00 00 00 00 } ...
00 40 05 d1
call_echo:
8 bytes unused . . .
4005cc: callq 400597 <echo>
[7] [6] [5] [4] 4005d1: add $0x8,%rsp
[3] [2] [1] [0] buf . . .

8 bytes unused
⟵%rsp

20
L15: Buffer Overflows CSE351, Spring 2020

Buffer Overflow Example #1


After call to gets
void echo() echo:
Stack frame for { subq $24, %rsp
call_echo char buf[8]; ...
gets(buf); leaq 8(%rsp), %rdi
. . . call gets
00 00 00 00 } ...
00 40 05 d1
00 35 34 33
call_echo:
32 31 30 39 . . .
4005cc: callq 400597 <echo>
38 37 36 35 4005d1: add $0x8,%rsp
34 33 32 31 buf . . .

8 bytes unused
⟵%rsp
unix> ./buf-nsp
Note: Digit “𝑁” is Enter string: 123456789012345
just 0x3𝑁 in ASCII! 123456789012345
Overflowed buffer, but did not corrupt state
21
L15: Buffer Overflows CSE351, Spring 2020

Buffer Overflow Example #2


After call to gets
void echo() echo:
Stack frame for { subq $24, %rsp
call_echo char buf[8]; ...
gets(buf); leaq 8(%rsp), %rdi
. . . call gets
00 00 00 00 } ...
00 40 05 00
36 35 34 33
call_echo:
32 31 30 39 . . .
4005cc: callq 400597 <echo>
38 37 36 35 4005d1: add $0x8,%rsp
34 33 32 31 buf . . .

8 bytes unused
⟵%rsp
unix> ./buf-nsp
Enter string: 1234567890123456
Illegal instruction
Overflowed buffer and corrupted return pointer
22
L15: Buffer Overflows CSE351, Spring 2020

Buffer Overflow Example #2 Explained


After return from echo
00000000004004f0 <deregister_tm_clones>:
Stack frame for 4004f0: push %rbp
call_echo 4004f1: mov $0x601040,%eax
⟵%rsp 4004f6: cmp $0x601040,%rax
00 00 00 00 4004fc: mov %rsp,%rbp
00 40 05 00 4004ff: je 400518
400501: mov $0x0,%eax
36 35 34 33 400506: test %rax,%rax
32 31 30 39 400509: je 400518
38 37 36 35 40050b: pop %rbp
40050c: mov $0x601040,%edi
34 33 32 31 buf 400511: jmpq *%rax
400513: nopl 0x0(%rax,%rax,1)
8 bytes unused 400518: pop %rbp
400519: retq

“Returns” to a byte that is not the beginning of an instruction,


so program signals SIGILL, Illegal instruction

23
L15: Buffer Overflows CSE351, Spring 2020

Malicious Use of Buffer Overflow:


Code Injection Attacks Stack after call to gets()
High Addresses

void foo(){ foo


bar(); stack frame
A:... return address A
} A (return
B addr)

int bar() { data written pad


char buf[64]; bar
by gets() stack frame
gets(buf);
... exploit code
return ...; buf starts here B
}

Low Addresses
 Input string contains byte representation of executable code
 Overwrite return address A with address of buffer B
 When bar() executes ret, will jump to exploit code
24
L15: Buffer Overflows CSE351, Spring 2020

Peer Instruction Question [Buf]


 smash_me is vulnerable to stack smashing!
 What is the minimum number of characters that
gets must read in order for us to change the return
address to a stack address?
 Vote at http://PollEv.com/rea
 For example: (0x00 00 7f ff CA FE F0 0D)
Previous
stack frame
A. 27
00 00 00 00
smash_me:
subq $0x40, %rsp
B. 30
00 40 05 d1 ...
leaq 16(%rsp), %rdi
C. 51
. . .
call gets
...
D. 54
[0] E. We’re lost…
25
L15: Buffer Overflows CSE351, Spring 2020

Exploits Based on Buffer Overflows


Buffer overflow bugs can allow attackers to
execute arbitrary code on victim machines

 Distressingly common in real programs


 Programmers keep making the same mistakes 
 Recent measures make these attacks much more difficult
 Examples across the decades
 Original “Internet worm” (1988)
 Heartbleed (2014, affected 17% of servers)
• Similar issue in Cloudbleed (2017)
 Hacking embedded devices
• Cars, Smart homes, Planes
26
L15: Buffer Overflows CSE351, Spring 2020

Example: the original Internet worm (1988)


 Exploited a few vulnerabilities to spread
 Early versions of the finger server (fingerd) used gets()
to read the argument sent by the client:
• finger [email protected]
 Worm attacked fingerd server with phony argument:
• finger "exploit-code padding new-return-addr"
• Exploit code: executed a root shell on the victim machine with a
direct connection to the attacker
 Scanned for other machines to attack
 Invaded ~6000 computers in hours (10% of the Internet)
• see June 1989 article in Comm. of the ACM
 The author of the worm (Robert Morris*) was prosecuted…
27
L15: Buffer Overflows CSE351, Spring 2020

Example: Heartbleed

28
L15: Buffer Overflows CSE351, Spring 2020

Example: Heartbleed

29
L15: Buffer Overflows CSE351, Spring 2020

Example: Heartbleed

30
L15: Buffer Overflows CSE351, Spring 2020

Heartbleed (2014)
 Buffer over‐read in OpenSSL
 Open source security library
 Bug in a small range of versions
 “Heartbeat” packet
 Specifies length of message
 Server echoes it back
 Library just “trusted” this length
 Allowed attackers to read contents
of memory anywhere they wanted
 Est. 17% of Internet affected
 “Catastrophic”
 Github, Yahoo, Stack Overflow, By FenixFeather ‐ Own work, CC BY‐SA 3.0,
Amazon AWS, ... https://commons.wikimedia.org/w/index.php?curid=32276981

31
L15: Buffer Overflows CSE351, Spring 2020

Hacking Cars
 UW CSE research from 2010 demonstrated wirelessly
hacking a car using buffer overflow
 Overwrote the onboard control system’s code
 Disable brakes
 Unlock doors
 Turn engine on/off

32
L15: Buffer Overflows CSE351, Spring 2020

Dealing with buffer overflow attacks


1) Employ system‐level protections
2) Avoid overflow vulnerabilities
3) Have compiler use “stack canaries”

33
L15: Buffer Overflows CSE351, Spring 2020

1) System‐Level Protections
 Non‐executable code segments Stack after call
to gets()
 In traditional x86, can mark
foo
region of memory as either stack
“read‐only” or “writeable” frame

 Can execute anything readable B


 x86‐64 added explicit “execute”
permission data written pad bar
by gets() stack
 Stack marked as non‐executable frame
exploit
 Do NOT execute code in Stack, B
code
Static Data, or Heap regions
 Hardware support needed

Any attempt to execute this code will fail


34
L15: Buffer Overflows CSE351, Spring 2020

1) System‐Level Protections
Stack after call
 Non‐executable code segments to gets()
 Wait, doesn’t this fix everything? foo
 Works well, but can’t always use it stack
frame
 Many embedded devices do not
B
have this protection
 Cars data written pad bar
stack
 Smart homes by gets()
frame
exploit
 Pacemakers code
B
 Some exploits still work!
 Return‐oriented programming
 Return to libc attack
 JIT‐spray attack
Any attempt to execute this code will fail
35
L15: Buffer Overflows CSE351, Spring 2020

1) System‐Level Protections High Addresses

 Randomized stack offsets


 At start of program, allocate random amount Random
of space on stack allocation
 Shifts stack addresses for entire program main’s
• Addresses will vary from one run to another stack frame
 Makes it difficult for hacker to predict Other
beginning of inserted code functions’
stack frames
 Example: Code from Slide 6 executed 5
times; address of variable local = B?
• 0x7ffd19d3f8ac pad
• 0x7ffe8a462c2c
• 0x7ffe927c905c exploit
• 0x7ffefd5c27dc B? code
• 0x7fffa0175afc Low Addresses

 Stack repositioned each time program executes


36
L15: Buffer Overflows CSE351, Spring 2020

2) Avoid Overflow Vulnerabilities in Code


/* Echo Line */
void echo()
{
char buf[8]; /* Way too small! */
fgets(buf, 8, stdin);
puts(buf);
}

 Use library routines that limit string lengths


 fgets instead of gets (2nd argument to fgets sets limit)
 strncpy instead of strcpy
 Don’t use scanf with %s conversion specification
• Use fgets to read the string
• Or use %ns where n is a suitable integer

37
L15: Buffer Overflows CSE351, Spring 2020

2) Avoid Overflow Vulnerabilities in Code


 Alternatively, don’t use C ‐ use a language that does
array index bounds check
 Buffer overflow is impossible in Java
• ArrayIndexOutOfBoundsException
 Rust language was designed with security in mind
• Panics on index out of bounds, plus more protections

38
L15: Buffer Overflows CSE351, Spring 2020

3) Stack Canaries
 Basic Idea: place special value (“canary”) on stack just
beyond buffer
 Secret value that is randomized before main()
 Placed between buffer and return address
 Check for corruption before exiting function
 GCC implementation
 -fstack-protector

unix>./buf unix> ./buf


Enter string: 12345678 Enter string: 123456789
12345678 *** stack smashing detected ***
39
L15: Buffer Overflows CSE351, Spring 2020

This is extra
Protected Buffer Disassembly (buf) (non‐testable)
material
echo:
400607: sub $0x18,%rsp
40060b: mov %fs:0x28,%rax
400614: mov %rax,0x8(%rsp)
400619: xor %eax,%eax
... ... call printf ...
400625: mov %rsp,%rdi
400628: callq 400510 <gets@plt>
40062d: mov %rsp,%rdi
400630: callq 4004d0 <puts@plt>
400635: mov 0x8(%rsp),%rax
40063a: xor %fs:0x28,%rax
400643: jne 40064a <echo+0x43>
400645: add $0x18,%rsp
400649: retq
40064a: callq 4004f0 <__stack_chk_fail@plt>

40
L15: Buffer Overflows CSE351, Spring 2020

This is extra
Setting Up Canary (non‐testable)
material
Before call to gets
/* Echo Line */
Stack frame for void echo()
call_echo {
char buf[8]; /* Way too small! */
gets(buf);
Return address puts(buf);
(8 bytes) }
Segment register
echo: (don’t worry about it)
. . .
Canary movq %fs:40, %rax # Get canary
(8 bytes) movq %rax, 8(%rsp) # Place on stack
xorl %eax, %eax # Erase canary
[7] [6] [5] [4] . . .
[3] [2] [1] [0] buf ⟵%rsp

41
L15: Buffer Overflows CSE351, Spring 2020

This is extra
Checking Canary (non‐testable)
material
After call to gets
/* Echo Line */
Stack frame for void echo()
call_echo {
char buf[8]; /* Way too small! */
gets(buf);
Return address puts(buf);
(8 bytes) }

echo:
. . .
movq 8(%rsp), %rax # retrieve from Stack
Canary xorq %fs:40, %rax # compare to canary
(8 bytes) jne .L4 # if not same, FAIL
. . .
00 37 36 35 .L4: call __stack_chk_fail
34 33 32 31 buf ⟵%rsp
Input: 1234567

42
L15: Buffer Overflows CSE351, Spring 2020

Summary of Prevention Measures


1) Employ system‐level protections
 Code on the Stack is not executable
 Randomized Stack offsets

2) Avoid overflow vulnerabilities


 Use library routines that limit string lengths
 Use a language that makes them impossible

3) Have compiler use “stack canaries”

43
L15: Buffer Overflows CSE351, Spring 2020

Think this is cool?


 You’ll love Lab 3 😉
 Check out the buffer overflow simulator!
 Take CSE 484 (Security)
 Several different kinds of buffer overflow exploits
 Many ways to counter them
 Nintendo fun!
 Using glitches to rewrite code:
https://www.youtube.com/watch?v=TqK‐2jUQBUY
 Flappy Bird in Mario:
https://www.youtube.com/watch?v=hB6eY73sLV

44
L15: Buffer Overflows CSE351, Spring 2020

This is extra
Extra Notes about %rbp (non‐testable)
material

 %rbp is used to store the frame pointer


 Name comes from “base pointer”
 You can refer to a variable on the stack as
%rbp+offset
 The base of the frame will never change, so each
variable can be uniquely referred to with its offset
 The top of the stack (%rsp) may change, so referring
to a variable as %rsp-offset is less reliable
 For example, if you need save a variable for a function call,
pushing it onto the stack changes %rsp

45

You might also like