Вы­бор сис­темы ини­циали­зации в Linux — важ­ней­шая задача: от это­го зависит надеж­ность и безопас­ность. Systemd руга­ют за слож­ность и потен­циаль­ные уяз­вимос­ти, SysVinit счи­тает­ся уста­рев­шим, а OpenRC и runit — непонят­ная экзо­тика. В этой статье я раз­беру systemd, OpenRC и runit, их архи­тек­туру, вли­яние на безопас­ность и прак­тичес­кое при­мене­ние, что­бы помочь тебе выб­рать.

Сис­тема ини­циали­зации — это про­цесс с PID 1, который запус­кает все осталь­ное в Linux. Если она нас­тро­ена неп­равиль­но, это может открыть две­ри для атак или усложнить вос­ста­нов­ление пос­ле сбоя. Нап­ример, в 2018 году уяз­вимость CVE-2018-15686 в systemd поз­воляла зло­умыш­ленни­ку с локаль­ным дос­тупом получить root-пра­ва через ошиб­ку в обра­бот­ке сооб­щений D-Bus. Такие проб­лемы показы­вают, что выбор и нас­трой­ка init-сис­темы нап­рямую вли­яют на безопас­ность. Понима­ние того, как раз­ные сис­темы работа­ют и защища­ются, помога­ет миними­зиро­вать рис­ки и упростить аудит.

 

Systemd: возможности и риски

Systemd — эко­сис­тема, исполь­зуемая в Ubuntu, RHEL, Debian. Она управля­ет мно­жес­твом внут­ренних механиз­мов в этих сис­темах. Под­дер­жка cgroups v2, namespaces и resolved поз­воля­ет изо­лиро­вать про­цес­сы и ресур­сы, что дела­ет systemd популяр­ным инс­тру­мен­том для DevSecOps, но слож­ность это­го инс­тру­мен­та уве­личи­вает повер­хность ата­ки. Слож­ность всег­да соз­дает допол­нитель­ные рис­ки!

Да­вай раз­берем, что уме­ет systemd и как ее обе­зопа­сить.

Как писать systemd

Ав­тор systemd Лен­нарт Пёт­теринг:

Пра­виль­но писать systemd, а не System D или даже SystemD. И уж точ­но не system d. Почему? Потому что это сис­темный демон (system daemon), а в Unix/Linux их пишут в ниж­нем регис­тре и добав­ляют суф­фикс d (тоже строч­ный). А так как systemd управля­ет сис­темой (system), он и называ­ется systemd. Все прос­то. Единс­твен­ный слу­чай, ког­да мы допус­каем заг­лавную бук­ву в наз­вании (хотя и это нам не по душе), — если вы начина­ете пред­ложение со сло­ва systemd. В осо­бо тор­жес­твен­ные праз­дни­ки вам так­же поз­волитель­но писать sÿstëmd.

 

Безопасность

Systemd — это не прос­то механизм ини­циали­зации, а целая эко­сис­тема, которая управля­ет служ­бами, сетью, логиро­вани­ем и даже кон­тей­нерами. Она сто­ит по умол­чанию в Ubuntu, RHEL, Debian и дру­гих популяр­ных дис­три­бути­вах, но ее слож­ность вызыва­ет спо­ры. Давай раз­берем, что она уме­ет и как ее обе­зопа­сить.

Systemd работа­ет с юни­тами — кон­фигура­цион­ными фай­лами, которые зада­ют, как запус­кать служ­бы (.service), сокеты (.socket), тай­меры (.timer) или точ­ки мон­тирова­ния (.mount). Нап­ример, файл nginx.service опре­деля­ет, как под­нять веб‑сер­вер, его зависи­мос­ти и огра­ниче­ния. Сре­ди ком­понен­тов — systemd-journald для бинар­ного логиро­вания (аль­тер­натива rsyslog), systemd-networkd и resolved для управле­ния сетью и DNS, logind для кон­тро­ля поль­зователь­ских сес­сий и systemd-nspawn для лег­кой кон­тей­нериза­ции.

Для безопас­ности systemd пред­лага­ет механиз­мы огра­ниче­ния при­виле­гий, которые про­ще, чем нас­трой­ка seccomp или POSIX-капаби­лити.

  • NoNewPrivileges=yes бло­киру­ет повыше­ние при­виле­гий, даже при экс­плу­ата­ции уяз­вимос­тей.
  • PrivateTmp=yes изо­лиру­ет /tmp, что­бы служ­ба не читала чужие фай­лы.
  • ProtectSystem=full дела­ет катало­ги /usr, /boot и /etc дос­тупны­ми толь­ко для чте­ния.
  • ReadWritePaths раз­реша­ет запись толь­ко в ука­зан­ные дирек­тории, нап­ример /var/log/nginx.
  • CapabilityBoundingSet огра­ничи­вает capabilities — воз­можнос­ти про­цес­сов выпол­нять те или иные дей­ствия.
  • RestrictAddressFamilies раз­реша­ет толь­ко нуж­ные про­токо­лы, такие как AF_INET и AF_INET6.
  • MemoryDenyWriteExecute=yes защища­ет от инъ­екции кода в про­цес­сы.
  • PrivateDevices=yes огра­ничи­вает дос­туп к /dev.

Вот при­мер безопас­ной кон­фигура­ции для Nginx в /etc/systemd/system/secure-nginx.service:

[Unit]
Description=Secure NGINX Web Server
After=network.target
[Service]
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
User=nginx
Group=nginx
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=full
ReadWritePaths=/var/lib/nginx /var/log/nginx
RestrictAddressFamilies=AF_INET AF_INET6
MemoryDenyWriteExecute=yes
PrivateDevices=yes
ProtectHome=yes
SystemCallFilter=@system-service
SystemCallArchitectures=native
[Install]
WantedBy=multi-user.target

Эта кон­фигура­ция запус­кает nginx от име­ни неп­ривиле­гиро­ван­ного поль­зовате­ля, огра­ничи­вает его воз­можнос­ти, изо­лиру­ет /tmp, /home и сис­темные дирек­тории, раз­реша­ет толь­ко IPv4/IPv6 и бло­киру­ет выпол­нение кода из памяти. Коман­да systemd-analyze security secure-nginx.service покажет оцен­ку уяз­вимос­тей и пред­ложит улуч­шения.

Но у systemd есть и рис­ки. Уяз­вимос­ти, такие как CVE-2018-15686, показы­вают, что слож­ность сис­темы соз­дает потен­циаль­ные век­торы атак. Бинар­ные логи journald слож­нее ана­лизи­ровать без journalctl, что может зат­руднить аудит.

Продолжение доступно только участникам

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии