天天看點

Fork(分叉函數)炸彈

遞歸調用自身,分支出大量的程序,最終造成拒絕服務攻擊。

http://www.ha97.com/2618.html

?){ ?:& |};:

所謂fork炸彈是一種惡意程式,它的内部是一個不斷在fork程序的無限循環,fork炸彈并不需要有特别的權限即可對系統造成破壞。fork炸彈實質是一個簡單的遞歸程式。由于程式是遞歸的,如果沒有任何限制,這會導緻這個簡單的程式迅速耗盡系統裡面的所有資源。現在來看看Jaromil設計的最簡單的fork炸彈:

:() { :|:& };:
           

或者

.() { .|.& };.
           

一行看似無法了解的隻有13個字元的指令,即可占用掉所有系統的資源。其實,這行指令如果這樣寫成bash script就不難了解了:

:()
{
:|: &
}
;
:
           
  • 第 1 行說明下面要定義一個函數,函數名為小數點,沒有可選參數。
  • 第 2 行表示函數體開始。
  • 第 3 行是函數體真正要做的事情,首先它遞歸調用本函數,然後利用管道調用一個新程序(它要做的事情也是遞歸調用本函數),并将其放到背景執行。
  • 第 4 行表示函數體結束。
  • 第 5 行并不會執行什麼操作,在指令行中用來分隔兩個指令用。從總體來看,它表明這段程式包含兩個部分,首先定義了一個函數,然後調用這個函數。
  • 第 6 行表示調用本函數。

冒号”:”其實是函數名,這個bash腳本就是在不斷的執行該函數,然後不斷fork出新的程序。

對于函數名,大家可能會有所疑惑,小數點也能做函數名使用嗎?畢竟小數點是 shell 的一個内嵌指令,用來在目前 shell 環境中讀取指定 檔案,并運作其中的指令。實際上的确可以,這取決于bash對指令的解釋順序。

預設情況下,bash處于非POSIX模式,此時對指令的解釋順序如下:

  • 關鍵字,例如 if、for 等。
  • 别名。别名不能與關鍵字相同,但是可以為關鍵字定義别名,例如 end=fi。
  • 特 殊内嵌指令,例如 break、continue 等。POSIX 定義的特殊内嵌指令包括:.(小數點)、:(冒号)、break、continue、 eval、exec、exit、export、readonly、 return、set、shift、times、trap 和 unset。 bash 又增加了一個特殊的内嵌指令 source。
  • 函數。如果處于非 POSIX 模式,bash 會優先比對函數,然後再比對内嵌指令。
  • 非特殊内嵌指令,例如 cd、test 等。
  • 腳本和可執行程式。在 PATH 環境變量指定的目錄中進行搜尋,傳回第一個比對項。

    由 于預設情況下,bash 處于非 POSIX 模式,是以fork炸彈中的小數點會優先當成一個函數進行比對。(注:使用小數點代替其中的冒号,也能起到完全相同的效果。)

要使用POSIX模式來運作bash腳本,可以使用以下三種方法:

  • 使用 –posix 選項啟動 bash。
  • 在運作bash之後,執行 set -o posix 指令。
  • 使用 /bin/sh 。

那麼,有沒有辦法扼制這種情況的發生呢?答案是肯定的,隻需設定程序的limit數即可。

[[email protected] ~]# ulimit -u 128
[[email protected] ~]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
max nice                        (-e) 20
file size               (blocks, -f) unlimited
pending signals                 (-i) unlimited
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) unlimited
max rt priority                 (-r) unlimited
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 128
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
[[email protected] ~]# .() { .|.& } ; .
[1] 6152
[[email protected] ~]# bash: fork: Resource temporarily unavailable
bash: fork: Resource temporarily unavailable
bash: fork: Resource temporarily unavailable
…
           

在上面的例子中,我們将使用者可以建立的最大程序數限制為 128,執行fork炸彈會迅速fork出大量程序,此後會由于資源不足而無法繼續執行。使用工具ulimit即可設定各種限制數,具體的請參考該工具的man或help。

fork 炸彈讓我們認識到了遞歸函數的強大功能,同時也意識到一旦使用不當,遞歸函數所造成的破壞将是巨大的。實際上,fork 炸彈隻是一個非常簡單的遞歸函數,它并不涉及參數傳遞、傳回值等問題,而這些問題在使用bash程式設計時是否有完善的支援呢?在bash中編寫遞歸函數時應該注意相關問題。

繼續閱讀