棧緩衝區溢出

棧緩衝區溢出(stack buffer overflow或stack buffer overrun)是電腦程式把數據寫入調用棧上的內存時超出了數據結構的邊界。[1][2]棧緩衝區溢出是緩衝區溢出的一種。[1] 這會損壞相鄰數據的值,引發程序崩潰或者修改了函數返回地址從而導致執行惡意的程序。這種攻擊方式稱為stack smashing。可被用於注入可執行代碼、接管進程的執行。是最為古老的黑客攻擊行為之一。[3][4][5]

例子 編輯

下例可用於覆蓋函數返回地址。[3][6] 通過函數 strcpy() :

#include <string.h>

void foo (char *bar)
{
   char  c[12];

   strcpy(c, bar);  // no bounds checking
}

int main (int argc, char **argv)
{
   foo(argv[1]);

   return 0;
}

當命令行參數少於12個字符時(例子B時)該程序是安全的。

foo()函數的不同輸入下的調用棧:

 
A. - Before data is copied.
 
B. - "hello" is the first command line argument.
 
C. - "A​A​A​A​A​A​A​A​A​A​A​A​A​A​A​A​A​A​A​A​\x08​\x35​\xC0​\x80" is the first command line argument.

例子C中, 命令行參數多於11個字符,導致foo()覆蓋了本地調用棧的數據、存儲的棧指針(EBP)以及最重要的返回地址。

攻擊也可以修改內部變量值:

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

void foo (char *bar)
{
   float My_Float = 10.5; // Addr = 0x0023FF4C
   char  c[28];           // Addr = 0x0023FF30

   // Will print 10.500000
   printf("My Float value = %f\n", My_Float);

    /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       Memory map:
       @ : c allocated memory
       # : My_Float allocated memory

           *c                      *My_Float
       0x0023FF30                  0x0023FF4C
           |                           |
           @@@@@@@@@@@@@@@@@@@@@@@@@@@@#####
      foo("my string is too long !!!!! XXXXX");

   memcpy will put 0x1010C042 (little endian) in My_Float value.
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

   memcpy(c, bar, strlen(bar));  // no bounds checking...

   // Will print 96.031372
   printf("My Float value = %f\n", My_Float);
}

int main (int argc, char **argv)
{
   foo("my string is too long !!!!! \x10\x10\xc0\x42");
   return 0;
}

平台相關 編輯

保護方式 編輯

常用三種方式來對抗棧緩衝區溢出攻擊。

檢查棧緩衝區溢出的發生 編輯

棧的警惕標誌(stack canary),得名於煤礦里的金絲雀英語Animal sentinel#Historical examples,用於探測該災難的發生。具體辦法是在棧的返回地址的存儲位置之前放置一個整形值,該值在裝入程序時隨機確定。棧緩衝區攻擊時從低地址向高地址覆蓋棧空間,因此會在覆蓋返回地址之前就覆蓋了警惕標誌。返回返回前會檢查該警惕標誌是否被篡改。[2]

棧數據不可執行 編輯

採取了「寫異或執行」策略(W^X英語W^X, "Write XOR Execute"),即內存要麼可寫,要麼可執行,但二者不能兼得。這是最常用的方法,大部分桌面處理器都硬件支持不可執行標誌(no-execute flag)。

隨機化內存空間佈局 編輯

著名例子 編輯

參見 編輯

參考文獻 編輯

  1. ^ 1.0 1.1 Fithen, William L.; Seacord, Robert. VT-MB. Violation of Memory Bounds. US CERT. 2007-03-27 [2017-02-19]. (原始內容存檔於2012-02-05). 
  2. ^ 2.0 2.1 Dowd, Mark; McDonald, John; Schuh, Justin. The Art Of Software Security Assessment. Addison Wesley. November 2006: 169–196. ISBN 0-321-44442-6. 
  3. ^ 3.0 3.1 Levy, Elias. Smashing The Stack for Fun and Profit. Phrack. 1996-11-08, 7 (49): 14 [2017-02-19]. (原始內容存檔於2021-03-04). 
  4. ^ Pincus, J.; Baker, B. Beyond Stack Smashing: Recent Advances in Exploiting Buffer Overruns (PDF). IEEE Security and Privacy Magazine. July–August 2004, 2 (4): 20–27 [2017-02-19]. doi:10.1109/MSP.2004.36. (原始內容存檔 (PDF)於2016-03-04). 
  5. ^ Burebista. Stack Overflows (PDF). [2017-02-19]. (原始內容 (PDF)存檔於2007-09-28).  (dead link)
  6. ^ Bertrand, Louis. OpenBSD: Fix the Bugs, Secure the System. MUSESS '02: McMaster University Software Engineering Symposium. 2002 [2017-02-19]. (原始內容存檔於2007-09-30).