Хорошие списки с объяснениями: [Links/Hardening] Лично я бы всё свёл к: * SSP: защита стэка канареечным значением, SafeStack, RETGUARD. Это требует только помощи компилятора. OpenBSD имеет патчи для GCC для SSP, но не остальных технологий. LLVM/Clang поддерживает всё * Рандомизация адресного пространства (ASR, ALSR, RELRO, BIND_NOW, PIE, SEGVGUARD, размещение рандомное mmap-ed адресов, рандомизация символов и библиотек). Это требует и поддержки со стороны ОС/ядра, и некоторые вещи со стороны компилятора/линковщика (PIE). Поддерживается в OpenBSD, PaX патчах Linux, HardenedBSD (небольшой набор патчей для FreeBSD) * NX, W^X: запрет существования исполняемых и записываемых страниц памяти. Может требовать изменения ПО (добавляя mprotect() вызовы) для W^X. Но для автоматической защиты стэка достаточно только поддержки со стороны ядра (что делается по сути всеми) Другой защитой от *последствий* атак является privilege separation (privsep) и privilege drop (privdrop) технологии: * для setuid/setgid исполняемых файлов сразу же сбрасывать привилегии после запуска (set*id, setgroups) * закрывать за собой все ненужные файлы * делать chroot * порождать процессы которые занимаются только своей одной какой-то частью: один только с сетью работает, другой с диском, третий с бизнес логикой, и т.д.. Общаются между собой по Unix-сокетам. Подход вовсю применяемый в OpenBSD и Postfix privsep/privdrop из коробки имеет слишком большую гранулярность, отвечает по сути только за операции с файлами. Можно использовать capability-based security, где сама программа говорит как её надо ограничить и что она вообще обещает и собирается использовать: * pledge в OpenBSD позволяет чётко говорить что программа, после этого вызова, может делать: общаться только по stdio, читать файлы, делать на них stat, создавать временные файлы, chown/flock, dns, getpw, работать с сокетами, звуком, выставлять время, fork/exec, и т.д.. Гранулярность хоть и довольно большая этих capabilities, но простота использования pledge легко позволит проект переводить на его использование (за пару недель сотни программ в OpenBSD переведены на использование pledge) * unveil в OpenBSD похож на AppArmor и они позволяют per-filesystem-path задавать права доступа. По сути pledge это про группы системных вызовов, а unveil это как pledge для файлов на ФС * FreeBSD имеет Capsicum. Она позволяет одним вызовом ограничить возможности по работе с глобальными объектами (файлы, PID-ы и прочее), оставляя возможность работы с локальными файловыми дескрипторами и shared memory. Файловые дескрипторы относятся не только к файлам файловой системы, но и сокетам, kqueue, открытым директориям, процессам (pdfork), pipe. Capsicum может задавать несколько десятков прав которые можно сделать с каждым из FD. Это намекает, в том числе, на использование privsep. В качестве примера имеется Casper библиотека с возможностью порождения процессов делающих DNS запросы, получающих рандом или getpw, к которым через Unix-сокет можно сделать RPC вызов. Для сериализации можно использовать libnv библиотеку (сериализация типизированных словарей) входящую в состав Capsicum. Не так просто как pledge, нет аналогичного инструмента типа unveil, но зато хорошая гранулярность. Но софт нужно писать with "privsep in mind" * Linux имеет seccomp. Гораздо более сложную штуку чем всё описанное. Как и Capsicum она может одним вызовом оставить возможность только делать read/write/_exit/sigreturn вызовы (strict mode). А может использовать BPF-фильтр системных вызовов программы. Если в OpenBSD всё активно на pledge/unveil переведено, в FreeBSD десятки программ с каждым релизом переводятся на Capsicum, то seccomp массово не используется из-за сложности с его BPF. Эти технологии приятны тем, что они вшиты в само ПО, не требуя ничего более от пользователя/администратора. Имеют ничтожный overhead, о котором можно не думать. Дружелюбны и намекают на использование privsep/privdrop подхода. Для ограничения ПО уже извне, а не полагаясь на то что программа будет себя вести хорошо и корректно применять capability-based security, используются: * sandboxing технологии: jails (тут возможно и создание полностью отдельного своего сетевого стэка), cgroups, seccomp, chroot * ACL для файлов: AppArmor, POSIX.1e (POSIX ACL) поддержка из коробки в большинстве GNU/Linux дистрибутивов и в FreeBSD, NFSv4 ACL (то, что заменило POSIX.1e) поддержка имеется только в ZFS, AIX, FreeBSD * MAC (mandatory access control) технологии: SELinux, MAC подсистема FreeBSD (изначально появившаяся в TrustedBSD, реализующая POSIX.1e labels, Biba модель и другие) * OpenBSD вообще ничего из вышеуказанного не имеет, кроме банального chroot Так как некоторые операции требуют получения энтропии для эфемерных ключей и векторов инициализации, то нужны права для /dev/urandom, что либо делать через отдельный privsep-процесс, либо использовать не POSIX функции типа getentropy (появилась в OpenBSD, позже в GNU/Linux и FreeBSD), или arc4random. Современные реализации arc4random используют ChaCha20, зерно которого взято честно из источника энтропии ОС, поэтому это абсолютно безопасная замена /dev/urandom, не требующая работы с файловой системой и файлами, никогда не падая. Сделать в seccomp всё что делается в Capsicum -- можно, относительно легко. Но в общем случае без рассмотрения исходного кода каждой конкретной зависимости -- нельзя заранее понять и знать какие вызовы будут использованы (делает ли PCSC библиотека poll, select или epoll?). Кроме того, заранее неизвестно какие вызовы действительно будут применяться даже libc -- например glibc при вызове waitpid() делает wait4() на самом деле, а exit() вызывает exit_group(). То есть, seccomp код, как минимум, даже с использованием libseccomp будет libc-specific (даже от версии libc). И не исключено что в зависимости от платформы libc может на деле использовать другие системные вызовы. seccomp в итоге имеет самую маленькую гранулярность, возможность регулировать каждый чих программы. Но он платформо/libc-специфичен и с ним я потратил не один день на то, чтобы у меня в отдельном процессе заработал PCSC код, общающийся с главным процессом. seccomp -- трудоёмко использовать, как мне показалось. pledge имеет очень большую гранулярность, но крайне низкий порог вхождения -- всё прямо противоположного. Capsicum -- нечто среднее и заточенное на использование файловых дескрипторов (которые в FreeBSD отвечают не только за файловую систему, но и сокеты, mmap, процессы). Не могу не отметить качество документации GNU/Linux: отвратительное. Даже примеры из man-ов не работают и не могут даже в принципе: указываются функции которых нет в заголовочных файлах. Поведение (которое подглядываю в исходном коде glibc) не всегда соответствует тому что написано в документации. Приходится регулярно смотреть в glibc/Linux код. В BSD системах для работы с тем же kqueue или nvlist мне достаточно было ровно одного man вызова, где содержится всё что нужно.