CSCE 465 Lecture 6
« previous | Thursday, January 31, 2013 | next »
Other Buffer Overflow Vulnerabilities
Off-by-One Overflow
void notSoSafeCopy(char *input) {
char buffer[512]; int i;
for (i=0; i<=512; i++) { // THIS SHOULD BE '<' INSTEAD OF '<='
buffer[i] = input[i];
}
}
void main(int argc, char *argv[]) {
if (argc == 2) {
notSoSafeCopy(argv[1]);
}
}
1-byte overflow can't change RET, but can change pointer to previous stack frame.
- On a little-endian architecture, one can make it point to buffer.
Heap Overflow
Overflowing buffers on heap can change pointers that point to important data.
- sometimes can also transfer executino to attack code
- change filename to AUTOEXEC.BAT, for example, to modify Windows boot behavior [1]
Function Pointer Overflow
C uses function pointers for callbacks: if pointer to F is stored in memory location P, then another function G can call F as (*P)(...)
Format Strings
Proper use of printf format string
int foo = 1234;
printf("foo = %d in decimal, %X in hex", foo, foo);
Prints
foo = 1234 in decimal, 4D2 in hex
Sloppy use
char buf[13] = "Hello, world!";
printf(buf);
should've used printf("%s", buf);
If buffer contains format symbols starting with '%', location pointed to by printf's internal stack pointer will be interpreted as an argument of printf.
%n tells printf to write number of characters that have been printed.
- Argument of pritf is interpreted as destination address.
- printf("Overflow this!%n", &myVar); prints Overflow this!14
Other Overflow Targets
- Heap Management Structures Used by malloc
- URL validation and canonicalization
- if server stores URL in buffer with overflow, then attacker can gain control by typing malformed URL
- Microsoft IIS
- Some attacks don't even need overflow:
- http://victim.com/user/../../autoexec.bat may give access to system file.
- Defeat check for '/' chars by using hex representation in URL
Buffer Overflow Defense
(See wikipedia:Buffer overflow protection→)
Writing correct code
- Use safe languages like Java
- Use compilers that warn about linking to unsafe functions (gcc)
- Static analysis of source code to find overflows
- Black-box testing with long strings
- Use safer versions of functions (gets and strcpy should be replaced with getline and strlcpy)
Problem: no input size checking:
- strcpy(buf, str) simply copies memory contents into buf starting from *str until '\0' is encountered, ignoring the size of area allocated to buf
- strncpy(buf, str, n) copies n characters from *str into buf
Non-Executable Buffers
Works by marking a region of memory as non-executable.
Problem with recent systems: emit executable code within data section, but more applicable to stack segment since no legitimate programs have code in stack
Non-executable Stack
- AMD Athlon 64, Intel P4 "Prescott", but not 32-bit x86
- NX bit on every page table entry
- Some applications need executable stack (e.g. LISP interpreters)
- Does not defend against return-to-libc attacks since libc code already exists and is executable or other pointer attacks
Address Randomization
- Motivation: introduce artificial diversity to prevent the same code from infecting multiple machines
- randomize stack location, addresses of library routines, etc.
- encrypt return address on stack by XORing with random string
- attacker won't know what address to use
- Attack by repetitively guessing randomized addresses [2] or spraying injected attack code everywhere in memory
- Vista/7/8 has this enabled, and software is available for Linux and other UNIX systems
Array bounds checking
- completely stops buffer overflow attacks
- all reads and writes to arrays are bound-checked in Jana and .NET languages
- solves problem at cost of performance.
- Libsafe (Dynamically loaded) intercepts calls to strcpy(dest, src) and checks if there is sufficient space in current stack frame: |frame_pointer - dest| > strlen(src)
- if yes, does strcpy; else terminates application.
,------------, | v -------+-----+----------+------+-----+---------------+-----+----------+--------- | sfp | ret_addr | dest | src | buf | sfp | ret_addr | -------+-----+----------+------+-----+---------------+-----+----------+---------
Code pointer integrity checking
- Detects whether code pointer (e.g. return address, function pointer) has been corrupted before dereferencing it.
- Prevents only overflow attacks exploiting automatic buffers
- better performance than array bounds checking
- e.g. StackGuard
How this works
- embeds random canary strings into stack frames
- buffer overflow will have to go through canary to get to stack pointer.
- attacker cannot guess what the value of the canary will be.
- check/verify integrity of canary before returning
Cons
- built into compiled code, so code must be recompiled with StackGuard to enable
- performance hit (8% for Apache Server) Other similar technology exists (e.g. PointGuard), but can have even worse performance overhead
- StackGuard can be defeated [3]
Footnotes
- ↑ ...and that's why I don't use Windows
- ↑ this method will be used in homework
- ↑ Phrack article by Bulba and Kil3r: http://phrack.org/issues.html?issue=56&id=5