Jaromil 在 2002 年設計了最為精簡的一個Linux Fork炸彈,整個程式碼只有13個字元,在 shell 中執行後幾秒後系統就會當機:
1 |
:(){:|:&};: |
這樣看起來不是很好理解,我們可以更改下格式:
1 2 3 4 5 |
:() { :|:& }; : |
更好理解一點的話就是這樣:
1 2 3 4 5 |
bomb() { bomb|bomb& }; bomb |
因為shell中函式可以省略function
關鍵字,所以上面的十三個字元是功能是定義一個函式與呼叫這個函式,函式的名稱為:
,主要的核心程式碼是:|:&
,可以看出這是一個函式本身的遞迴呼叫,通過&
實現在後臺開啟新程式執行,通過管道實現程式呈幾何形式增長,最後再通過:
來呼叫函式引爆炸彈。因此,幾秒鐘系統就會因為處理不過來太多的程式而當機,解決的唯一辦法就是重啟。
Bomb一下
秉著不作不死的心態,我們也來執行一下,於是我將矛頭指向雲主機,,我使用了國內的一個2G記憶體的雲主機,首先在本地開啟兩個終端,在一個終端連線雲主機後執行炸彈,秒後再嘗試用另外一個終端登入,效果可以看下面Gif圖:
看,執行一段時間後直接報出了-bash: fork: Cannot allocate memory
,說明記憶體不足了。並且我在二號終端上嘗試連線也沒有任何反應。因為是虛擬的雲主機,所以我只能通過主機服務商的後臺來給主機斷電重啟。然後才能重新登入:
炸彈危害
Fork炸彈帶來的後果就是耗盡伺服器資源,使伺服器不能正常的對外提供服務,也就是常說的DoS(Denial of Service)。與傳統1v1、通過不斷向伺服器傳送請求造成伺服器崩潰不同,Fork炸彈有種坐山觀虎鬥,不費一兵一卒斬敵人於馬下的感覺。更嚇人的是這個函式是不需要root許可權就可以執行的。看到網上有帖子說某些人將個性簽名改為Fork炸彈,結果果真有好奇之人中槍,試想如果中槍的人是在公司伺服器上執行的話,oh,!
預防方式
當然,Fork炸彈沒有那麼可怕,用其它語言也可以分分鐘寫出來一個,例如,python版:
1 2 3 |
import os while True: os.fork() |
Fork炸彈的本質無非就是靠建立程式來搶佔系統資源,在Linux中,我們可以通過ulimit
命令來限制使用者的某些行為,執行ulimit -a
可以檢視我們能做哪些限制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
ubuntu@10-10-57-151:~$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 7782 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 7782 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited |
可以看到,-u
引數可以限制使用者建立程式數,因此,我們可以使用ulimit -u 20
來允許使用者最多建立20個程式。這樣就可以預防bomb炸彈。但這樣是不徹底的,關閉終端後這個命令就失效了。我們可以通過修改/etc/security/limits.conf
檔案來進行更深層次的預防,在檔案裡新增如下一行(ubuntu需更換為你的使用者名稱):
1 |
ubuntu - nproc 20 |
這樣,退出後重新登入,就會發現最大程式數已經更改為20了,
這個時候我們再次執行炸彈就不會報記憶體不足了,而是提示-bash: fork: retry: No child processes
,說明Linux限制了炸彈建立程式。
參考
http://en.wikipedia.org/wiki/Fork_bomb