Jaromil在2002年設(shè)計了最為精簡的一個Linux Fork炸彈,整個代碼只有13個字符迅栅,在shell中運行后幾秒后系統(tǒng)就會宕機:
:() { :|:& };:
這樣看起來不是很好理解彼绷,我們可以更改下格式:
:()
{
:|:&
};
:
更好理解一點的話就是這樣:
bomb()
{
bomb|bomb&
};
bomb
因為shell中函數(shù)可以省略function
關(guān)鍵字,所以上面的十三個字符是功能是定義一個函數(shù)與調(diào)用這個函數(shù)姐浮,函數(shù)的名稱為:
,主要的核心代碼是:|:&
窖壕,可以看出這是一個函數(shù)本身的遞歸調(diào)用钠糊,通過&
實現(xiàn)在后臺開啟新進(jìn)程運行锡凝,通過管道實現(xiàn)進(jìn)程呈幾何形式增長,最后再通過:
來調(diào)用函數(shù)引爆炸彈.因此垢啼,幾秒鐘系統(tǒng)就會因為處理不過來太多的進(jìn)程而死機窜锯,解決的唯一辦法就是重啟。
Bomb一下
秉著不作不死的心態(tài)芭析,我們也來運行一下锚扎,于是我將矛頭指向云主機,我使用了國內(nèi)的一個2G內(nèi)存的云主機馁启,首先在本地開啟兩個終端驾孔,在一個終端連接云主機后運行炸彈芍秆,幾秒后再嘗試用另外一個終端登錄,效果可以看下面Gif圖:
看翠勉,運行一段時間后直接報出了-bash: fork: Cannot allocate memory
妖啥,說明內(nèi)存不足了。并且我在二號終端上嘗試連接也沒有任何反應(yīng)对碌。因為是虛擬的云主機荆虱,所以我只能通過主機服務(wù)商的后臺來給主機斷電重啟。然后才能重新登錄:
炸彈危害
Fork炸彈帶來的后果就是耗盡服務(wù)器資源朽们,使服務(wù)器不能正常的對外提供服務(wù)怀读,也就是常說的DoS(Denial of Service)。與傳統(tǒng)1v1骑脱、通過不斷向服務(wù)器發(fā)送請求造成服務(wù)器崩潰不同菜枷,F(xiàn)ork炸彈有種坐山觀虎斗,不費一兵一卒斬敵人于馬下的感覺叁丧。更嚇人的是這個函數(shù)是不需要root權(quán)限就可以運行的啤誊。看到網(wǎng)上有帖子說某些人將個性簽名改為Fork炸彈歹袁,結(jié)果果真有好奇之人中槍坷衍,試想如果中槍的人是在公司服務(wù)器上運行的話,oh条舔,枫耳!
預(yù)防方式
當(dāng)然,F(xiàn)ork炸彈沒有那么可怕孟抗,用其它語言也可以分分鐘寫出來一個迁杨,例如,python版:
import os
while True:
os.fork()
Fork炸彈的本質(zhì)無非就是靠創(chuàng)建進(jìn)程來搶占系統(tǒng)資源凄硼,在Linux中铅协,我們可以通過ulimit
命令來限制用戶的某些行為,運行ulimit -a
可以查看我們能做哪些限制:
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
參數(shù)可以限制用戶創(chuàng)建進(jìn)程數(shù)狐史,因此,我們可以使用ulimit -u 20
來允許用戶最多創(chuàng)建20個進(jìn)程说墨。這樣就可以預(yù)防bomb炸彈骏全。但這樣是不徹底的,關(guān)閉終端后這個命令就失效了尼斧。我們可以通過修改/etc/security/limits.conf
文件來進(jìn)行更深層次的預(yù)防姜贡,在文件里添加如下一行(ubuntu需更換為你的用戶名):
ubuntu - nproc 20
這樣,退出后重新登錄棺棵,就會發(fā)現(xiàn)最大進(jìn)程數(shù)已經(jīng)更改為20了楼咳,
這個時候我們再次運行炸彈就不會報內(nèi)存不足了熄捍,而是提示-bash: fork: retry: No child processes
,說明Linux限制了炸彈創(chuàng)建線程母怜。
參考
http://en.wikipedia.org/wiki/Fork_bomb