How to Avoid Stack Smashing Attacks with GCC

by Himanshu Arora on February 7, 2013

Stack smashing is a fancy term used for stack buffer overflows. It refers to attacks that exploit bugs in code enabling buffer overflows. Earlier it was solely the responsibility of programmers/developers to make sure that there is no possibility of a buffer overflow in their code but with time compilers like gcc have got flags to make sure that buffer overflow problems are not exploited by crackers to damage a system or a program.

I came to know about these flags when I was trying to reproduce a buffer overflow on my Ubuntu 12.04 with gcc 4.6.3 version. Here is what I was trying to do :

#include <stdio.h>
#include <string.h>

int main(void)
{
    int len = 0;
    char str[10] = {0};

    printf("\n Enter the name \n");

    gets(str); // Used gets() to cause buffer overflow

    printf("\n len = [%d] \n", len);

    len  = strlen(str);
    printf("\n len of string entered is : [%d]\n", len);

    return 0;
}

In the code above, I have used gets() to accept a string from user. and then calculated the length of this string and printed back on stdout. The idea here is to input a string whose length is more than 10 bytes. Since gets() does not check array bounds so it will try to copy the input in the str buffer and this way buffer overflow will take place.

This is what happened when I executed the program:

$ ./stacksmash 

 Enter the name
TheGeekStuff

 len = [0] 

 len of string entered is : [12]
*** stack smashing detected ***: ./stacksmash terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0xb76e4045]
/lib/i386-linux-gnu/libc.so.6(+0x103ffa)[0xb76e3ffa]
./stacksmash[0x8048548]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb75f94d3]
./stacksmash[0x8048401]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:06 528260     /home/himanshu/practice/stacksmash
08049000-0804a000 r--p 00000000 08:06 528260     /home/himanshu/practice/stacksmash
0804a000-0804b000 rw-p 00001000 08:06 528260     /home/himanshu/practice/stacksmash
0973a000-0975b000 rw-p 00000000 00:00 0          [heap]
b75af000-b75cb000 r-xp 00000000 08:06 787381     /lib/i386-linux-gnu/libgcc_s.so.1
b75cb000-b75cc000 r--p 0001b000 08:06 787381     /lib/i386-linux-gnu/libgcc_s.so.1
b75cc000-b75cd000 rw-p 0001c000 08:06 787381     /lib/i386-linux-gnu/libgcc_s.so.1
b75df000-b75e0000 rw-p 00000000 00:00 0
b75e0000-b7783000 r-xp 00000000 08:06 787152     /lib/i386-linux-gnu/libc-2.15.so
b7783000-b7784000 ---p 001a3000 08:06 787152     /lib/i386-linux-gnu/libc-2.15.so
b7784000-b7786000 r--p 001a3000 08:06 787152     /lib/i386-linux-gnu/libc-2.15.so
b7786000-b7787000 rw-p 001a5000 08:06 787152     /lib/i386-linux-gnu/libc-2.15.so
b7787000-b778a000 rw-p 00000000 00:00 0
b7799000-b779e000 rw-p 00000000 00:00 0
b779e000-b779f000 r-xp 00000000 00:00 0          [vdso]
b779f000-b77bf000 r-xp 00000000 08:06 794147     /lib/i386-linux-gnu/ld-2.15.so
b77bf000-b77c0000 r--p 0001f000 08:06 794147     /lib/i386-linux-gnu/ld-2.15.so
b77c0000-b77c1000 rw-p 00020000 08:06 794147     /lib/i386-linux-gnu/ld-2.15.so
bfaec000-bfb0d000 rw-p 00000000 00:00 0          [stack]
Aborted (core dumped)

Well, this came in as pleasant surprise that the execution environment was somehow able to detect that buffer overflow could happen in this case. In the output you can see that stack smashing was detected. This prompted me to explore as to how buffer overflow was detected.

While searching for the reason, I came across a gcc flag ‘-fstack-protector’. Here is the description of this flag (from the man page) :

-fstack-protector

Emit extra code to check for buffer overflows, such as stack smashing attacks. This is done by adding a guard variable to functions with vulnerable objects. This includes functions that call alloca, and functions with buffers larger than 8 bytes. The guards are initialized when a function is entered and then checked when the function exits. If a guard check fails, an error message is printed and the program exits.

NOTE: In Ubuntu 6.10 and later versions this option is enabled by default for C, C++, ObjC, ObjC++, if none of -fno-stack-protector, -nostdlib, nor -ffreestanding are found.

 

So you see that gcc has got this flag that emits extra code to check buffer overflows. Now the next question that came into my mind was that I never included this flag while compilation then how this functionality got enabled. Then I read the last two lines that said for Ubuntu 6.10 this functionality is enabled by default.

Then, as a next step, I decided to deactivate this functionality by using the flag ‘-fno-stack-protector’ while compilation and then try to execute the same use-case that I was doing earlier.

Here is how I did it :

$ gcc -Wall -fno-stack-protector stacksmash.c -o stacksmash
$ ./stacksmash 

 Enter the name
TheGeekStuff

 len = [26214] 

 len of string entered is : [12]

So we see that once the code was compiled with this flag then with the same input, the execution environment was not able to detect buffer overflow that actually happened and corrupted the value of variable ‘len’.

Also, if you are new to gcc, you should understand the most frequently used gcc compiler options that we discussed earlier.


Linux Sysadmin Course Linux provides several powerful administrative tools and utilities which will help you to manage your systems effectively. If you don’t know what these tools are and how to use them, you could be spending lot of time trying to perform even the basic administrative tasks. The focus of this course is to help you understand system administration tools, which will help you to become an effective Linux system administrator.
Get the Linux Sysadmin Course Now!

If you enjoyed this article, you might also like..

  1. 50 Linux Sysadmin Tutorials
  2. 50 Most Frequently Used Linux Commands (With Examples)
  3. Top 25 Best Linux Performance Monitoring and Debugging Tools
  4. Mommy, I found it! – 15 Practical Linux Find Command Examples
  5. Linux 101 Hacks 2nd Edition eBook Linux 101 Hacks Book

Bash 101 Hacks Book Sed and Awk 101 Hacks Book Nagios Core 3 Book Vim 101 Hacks Book

{ 4 comments… read them below or add one }

1 Bob February 8, 2013 at 8:02 am

Learned something new today!!! Thanks a lot.

2 Júlio Hoffimann Mendes February 8, 2013 at 1:47 pm

Nice to know about this flag.

Thanks,
Júlio.

3 Henry February 9, 2013 at 3:48 am

Nice information about the flag. This output has happened to me before – Got the original message as in article. Always traced to a buffer overflow – Nice to know the reasons for it and behind it .

Thanks, Henry

4 Arvind Singh February 27, 2013 at 2:35 pm

Now you should discuss how this can be exploited to push shellcode in large enough stack buffers and overwrite the return address in the call frame to meaningfully exploit the vulnerability.

Leave a Comment

Previous post:

Next post: