Enhance application security with FORTIFY_SOURCE
*** buffer overflow detected ***: ./foobar terminated
======= Backtrace: =========
/lib64/libc.so.6[0x382d875cff]
/lib64/libc.so.6(__fortify_fail+0x37)[0x382d906b17]
...memcpy, mempcpy, memmove, memset, strcpy, stpcpy, strncpy, strcat, 
strncat, sprintf, vsprintf, snprintf, vsnprintf, gets.If _FORTIFY_SOURCE is set to 1, with compiler optimization level 1 (gcc -O1) and above, checks that shouldn't change the behavior of conforming programs are performed. With _FORTIFY_SOURCE set to 2 some more checking is added, but some conforming programs might fail. Some of the checks can be performed at compile time, and result in compiler warnings; other checks take place at run time, and result in a run-time error if the check fails. Use of this macro requires compiler support, available with gcc(1) since version 4.0.
Consider the following example that shows potentially dangerous code:
// fortify_test.c
#include<stdio.h>
/* Commenting out or not using the string.h header will cause this
 * program to use the unprotected strcpy function.
 */
//#include<string.h>
int main(int argc, char **argv) {
char buffer[5];
printf ("Buffer Contains: %s , Size Of Buffer is %d
",
                               buffer,sizeof(buffer));
strcpy(buffer,argv[1]);
printf ("Buffer Contains: %s , Size Of Buffer is %d
",
                               buffer,sizeof(buffer));
}
~]$ gcc -D_FORTIFY_SOURCE=1 -Wall -g -O2 fortify_test.c \
    -o fortify_test~]$ objdump -d ./fortify_test
0000000000400440 :
400440:  48 83 ec 18             sub $0x18,%rsp
400444:  ba 05 00 00 00          mov $0x5,%edx
400449:  bf 10 06 40 00          mov $0x400610,%edi
40044e:  48 89 e6                mov %rsp,%rsi
400451:  31 c0                   xor %eax,%eax
400453:  e8 b8 ff ff ff          callq 400410
400458:  48 b8 64 65 61 64 62    movabs $0x6665656264616564,%rax
40045f:  65 65 66
400462:  48 89 e6                mov %rsp,%rsi
400465:  ba 05 00 00 00          mov $0x5,%edx
40046a:  48 89 04 24             mov %rax,(%rsp)
40046e:  bf 10 06 40 00          mov $0x400610,%edi
400473:  31 c0                   xor %eax,%eax
400475:  c6 44 24 08 00          movb $0x0,0x8(%rsp)
40047a:  e8 91 ff ff ff          callq 400410
40047f:  31 c0                   xor %eax,%eax
400481:  48 83 c4 18             add $0x18,%rsp
400485:  c3                      retq
400486:  66 90                   xchg %ax,%ax
$ gdb -q ./fortify_test
Reading symbols from /home/sid/security/fortify/fortify_test...done.
(gdb) br 8
Breakpoint 1 at 0x4004b8: file fortify_test.c, line 8.
(gdb) r $(python -c 'print "\x41" * 360')
Starting program: /home/sid/security/fortify/fortify_test \ 
$(python -c 'print "\x41" * 360')
Buffer Contains: ����� , Size Of Buffer is 5
Breakpoint 1, main (argc=, argv=0x7fffffffd788) at fortify_test.c:8
8 printf ("Buffer Contains: %s , Size Of Buffer is %d
",buffer,
sizeof(buffer));
(gdb) i r
rax 0x7fffffffd690 140737488344720
rbx 0x7fffffffd788 140737488344968
rcx 0x4141414141414141 4702111234474983745
rdx 0x41 65
rsi 0x7fffffffdd40 140737488346432
rdi 0x7fffffffd7ef 140737488345071
rbp 0x0 0x0
rsp 0x7fffffffd690 0x7fffffffd690
r8 0x2d 45
r9 0x0 0
r10 0x7fffffffd450 140737488344144
r11 0x382d974c60 241283058784
r12 0x4004d4 4195540
r13 0x7fffffffd780 140737488344960
r14 0x0 0
r15 0x0 0
rip 0x4004b8 0x4004b8
eflags 0x206 [ PF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb) x /100x $rax
0x7fffffffd690: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffd6a0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffd6b0: 0x41414141 0x41414141 0x41414141 0x41414141
...
0x7fffffffd7d0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffd7e0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffd7f0: 0x41414141 0x41414141 0xffffde00 0x00007fff
0x7fffffffd800: 0xffffde6a 0x00007fff 0xffffde85 0x00007fff
0x7fffffffd810: 0xffffde93 0x00007fff 0xffffdeae 0x00007fff
// fortify_test.c
#include<stdio.h>
#include<string.h>
int main(int argc, char **argv) {
char buffer[5];
printf ("Buffer Contains: %s , Size Of Buffer is %d
",
                               buffer,sizeof(buffer));
// Here the compiler the length of string to be copied
strcpy(buffer,"deadbeef");
printf ("Buffer Contains: %s , Size Of Buffer is %d
",
                               buffer,sizeof(buffer));
} 
 If we attempt to compile the above program using FORTIFY_SOURCE and an appropriate optimization flag, the compiler returns a warning because it correctly detects the buffer overflaw in the buffer variable:
 
  ~]$ gcc -D_FORTIFY_SOURCE=1 -Wall -g -O2 fortify_test.c \ 
-o fortify_test
In file included from /usr/include/string.h:636:0,
from fortify_test.c:2:
In function ‘strcpy’,
inlined from ‘main’ at fortify_test.c:7:8:
/usr/include/bits/string3.h:104:3: warning: call to 
__builtin___memcpy_chk will always overflow destination buffer 
[enabled by default]
return __builtin___strcpy_chk (__dest, __src, __bos (__dest));
^
  
 If we disassemble the binary output of the above command, we can see the call to <__memcpy_chk@plt> , which checks for a potential buffer overflow:
  
~]$ objdump -d ./fortify_test
...
00000000004004b0 :
4004b0:       48 83 ec 18             sub    $0x18,%rsp
4004b4:       ba 05 00 00 00          mov    $0x5,%edx
4004b9:       bf 80 06 40 00          mov    $0x400680,%edi
4004be:       48 89 e6                mov    %rsp,%rsi
4004c1:       31 c0                   xor    %eax,%eax
4004c3:       e8 a8 ff ff ff          callq  400470 <printf@plt>
4004c8:       48 89 e7                mov    %rsp,%rdi
4004cb:       b9 05 00 00 00          mov    $0x5,%ecx
4004d0:       ba 09 00 00 00          mov    $0x9,%edx
4004d5:       be b0 06 40 00          mov    $0x4006b0,%esi
4004da:       e8 b1 ff ff ff          callq  400490<__memcpy_chk@plt> 
4004df:       48 89 e6                mov    %rsp,%rsi
4004e2:       ba 05 00 00 00          mov    $0x5,%edx
4004e7:       bf 80 06 40 00          mov    $0x400680,%edi
4004ec:       31 c0                   xor    %eax,%eax
4004ee:       e8 7d ff ff ff          callq  400470 <printf@plt>
4004f3:       31 c0                   xor    %eax,%eax
4004f5:       48 83 c4 18             add    $0x18,%rsp
4004f9:       c3                      retq   
4004fa:       66 90                   xchg   %ax,%ax
...
 However, if the program is modified so that the strcpy function takes a value that has a variable length, compiling it will not return any warnings:
  // fortify_test.c
#include<stdio.h>
#include<string.h>
int main(int argc, char **argv) {
char buffer[5];
printf ("Buffer Contains: %s , Size Of Buffer is %d
",
                               buffer,sizeof(buffer));
// String length is determined at runtime
strcpy(buffer,argv[1]);
printf ("Buffer Contains: %s , Size Of Buffer is %d
",
                               buffer,sizeof(buffer));
}
  ~]$ gcc -D_FORTIFY_SOURCE=1 -Wall -g -O2 fortify_test.c \ 
    -o fortify_test
~]$
 Because FORTIFY_SOURCE cannot predict the length of the string that is passed from argv[1], the compiler does not return any warning related to a buffer overflow at compile time. If we run this program and supply it with a string that triggers a buffer overflow , the program terminates:
  ~]$ ./fortify_test $(python -c 'print "\x41" * 360')
Buffer Contains: �Q��� , Size Of Buffer is 5
*** buffer overflow detected ***: ./fortify_test terminated
======= Backtrace: =========
/lib64/libc.so.6[0x382d875cff]
/lib64/libc.so.6(__fortify_fail+0x37)[0x382d906b17]
/lib64/libc.so.6[0x382d904d00]
./fortify_test[0x4004dd]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x382d821d65]
./fortify_test[0x400525]
======= Memory map: ========
00400000-00401000 r-xp 00000000 fd:05 9967292 /home/sid/security/ \
fortify/fortify_test
00600000-00601000 r--p 00000000 fd:05 9967292 /home/sid/security/ \
fortify/fortify_test
00601000-00602000 rw-p 00001000 fd:05 9967292 /home/sid/security/ \
fortify/fortify_test
013ee000-0140f000 rw-p 00000000 00:00 0 [heap]
382d400000-382d420000 r-xp 00000000 fd:03 922951 /usr/lib64/ld-2.18.so
382d61f000-382d620000 r--p 0001f000 fd:03 922951 /usr/lib64/ld-2.18.so
382d620000-382d621000 rw-p 00020000 fd:03 922951 /usr/lib64/ld-2.18.so
382d621000-382d622000 rw-p 00000000 00:00 0
382d800000-382d9b4000 r-xp 00000000 fd:03 928040 /usr/lib64/ \
libc-2.18.so
382d9b4000-382dbb4000 ---p 001b4000 fd:03 928040 /usr/lib64/ \
libc-2.18.so
382dbb4000-382dbb8000 r--p 001b4000 fd:03 928040 /usr/lib64/ \
libc-2.18.so
382dbb8000-382dbba000 rw-p 001b8000 fd:03 928040 /usr/lib64/ \
libc-2.18.so
382dbba000-382dbbf000 rw-p 00000000 00:00 0
382f800000-382f815000 r-xp 00000000 fd:03 928048 /usr/lib64/ \
libgcc_s-4.8.2-20131212.so.1
382f815000-382fa14000 ---p 00015000 fd:03 928048 /usr/lib64/ \
libgcc_s-4.8.2-20131212.so.1
382fa14000-382fa15000 r--p 00014000 fd:03 928048 /usr/lib64/ \
libgcc_s-4.8.2-20131212.so.1
382fa15000-382fa16000 rw-p 00015000 fd:03 928048 /usr/lib64/ \
libgcc_s-4.8.2-20131212.so.1
7ffb727a5000-7ffb727a8000 rw-p 00000000 00:00 0
7ffb727cc000-7ffb727cf000 rw-p 00000000 00:00 0
7fffa1945000-7fffa1967000 rw-p 00000000 00:00 0 [stack]
7fffa19fe000-7fffa1a00000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted
 To conclude this post, the use of FORTIFY_SOURCE is highly recommended when compiling source code. Developers should ensure their code uses protected functions by including the correct headers, use the -D_FORTIFY_SOURCE option, and use optimization flags equal to 1 or greater. It is also important to view the log files after a compilation of the source code to spot any anomalies FORTIFY_SOURCE detected.
 For more information on FORTIFY_SOURCE, refer to http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
                             
                        
                이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.