64

Ковыряем атаку forkbomb на bash в docker

Есть такой вид атаки на отказ в обслуживании (DoS, Denial of Service) — forkbomb. Запускается процесс, который бесконечно порождает сам себя, пожирая все ресурсы системы. Прав суперпользователя не требуется, любой пользователь может создавать процессы.


Cкрипт атаки выглядит так. Функция порождает две версии себя, связанные конвейером. Правая функция уходит в фоновый режим с помощью знака амперсанд &.

forkbomb()
{
forkbomb | forkbomb&
}

Скрипт можно переписать в непонятный однострочник, изменив название на символ двоеточия:

:(){ :|:& }; :

Такой набор символов эквивалентен скрипту выше. При этом он компактен, и его могут запихнуть вам в качестве шуточного ответа на вопрос. Спасибо ещё, что не патч Бармина.


В видео также рассматриваются линуксовые команды команды

1. lscpu

2. nproc

3. uptime

4. top

5. free

6. переменные $$ $PPID

7. настройка числа PID в /proc/sys/kernel/pid_max

8. ctrl-L для очистки терминала

9. разделение экрана в терминале terminator

10. буфер выделения и вставка по нажатию на колёсико мышки

11. pkill


И разбираются флаги такой docker команды

docker run --it --rm --cpus="0.5" --memory=4G --pids-limit=1000 --name=forkbomb ubuntu bash

Плюс применяются команды docker ps / stats / exec.


Хотите почувствовать себя капитаном тонущего корабля? Теперь ресурсы системы принадлежат не вам, а паразитному процессу forkbomb. Приятного просмотра!

Починить атакованную систему можно только перезагрузкой. Ну, если атакующий скрипт вам не дописали в .bashrc. Тогда только recovery mode в grub.


В телеграм-канале разбираем разные нюансы из жизни разработчика на Python и не только — python, bash, linux, тесты, командную разработку.

GNU/Linux

1.2K пост15.6K подписчика

Правила сообщества

Все дистрибутивы хороши.

Будьте людьми.

0
Автор поста оценил этот комментарий

а каким пользуешься?

раскрыть ветку (1)
2
Автор поста оценил этот комментарий

а ты каким? мне нравится terminator

0
Автор поста оценил этот комментарий
у меня терминал так на части не делится
раскрыть ветку (1)
2
Автор поста оценил этот комментарий

Это сторонний терминал, называется terminator. В ubuntu поставить так

sudo apt install terminator


У него деление экрана (сколько угодно раз, правой кнопкой мыши - разделить горизонтально или вертикально или горячие клавиши ctrl+shift-O, ctrl-shif-E и ctrl-shift-X для увеличения окна на весь экран), возможность настроить бесконечный скролл, приятную цветовую схему и подобные мелочи

показать ответы
Автор поста оценил этот комментарий

А есть ли подобные атаки на питоне?

раскрыть ветку (1)
2
Автор поста оценил этот комментарий

Конечно. На python будет выглядеть так

import os
while True:
    os.fork()

0
Автор поста оценил этот комментарий

слушай, а ты не знаешь как сделать запуск терминатора уже с, скажем, 5-ю вкладками?

раскрыть ветку (1)
1
Автор поста оценил этот комментарий

если я правильно понял вопрос, то тут гайд по настройке https://superuser.com/a/610048

показать ответы
1
Автор поста оценил этот комментарий

Упс, renice не в ту сторону сделал... Я наоборот имел в виду приоритезацию своего шелла до -20. Но и так сработало.


Почему у меня смог вызваться дочерний процесс killall я не знаю, но думаю я его просто слишком рано вызвал. За 5 секунд форк-бомба ещё могла не забить таблицу процессов. В других сценариях я вызывал 2й терминал и killall из него вручную и гораздо позже, а не через серию команд через ";" в том же терминале. И тогда да, они не с первого раза вызывались. Но с какой-то попытки вызывались. Эмулятор терминала смог запуститься когда я непрерывно жал хоткей для его вызова. Killall смог вызваться с какой-то попытки когда я его стал вызывать внутри вечного цикла. Также у меня zsh (не bash), это может влиять, например в zsh, kill - это shell builtin, а в bash это внешний бинарник, и если я просто вызову kill (не killall) в zsh в сценарии с форк-бомбой, то это не потребует дочернего процесса

раскрыть ветку (1)
0
Автор поста оценил этот комментарий
И тогда да, они не с первого раза вызывались
Уф, тогда моя картина мира на месте - как я и сказал, killall будет недетерминирован. А дальше прикол в том, что ты делаешь killall forkbomb. Но мы же говорим про атаку, значит, мы запустили неизвестный скрипт. Или даже случайно вставили в терминал плохую команду. Совершенно непонятно, чему именно делать kill


Спасибо за приятный диалог, приходи в мои посты ещё)

2
Автор поста оценил этот комментарий

Так даже ls не работает, какой killall

Я сейчас попробовал форк-бомбу в виртуалке qemu, полную потерю возможности запускать процессы не увидел. Killall отработал


Мммм. Включаешь комп, он логинится и сразу начинает выполнять forkbomb. В какой момент --norc запускать?

Я говорил про ситуацию, когда в работающей системе запущен forkbomb. Запустить bash --norc можно из уже запущенного шелла или из окна запуска команд или создав соотв. ярлык. В системе обычно есть пара уже работающих приложений, позволяющих запуск произвольных дочерних процессов. У меня это emacs


Если речь идёт про загрузку, то запуск интерактивного баша не является частью типовой процедуры загрузки. Стартует init, затем X, затем оконный менеджер. Интерактивного шелла в этом списке нет.


Но вроде пока это всё ещё дефолтное поведение, или я отстал от жизни?

Дефолтное поведение чего?

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Можно видео с qemu? Может, что-то настроено хитрее. Я на базе docker показал, что в терминале с forkbomb куча сообщений сыплются и ничего не видно. А если в соседней консоли, то даже печатать тяжело. По ссылке есть видосы на ubuntu и windos, где запускается на виртуалке или хосте без докера. Система тоже мгновенно повисает


Если в системе уже запущен forkbomb, то bash --norc, скорее всего, просто не запустится. Блин, ls не работает даже, что в видео показано со всем сторон. Дочерние процессы не запустить толком, только по случайности


Дефолтное поведение - это скрин grub, который я привёл выше. Если ubuntu поставить на ноут и всё сделать по умолчанию, то до запуска ОС будет вот такое окно выбора

показать ответы
2
Автор поста оценил этот комментарий

Починить атакованную систему можно только перезагрузкой.

Да ладно. Killall bash/zsh или изменить ulimit временно.


Ну, если атакующий скрипт вам не дописали в .bashrc. Тогда только recovery mode в grub.

Ужастики продолжаются. bash --norc. И почему "в grub"? Есть другие загрузчики, не говоря уже о том, что под UEFI систему можно стартовать прямо из UEFI shell, без загрузчика

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Так даже ls не работает, какой killall) С ограничением на CPU можно что-то сделать, а без ограничения никакую команду не выполнить


Мммм. Включаешь комп, он логинится и сразу начинает выполнять forkbomb. В какой момент --norc запускать?


С grub, конечно, не обязательно. Но вроде пока это всё ещё дефолтное поведение, или я отстал от жизни?

Иллюстрация к комментарию
показать ответы
2
Автор поста оценил этот комментарий

Дефолтное поведение - это скрин grub, который я привёл выше. Если ubuntu поставить на ноут и всё сделать по умолчанию, то до запуска ОС будет вот такое окно выбора

Не у всех стоит ubuntu, не на всякой ubuntu загрузчиком является grub. Никто и никогда не назначал ubuntu дефолтным линуксом


Можно видео с qemu?

Можно, вот даже на реальном железе запустил, после того как убедился, что в виртуалке всё нормально:

https://gifyu.com/image/Swit4


Команда для запуска сценария (видна в первых секундах гифки):


/dev/shm/forkbomb.sh; sleep 5; renice +19 $$; killall -STOP forkbomb.sh; killall -KILL forkbomb.sh

раскрыть ветку (1)
Автор поста оценил этот комментарий

Говорю про самый популярный вариант, так как зоопарк слишком большой. Понятно, что есть варианты. С современной докеризаций дистрибутив всё дальше уходит на второй план.


Гифка восторг :) А как renice тут влияет? Ты ставишь текущему терминалу низший приоритет, чтобы показать, что даже в этом случае killall сработает?


Спасибо за направление, я поковыряюсь ещё. Типа набрать команду killall, когда в терминал сыплется мусор не очень просто. Но положим. Интересно, почему у меня kill почти нереально выполнить было (в плане я пишу килл, получаю ошибку "не смог fork" и всё), а у тебя выполнилось нормально. Ощущение, что факт выполнения всего заранее как-то влияет. Хотя не должно

показать ответы