Secure Coding Lecture 2: Injections, and Buffer Overflows: Benny Pinkas
Secure Coding Lecture 2: Injections, and Buffer Overflows: Benny Pinkas
page 1
Injections
OWASP Top 10
A1 – Injection
A2 – Broken Authentication and Session Management
A3 – Cross-Site Scripting (XSS)
A4 – Insecure Direct Object References
A5 – Security Misconfiguration
A6 – Sensitive Data Exposure
A7 – Missing Function Level Access Control
A8 – Cross-Site Request Forgery (CSRF)
A9 – Using Known Vulnerable Components
A10 – Unvalidated Redirects and Forwards
(Source: OWASP Top 10 Web Application Security Risks, 2013-
2018)
Injections
• Injection
– Injection flaws, such as SQL, OS, and LDAP injection
occur when untrusted data is sent to an interpreter
as part of a command or query.
if not ok.EOF
login success
else fail;
What does this code do? Is this exploitable?
Normal Query
• The Attack
– 263,000 credit card #s stolen from database
– credit card #s stored unencrypted
– 43 million credit card #s exposed
Slide taken from John Mitchell
page 27
page 28
page 29
Blind SQL Injection
• Blind SQL injection asks the database true or false
questions and determines the answer based on the
response.
• This attack is often used when the web application is
configured to show only generic error messages, but
has not mitigated the code that is vulnerable to SQL
injection.
• Blind SQL injection works even when the database
does not output data to the web page.
• The attacker steals data by asking the database a
series of true or false questions.
Blind SQL Injection
1
if ASCII(SUBSTRING(username,1,1))
= 64 waitfor delay ‘0:0:5’
2 if ASCII(SUBSTRING(username,1,1))
= 64 waitfor delay ‘0:0:5’
2 if ASCII(SUBSTRING(username,1,1))
= 65 waitfor delay ‘0:0:5’
page 48
Buffer overflows
• Extremely common bug.
– First major exploit: 1988 Internet Worm. (exploited Unix fingerd).
page 49
What is needed
• Understanding C functions and the stack.
• Some familiarity with machine code.
• Know how system calls are made.
page 55
A comment about 64 bit
• The stack stores return addresses and local variables.
• In 32 bit x86, it also stores the arguments sent to
functions.
• In 64 bit x86, the arguments are sent in special
registers. This complicates the attacks that we will
show, but does not prevent them (since the
parameters must somehow be delivered to memory).
page 56
x86 architecture
• Any instruction can write to memory.
• Instruction pointer eip (32 bit long)
• 8 general purpose registers,
eax,ebx,ecx,edx,esi,edi,esp,ebp.
• eax contains returned value from function calls
• All other registers must be recovered after
returning from a call.
page 57
Calling a function: arguments (parameters)
page 58
Calling a function: arguments (parameters)
page 59
Calling a function: arguments (parameters)
page 61
Calling a function: local variables
• g() defines a local array of 16 chars.
• The compiler assigns this memory location on
the stack.
• Namely sub $16, %esp
page 62
Returning from a function
• The calling function, f, must remove the three
arguments it put on the stack.
– I.e., run the instruction add $12, %esp
• The called function, g, might have put many
items on the stack.
– In order to save on book keeping, when called it
sets ebp←esp, and before a return sets esp←ebp.
– Using ebp like this is popular, since arguments are
positive offsets from ebp, and local vars are
negative offsets from ebp.
page 63
Returning from a function
• In other words:
• When g begins to run (“procedure prolog”)
– push %ebp (to save the current value of ebp)
– mov %esp, %ebp
– sub $16, %esp (for a local var of length 16)
• Before g returns it does (leave cmd, “proc epilog”)
– mov %ebp, %esp (restore stack head)
– pop %ebp
– ret
page 64
A simple example
C program: assembler code of main:
void function(int a,int b,int c) push $3
{ push $2
char buffer1[5]; push $1
char buffer2[10];
call function
}
void main() {
function(1,2,3); assembler code of
function:
} push %ebp
mov %esp,%ebp
call command pushes sub $20,%esp
return address onto
stack memory is referenced in words (4
bytes). Var lengths of each
variable are rounded.
page 65
Stack contents after function call
bottom of top of
memory memory
page 66
Example: Buffer overflow causes segmentation fault
page 67
Stack contents after function call
bottom of top of
memory memory
page 68
Example: buffer overflow changes execution
slide 70
What If Buffer is Overstuffed?
• Memory pointed to by str is copied onto stack…
void func(char *str) {
strcpy does NOT check whether the string
char buf[126];
strcpy(buf,str); at *str contains more than 126 characters
}
• If a string longer than 126 bytes is copied into buffer, it will
overwrite adjacent stack locations
Top of
overflow str
Frame of the
buf calling function
stack
This will be
interpreted
as return address!
slide 71
Executing Attack Code
• Suppose attacker manages to set buffer to contain attacker-created
string
– For example, *str contains a string received from the network as input to
some network service daemon
Top of
code ret str Frame of the
calling function
stack
Attacker puts actual assembly In the overflow, a pointer back
instructions into his input string, e.g., into the buffer appears in
binary code of execve(“/bin/sh”) the location where the system
expects to find return address
slide 72
Buffer Overflow Issues
• Executable attack code is stored on stack, inside the
buffer containing attacker’s string
page 75
Which return address to use?
• Problem: attacker must find at what address the buffer
(and thus our code) will be.
– For every program, the stack will start at the same address.
– Most programs push only a few KB into the stack.
– Can try to guess exact location, and write a program to go over
these guesses.
• NOP sled
– A simpler solution: pad the beginning of the buffer (before the
exploit program) with NOP operations.
– If the return address points inside the NOPs, the exploit runs.
– Success probability improves as the buffer size increases.
– Typically, a NOP sled of few KB.
page 76
Another example
int bar (int val1) {
int val2;
foo (a_function_pointer); val1 String
} val2 grow
Contaminated s
memory
slide 77
int foo (void (*funcp)()) {
char* ptr = point_to_an_array;
char buf[128];
Attack #1: Return Address gets (buf);
strncpy(ptr, buf, 8);
(*funcp)();
}
args (funcp)
① system()
return address
① Change the return address to
ebp
point to the attack code. After
the function returns, control is pointer var (ptr)
transferred to the attack code buffer (buf)
② … or return-to-libc: use existing
instructions in the code
segment such as system(),
exec(), etc. as the attack code
slide 78
int foo (void (*funcp)()) {
pointer Variables }
strncpy(ptr, buf, 8);
(*funcp)();
return address
ebp
slide 80
Problems enabling this attack
• Stack grows in one direction (downward)
while strings and array grow in the other
direction (upward).
slide 81
Some unsafe C lib functions
• strcpy (char *dest, const char *src)
• strcat (char *dest, const char *src)
• sprintf (const char *format, … )
– Write a string into an array
– Operates on null terminated strings and does not check for overflow
of the receiving string.
• gets (char *s)
– reads a line from stdin into a buffer until either a terminating newline
or EOF.
• scanf ( const char *format, … )
– A similar problem
page 82
Methods of finding buffer overflows
• For example, to find overflows in a web server:
– Run web server on local machine.
– Issue requests with long tags.
All long tags end with “$$$$$”.
– If web server crashes,
search core dump for “$$$$$” to find
overflow location.
• Some automated tools exist. (e.g. eEye Retina).
page 83
Other types of overflow attacks
• Integer overflows:
void func(int a, int v) {
int buf[128];
buf[a] = v;
}
page 84
Preventing overflow attacks
• Main problem:
– strcpy(), strcat(), sprintf() have no range
checking.
– “Safe” versions strncpy(), strncat() are
misleading
• strncpy() will not write a string terminator if the source
string does not contain a string terminator within the
specified number of bytes.
• Defenses:
– Rewrite all legacy code to be safe, and be careful
when writing new code…
page 86