Fork爆弾『 :(){ :|:& };:』とは?
Linuxに限らず、UNIX系のオペレーティングシステムで実行してはならないとされるコマンドや処理に「Fork爆弾」がある。これはひたすらプロセスをfork(2)する処理を行うことで、処理のほとんどをプロセスの生成やコンテキストスイッチに費やさせたり、新しいプロセスの生成を困難にさせたりして、システムを正常に利用できない状況にすることを指す。サービス妨害攻撃(Denial-of-service attack)の一種とも言える。
Fork爆弾は実行が簡単なことでも知られており、Bashであれば「:(){ :|:& };:」と入力するだけで実行できる。今回はこのコマンドを実行してみる。
Ubuntu Serverで『:(){ :|:& };:』を実行
では、早速Ubuntu Server 18.04 LTSで『:(){ :|:& };:』を実行してみよう。
Fork爆弾を実行してしばらく待っていると、コンソールに以下のスクリーンショットのようなエラーメッセージが表示されるようになる。これは、fork(2)を繰り返したことでもうfork(2)できないという意味だ。
システム負荷の高い状態になり、topコマンドですらほとんど反応しない状態になる。この状態ではほとんど使い物にならない。
しかし、この負荷が高い状況はそれほど長くは続かない。数分すると高負荷の状態は解除され、Fork爆弾で起動していたプロセスはきれいに終了していた。
これだけではいうほど、脅威という状態にはならない。
『f(){ f|f& };while :;do f;done』を実行
Fork爆弾があまり脅威とはならなかったので、もう少し攻撃が継続するように実行するコマンドを変えてみたい。
実行すると、コンソールに同じエラーが頻出されるようになり、システム負荷が高い状態になった。
しかし、先ほどよりは長い間高負荷の状態が続くものの、やはりそう長くない時間で問題のあるプロセスはすべて終了し、システムは正常な状態に戻った。
cronからFork爆弾を1分ごとに実行
すぐに収束してしまうのであれば、定期的に起動してやればよい。そこで、cronに仕込んで1分ごとに複数のFork爆弾が炸裂するようにしてみた。
この状態でシステムを運用すると、常に負荷が高い状態が続くようになる。しかし、インタラクティブにFork爆弾を実行した場合と比べると、それほど高い負荷にはならない。
たしかに、操作しているとなんかもっさりとした感じを受けるし、プロセス情報を表示させようとするとすごく遅い。しかし、平常時とまったく同じような反応を見せる操作もあり、場合によっては気がつかないかもしれない。
実のところ、最近のLinuxカーネルのみならず、最近のUNIX系オペレーティングシステムのスケジューラはよく出来ている。インタラクティブな操作には高い優先度が割り当てられ、不正なプロセスはそのうち終了する。
Fork爆弾にはもうひと工夫が必要
単純にインタラクティブシェルからFork爆弾を実行するだけでは、数分もすると元の状態に戻ってしまう。Fork爆弾を実行して常に高負荷状態を生み出したいのであれば、事あるごとにFork爆弾が起動するようにバイナリを書き換えておくとか、cronから定期的にFork爆弾を実行するとか、さらに工夫が必要だ。これまで通り、Fork爆弾は攻撃手段として機能するものの、単発ではそれほど脅威ではないのかもしれない。