Buffer Overflow is an error to programmers as carrying the one is to elementary school math students. So what is the potential security risk, namely buffer overflow, that may arise due poor programming? Find out in this article by Ahm.
Buffer Overflow the Security Threat. What Is It? - Article (Page 2 of 3 )
Definition of buffer overflow
Most application programs have fixed-size memory (buffers) that holds data. If an attacker sends too much data into one of these buffers and if program does not check the size of data, the buffer overflows. The computer may then execute the data that overflowed as if it were a set of command instructions.Now, if the exploitable buffer exists in a privileged process, a malicious program could then take full control of the server and can do any number of things of any types.
The Stack:
Before starting the technical details of buffer overflow, lets examine what happen when a program starts executing in memory. Before a program starts executing, operating system allocates memory space for it. The memory space allocated for a program is split into code segment (instructions that are to be executed by microprocessors), data segment (data is kept here) and stack segment (variables and temporary data are kept here). Lets write a simple C program.
#include <stdio.h> int main() { char Buffer[4]; printf(“%d”,Add(5,6,7)); return 0; } int Add(int a, int b, int c) { a= a + b + c; return a; }
Code Segment 1
A stack is a contiguous block of memory containing data and used whenever a function call is made. A stack pointer (SP) points to the top of the stack. In the example above, program will start executing from main () block. When it calls Add function, following steps take place in the memory:
Function parameters will be pushed onto memory from the right to the left (in this case 7, 6, 5 will be pushed onto stack).
The return address pushed onto the stack followed by a frame pointer (address to be executed after the function returns, in this case after executing Add function). A frame pointer is used to reference the local variables (Buffer [4]) and function parameters (a, b, c) because they are at a constant distance from the FP. Diagram 1 depicts different stack region during execution of this program. In most computer architecture stacks grow from higher memory address to lower and data are copied from lower to high address.For example, if SP pointed to memory address 0x0000FFFF, stack can hold 64-kilo bytes of data.
Low Memory High Memory
Buffer
FP
Return Address
C
B
C
------> Data Copies Up---> <--------Stack Grows Down <--
Diagram 1: During Execution of Program
The Threat
Skillful attackers might want to overwrite return address with the address of their own program, so it points back to buffer and execute the intended code literally hijack the processor’s execution path. An example code that spawns a root shell in Unix systems can be found here.The root cause of buffer overflow problem is, that C/C++ is inherently unsafe. There are no bound checks on array and pointer references, that means, developer has to check the bounds, moreover, a number of unsafe string operations also exists in the standard C library, i.e., strcpy(), strcat(), sprintf(), gets().
Most Commonly, attackers exploit buffer overflow to get an interactive session on the machine. If the program being exploited runs with a high privilege level (such as root or administrator).Up to fifty percent of today’s widely exploited vulnerabilities are buffer overflows. Read here, how Microsoft's programmers have been ordered to drop everything and work on fixing security problems.
Walkthrough Example I
Lets see the following example, if you execute this little program, you are prompted to introduce a string, if you type more than 4 characters, program will end with error message (like core dump). Because the string is bigger then the memory space allocated (char[4]) for it. This is the basic idea about buffer overflow.
#include <stdio.h> int main(){ ReadMe(); } int ReadMe(){ char Buffer[4]; scanf(“%s”, Buffer); printf(“%s”,s); }
Code Segment 2
Compile the above program.
>cc –ggdb T.C –o t
/home/asad$gdb ./t GNU gdb 19991004
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type, "show copying" to see the conditions. There is absolutely no warranty for GDB.Type "show warranty" for details. This GDB was configured as "i386-redhat-linux"...
(gdb) disassemble main
Dump of assembler code for function main:
0x80483f8 <main>:push%ebp 0x80483f9 <main+1>:mov%esp,%ebp 0x80483fb <main+3>:call0x8048404 <ReadMe> 0x8048400 <main+8>:leave 0x8048401 <main+9>:ret 0x8048402 <main+10>:mov%esi,%esi End of assembler dump. (gdb)
Here, you can see return address is now 0x414141 (which is a ASCII code for 3 consecutive characters of A) instead of 0x80483fb.
NOTE: Windows programmers can download a free copy of Windows debugger (WinDbg) from Microsoft’s site. In Windows system regardless of the type of memory dump that occurs, the dump file will be placed in %SystemRoot%\MiniDump. To see your path Open Control Panel -> Click System icon -> Select Advanced tab -> click on Startup and Recovery button.
Walkthrough
Example II
When you build and execute above program, the system will crash and you see the output as in Picture 1. The best way to understand it is visually (Diagram 2 and 3). Lets analyze the forensic evidence in the event of crash of this code snippet. When the overflow function is called from main(); the code in main() will popup the string argument on the stack and call overflow(), while EIP indirectly place on the stack.
------> Data Copies Up---> <--------Stack Grows Down <--
Diagram 2: Before strcpy ()
Low Memory High Memory
‘A’‘b’‘c’ ‘d’
‘e’ ‘f’ ‘g’ ‘h’
EIP 0x0000
EAX
------> Data Copies Up---> <--------Stack Grows Down <--
Diagram 3: After strcpy ()
Imagine what would happen if the function to which we passed the oversized argument (in our case fat_buffer []) was in the kernel of operating system. You could jump to another function in the kernel. This would allow you to execute any code of your choosing and have it execute in kernel mode. Performing a successful buffer overflow attack can give you ownership of a machine.