棧緩衝區溢位（stack buffer overflow 或 stack buffer overrun）是計算機程式把資料寫入呼叫棧上的記憶體時超出了資料結構的邊界。棧緩衝區溢位是緩衝區溢位的一種。 這會損壞相鄰資料的值，引發程式崩潰或者修改了函式返回地址從而導致執行惡意的程式。這種攻擊方式稱為 stack smashing。可被用於注入可執行程式碼、接管程序的執行。是最為古老的駭客攻擊行為之一。 dead link 例子 下例可用於覆蓋函式返回地址。 透過函式 strcpy include stringh 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 函式的不同輸入下的呼叫棧，下圖展示 32 位元小端序 littleendian 系統發生棧緩衝區溢位的記憶體狀態 例子 C 中，命令列引數多於 11 個字元，導致 foo 覆蓋了本地呼叫棧的資料、儲存的棧指標（EBP）以及最重要的返回地址。 攻擊也可以修改內部變數值： include stringh include stdioh void foo char bar float My_Float 105 Addr 0x0023FF4C char c 28 Addr 0x0023FF30 Will print 10500000 printf My Float value fn 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 96031372 printf My Float value fn My_Float int main int argc char argv foo my string is too long x10x10xc0x42 return 0 平臺相關 A number of platforms have subtle differences in their implementation of the call stack that can affect the way a stack buffer overflow exploit will work Some machine architectures store the top level return address of the call stack in a register This means that any overwritten return address will not be used until a later unwinding of the call stack Another example of a machine specific detail that can affect the choice of exploitation techniques is the fact that most RISC style machine architectures will not allow unaligned access to memory Combined with a fixed length for machine opcodes this machine limitation can make the jump to ESP technique almost impossible to implement with the one exception being when the program actually contains the unlikely code to explicitly jump to the stack register Stacks that grow up Within the topic of stack buffer overflows an often discussed but rarely seen architecture is one in which the stack grows in the opposite direction This change in architecture is frequently suggested as a solution to the stack buffer overflow problem because any overflow of a stack buffer that occurs within the same stack frame can not overwrite the return pointer Further investigation of this claimed protection finds it to be a naive solution at best Any overflow that occurs in a buffer from a previous stack frame will still overwrite a return pointer and allow for malicious exploitation of the bug For instance in the example above the return pointer for foo will not be overwritten because the overflow actually occurs within the stack frame for strcpy However because the buffer that overflows during the call to strcpy resides in a previous stack frame the return pointer for strcpy will have a numerically higher memory address than the buffer This means that instead of the return pointer for foo being overwritten the return pointer for strcpy will be overwritten At most this means that growing the stack in the opposite direction will change some details of how stack buffer overflows are exploitable but it will not reduce significantly the number of exploitable bugs 保護方式 常用三種方式來對抗棧緩衝區溢位攻擊。 檢查棧緩衝區溢位的發生 棧的警惕標誌（stack canary），得名於，用於探測該災難的發生。具體辦法是在棧的返回地址的儲存位置之前放置一個整形值，該值在裝入程式時隨機確定。棧緩衝區攻擊時從低地址向高地址覆蓋棧空間，因此會在覆蓋返回地址之前就覆蓋了警惕標誌。返回返回前會檢查該警惕標誌是否被篡改。 棧資料不可執行 採取了 寫異或執行 策略（ Write XOR Execute），即記憶體要麼可寫，要麼可執行，但二者不能兼得。這是最常用的方法，大部分桌面處理器都硬體支援不可執行標誌（noexecute flag）。 While this method definitely makes the canonical approach to stack buffer overflow exploitation fail it is not without its problems First it is common to find ways to store shellcode in unprotected memory regions like the heap and so very little need change in the way of exploitation Even if this were not so there are other ways The most damning is the socalled return to libc method for shellcode creation In this attack the malicious payload will load the stack not with shellcode but with a proper call stack so that execution is vectored to a chain of standard library calls usually with the effect of disabling memory execute protections and allowing shellcode to run as normal This works because the execution never actually vectors to the stack itself A variant of returntolibc is returnoriented programming which sets up a series of return addresses each of which executes a small sequence of cherrypicked machine instructions within the existing program code or system libraries sequence which ends with a return These socalled gadgets each accomplish some simple register manipulation or similar execution before returning and stringing them together achieves the attackers ends It is even possible to use returnless returnoriented programming by exploiting instructions or groups of instructions that behave much like a return instruction 隨機化記憶體空間佈局 Instead of separating the code from the data another mitigation technique is to introduce randomization to the memory space of the executing program Since the attacker needs to determine where executable code that can be used resides either an executable payload is provided with an executable stack or one is constructed using code reuse such as in ret2libc or ROP Return Oriented Programming randomizing the memory layout will as a concept prevent the attacker from knowing where any code is However implementations typically will not randomize everything usually the executable itself is loaded at a fixed address and hence even when ASLR Address Space Layout Randomization is combined with a nonexecutable stack the attacker can use this fixed region of memory Therefore all programs should be compiled with PIE positionindependent executables such that even this region of memory is randomized The entropy of the randomization is different from implementation to implementation and a low enough entropy can in itself be a problem in terms of brute forcing the memory space that is randomized 隨機化記憶體空間佈局 ASLR 會對處理程序的記憶體區段地址進行隨機化，阻止攻擊者進行返回導向程式設計與跳至 Shellcode 的攻擊手法，因為攻擊者需要知道可執行區段與 Shellcode 的記憶體地址。執行檔如果不是地址無關程式碼 PIE 的格式，會導致執行檔載入成處理程序之後，部分割槽段地址為固定的 如 text 區段，攻擊者在 Linux 系統上，依然可以 return 到 0x400000 地址。ASLR 受到資訊熵的影響，不同的實作會有不同的資訊熵，過低的資訊熵使攻擊者更容易猜測到地址，也因此 32 位元比起 64 位元的更容易受到威脅。也因此在 2015 年發生 Stagefright 漏洞，在 32 位元系統下，ASLR 僅有 8 位元的資訊熵，因此每次漏洞利用，只需要從 256 種組合猜測可能的記憶體地址進行利用。 著名例子 莫里斯蠕蟲針對 Unix 伺服器 針對 Microsoft SQL Server 衝擊波蠕蟲 針對微軟的 DCOM 服務 針對 Wii 參見 參考文獻 Category 程式錯誤 Category 軟體異常 Category 保全漏洞 Category 計算機錯誤