Belge

Systemd hizmetlerinin güvenliği nasıl artırılır

Günümüzde tüm büyük Linux dağıtımları Systemd’yi başlangıç ​​sistemi/hizmet yöneticisi olarak benimsemiştir.  Bir systemd hizmeti oluşturmak, uygun dizine bir “.service” birimi yazmak ve bunu systemctl yardımcı programını kullanarak yönetmek meselesidir.  Bir hizmeti başlatırken veya genel olarak bir süreci başlatırken, görevi gerçekleştirmek için ihtiyaç duyduğu mümkün olan en düşük ayrıcalıklarla çalıştığından emin olmak istiyoruz.  Systemd, bir hizmetin davranışına ince ayar yapmak, ayrıcalıkları ayrıntılı bir şekilde vermek veya reddetmek ve sistemin geri kalanından belirli bir düzeyde izolasyon sağlamak için kullanabileceğimiz bir dizi seçenek sunar.

 

Bu makalede, bir systemd hizmetinin güvenliğinin nasıl artırılacağını ve systemd-analyze yardımcı programını kullanarak maruz kalma düzeyine ilişkin bir tahminin nasıl alınacağını görüyoruz.

 

Bir test senaryosu: yedekleme hizmeti yazma

Bu makalenin amacına uygun olarak,  systemd-timer aracılığıyla bir yedeklemeyi planlamak için servis yazmak istediğimizi varsayalım.  “Birim” bölümünü yazarak başlıyoruz:

[Unit] 
Description=restic backup
Wants=network-online.target
After=network-online.target

İlk olarak Açıklama seçeneğini kullanarak bir hizmet açıklaması sağladık.  Yedeklemelerimiz için uzak depoları kullanabilmek istediğimizden, İstekler ve Sonra seçeneklerini kullanarak sırasıyla hizmetin network-online.target’e (zayıf) bağımlılığını ilan ettik ve hizmetin ancak söylenenden sonra başlatılması gerektiğini belirledik. hedefe ulaşıldı ve ağ arayüzleri yapılandırıldı.

Şimdi ünitenin “Servis” bölümünü dolduralım.  Hizmet davranışımızı burada tanımlıyoruz:

[Service]
Type=oneshot
User=restic
ExecStart=/usr/local/bin/restic_backup.sh

 



Hizmetimizi “oneshot” olarak tanımlamak için “Type” seçeneğini kullandık.  Bu, systemd’nin hizmete nasıl davrandığını etkiler: yalnızca ana süreç çıktıktan sonra onu “çalışıyor” olarak kabul eder. 

Güvenlik açığı nedeniyle, hizmeti root olarak çalıştırmaktan kaçınmak istiyoruz, bu nedenle “restic” ayrıcalıksız kullanıcıyı oluşturduk ve Kullanıcı seçeneğiyle işlemin ayrıcalıklarıyla başlatılması gerektiğini belirttik.  Son olarak ExecStart seçeneği ile servis başlatıldığında çağrılması gereken komutu/yürütülebilir dosyayı tanımladık;  bu durumda ana yedekleme mantığını içeren /usr/local/bin/restic_backup.sh betiğidir.

Ünitenin “Hizmet” bölümünde, hizmetimizin ayrıcalıklarını daha da ayarlamak için diğer birçok seçeneği kullanabiliriz.  Bunlardan bazılarını görelim.

Süreci yeteneklerle yürütmeHizmetimiz “restic” kullanıcısının ayrıcalıklarıyla çalışacaktır.  Bu iyi bir güvenlik önlemidir, ancak restic’in tüm dosya sistemini okuyabildiğinden emin olmalıyız.  Hedefimize ulaşmak için sürecin uygun yeteneklerle ilerlemesini sağlayabiliriz:

AmbientCapabilities=CAP_DAC_READ_SEARCH
CapabilityBoundingSet=CAP_DAC_READ_SEARCH

 



AmbientCapability seçeneği, değer olarak sürecin ortam yetenek kümesine dahil etmek istediğimiz yeteneklerin virgülle ayrılmış listesini alır.  Bu durumda, dosyaların ve dizinlerin okuma izni kontrollerini atlamaya izin veren “CAP_DAC_READ_SEARCH” özelliğini kullandık.  Bir güvenlik önlemi olarak, sürecin elde etmesine izin verilen yetenek kümesini sınırlamak için CapabilityBoundingSet seçeneğini de kullandık. 

Hizmeti Güvenli Hale Getirme

Yukarıda kullandığımız yeteneklerle ilgili iki seçenek, hizmeti “izole etmek” için kullanabileceğimiz seçeneklerin yalnızca küçük bir alt kümesidir.  Çoğu bir boole değeri kabul eder.  Hadi bazı örneklere bakalım.

PrivateTmp

“PrivateTmp” seçeneği, hizmet tarafından oluşturulan geçici dosyaları korur, böylece diğer işlemler bunlara erişemez.  Seçenek etkin olduğunda, systemd yalıtılmış /tmp ve /var/tmp dizinleri oluşturur ve bunları özel bir ad alanına bağlar.

ProtectKernelModules, ProtectKernelLogs and ProtectKernelTunables

Bu seçenekler çekirdek durumunu korur.  KorumaKernelModules etkin olduğunda hizmetin çekirdek modüllerini yükleme ve kaldırma yeteneğini reddeder, KorumaKernelLogs ise çekirdek günlük arabelleğine erişimi reddeder.  Belirli çekirdek modüllerinin davranışı, /proc ve /sys sözde dosya sistemlerinde gösterilen dosyalara uygun değerler yazılarak değiştirilebilir;  KorumaKernelTunables seçeneği etkin olduğunda bu tür eylemleri reddeder.

NoNewPrivileges

Bu seçenek, hizmetin ve alt işlemlerinin, standart C kitaplığının bir parçası olan execve sistem çağrısı aracılığıyla diğer programları çalıştırarak yeni ayrıcalıklar kazanamayacağından emin olmak için kullanılabilir.  Bu seçenek aktif olduğunda, SETUID veya SETGID bitleri ayarlıyken ikili dosyaların yürütülmesini reddeder.

RestrictSUIDSGID

Bu seçenek doğru olduğunda, hizmet tarafından başlatılan işlemin dosyalar ve dizinler üzerinde SETUID veya SETGID bitlerini ayarlamasını engeller.

RestrictAddressFamilies

Bu seçenek, sürecin erişebileceği adres ailesi adlarının boşlukla ayrılmış listesini kabul eder (örneğin: AF_UNIX, AF_INET, AF_INET6);  “Yok” da geçerli bir değerdir: hepsine erişimi reddeder.

PrivateDevices

Bu seçenek etkin olduğunda, /dev/sda veya /dev/mem gibi ham aygıtlara işlem erişimini reddeder.

ProtectClock

True olarak ayarlandığında sistem saatine erişimi reddeder.

ProtectHostname

Bu seçenek, sistemin ana bilgisayar adını koruyarak işlemin onu değiştirememesini sağlar.

RemoveIPC

Etkin olduğunda, hizmete tahsis edilen IPC (İşlemlerarası İletişim) kaynaklarının otomatik olarak kaldırılmasına neden olur.

PrivateMounts

Bu seçenek aktif olduğunda süreç, ana bilgisayardan erişilemeyen, kendi özel ve yalıtılmış dosya sisteminde çalışır.

Hizmetin tahmini güvenlik düzeyini elde etme

Sonunda hizmetimiz şu şekilde görünüyor:

[Unit] 
Description=restic backup
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
User=restic
ExecStart=/usr/local/bin/restic_backup.sh
AmbientCapabilities=CAP_DAC_READ_SEARCH
CapabilityBoundingSet=CAP_DAC_READ_SEARCH
PrivateTmp=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectKernelTunables=yes
NoNewPrivileges=yes
RestrictSUIDSGID=yes
RestrictAddressFamilies=yes
PrivateDevices=yes
ProtectClock=yes
ProtectHostname=yes
RemoveIPC=yes
PrivateMounts=yes

Üniteyi systemd tarafından tanınan dizinlerden birine yerleştirdikten sonra (örneğin, /etc/systemd/system), tahmini güvenlik seviyesini elde etmek için, “security” komutuyla “systemd-analyze”yi başlatmamız yeterlidir. argüman olarak birim adı.  Birimi “restic.service” olarak kaydettiğimizi varsayalım:

$ systemd-analyze security restic.service

 



Komut, ünitede mevcut olan ve olmayanları işaretleyerek mevcut güvenlik seçeneklerinin bir listesini ve genel maruz kalma düzeyini döndürür: bu ne kadar düşükse o kadar iyidir.  Kullanılmayan her seçenek, maruz kalma değerini “POZLAMA” sütununda bildirilen miktar kadar artırır.  Komutu servis birimimize karşı çalıştırdığımızda elde ettiğimiz çıktı şu şekildedir: 

  NAME                                                        DESCRIPTION                                                        EXPOSURE
 RemoveIPC=                                                  Service user cannot leave SysV IPC objects around                          
 RootDirectory=/RootImage=                                   Service runs within the host's root directory                           0.1
 User=/DynamicUser=                                          Service runs under a static non-root user identity                         
 CapabilityBoundingSet=~CAP_SYS_TIME                         Service processes cannot change the system clock                           
 NoNewPrivileges=                                            Service processes cannot acquire new privileges                            
 AmbientCapabilities=                                        Service process receives ambient capabilities                           0.1
 CapabilityBoundingSet=~CAP_(DAC_*|FOWNER|IPC_OWNER)         Service may override UNIX file/IPC permission checks                    0.2
 ProtectControlGroups=                                       Service may modify the control group file system                        0.2
 CapabilityBoundingSet=~CAP_BPF                              Service may load BPF programs                                              
 SystemCallArchitectures=                                    Service may execute system calls with all ABIs                          0.2
 MemoryDenyWriteExecute=                                     Service may create writable executable memory mappings                  0.1
 RestrictNamespaces=~user                                    Service may create user namespaces                                      0.3
 RestrictNamespaces=~pid                                     Service may create process namespaces                                   0.1
 RestrictNamespaces=~net                                     Service may create network namespaces                                   0.1
 RestrictNamespaces=~uts                                     Service may create hostname namespaces                                  0.1
 RestrictNamespaces=~mnt                                     Service may create file system namespaces                               0.1
 RestrictNamespaces=~cgroup                                  Service may create cgroup namespaces                                    0.1
 RestrictNamespaces=~ipc                                     Service may create IPC namespaces                                       0.1
 LockPersonality=                                            Service may change ABI personality                                      0.1
 RestrictRealtime=                                           Service may acquire realtime scheduling                                 0.1
 SupplementaryGroups=                                        Service has no supplementary groups                                        
 CapabilityBoundingSet=~CAP_SYS_RAWIO                        Service has no raw I/O access                                              
 CapabilityBoundingSet=~CAP_SYS_PTRACE                       Service has no ptrace() debugging abilities                                
 CapabilityBoundingSet=~CAP_SYS_(NICE|RESOURCE)              Service has no privileges to change resource use parameters                
 CapabilityBoundingSet=~CAP_NET_ADMIN                        Service has no network configuration privileges                            
 CapabilityBoundingSet=~CAP_NET_(BIND_SERVICE|BROADCAST|RAW) Service has no elevated networking privileges                              
 CapabilityBoundingSet=~CAP_AUDIT_*                          Service has no audit subsystem access                                      
 CapabilityBoundingSet=~CAP_SYS_ADMIN                        Service has no administrator privileges                                    
 PrivateTmp=                                                 Service has no access to other software's temporary files                  
 CapabilityBoundingSet=~CAP_SYSLOG                           Service has no access to kernel logging                                    
 PrivateDevices=                                             Service has no access to hardware devices                                  
 ProtectSystem=                                              Service has full access to the OS file hierarchy                        0.2
 ProtectProc=                                                Service has full access to process tree (/proc hidepid=)                0.2
 ProcSubset=                                                 Service has full access to non-process /proc files (/proc subset=)      0.1
 ProtectHome=                                                Service has full access to home directories                             0.2
 PrivateNetwork=                                             Service has access to the host's network                                0.5
 PrivateUsers=                                               Service has access to other users                                       0.2
 DeviceAllow=                                                Service has a device ACL with some special devices: char-rtc:r          0.1
 KeyringMode=                                                Service doesn't share key material with other services                     
 Delegate=                                                   Service does not maintain its own delegated control group subtree          
 SystemCallFilter=~@clock                                    Service does not filter system calls                                    0.2
 SystemCallFilter=~@cpu-emulation                            Service does not filter system calls                                    0.1
 SystemCallFilter=~@debug                                    Service does not filter system calls                                    0.2
 SystemCallFilter=~@module                                   Service does not filter system calls                                    0.2
 SystemCallFilter=~@mount                                    Service does not filter system calls                                    0.2
 SystemCallFilter=~@obsolete                                 Service does not filter system calls                                    0.1
 SystemCallFilter=~@privileged                               Service does not filter system calls                                    0.2
 SystemCallFilter=~@raw-io                                   Service does not filter system calls                                    0.2
 SystemCallFilter=~@reboot                                   Service does not filter system calls                                    0.2
 SystemCallFilter=~@resources                                Service does not filter system calls                                    0.2
 SystemCallFilter=~@swap                                     Service does not filter system calls                                    0.2
 IPAddressDeny=                                              Service does not define an IP address allow list                        0.2
 NotifyAccess=                                               Service child processes cannot alter service state                         
 ProtectClock=                                               Service cannot write to the hardware clock or system clock                 
 CapabilityBoundingSet=~CAP_SYS_PACCT                        Service cannot use acct()                                                  
 CapabilityBoundingSet=~CAP_KILL                             Service cannot send UNIX signals to arbitrary processes                    
 ProtectKernelLogs=                                          Service cannot read from or write to the kernel log ring buffer            
 CapabilityBoundingSet=~CAP_WAKE_ALARM                       Service cannot program timers that wake up the system                      
 CapabilityBoundingSet=~CAP_LINUX_IMMUTABLE                  Service cannot mark files immutable                                        
 CapabilityBoundingSet=~CAP_IPC_LOCK                         Service cannot lock memory into RAM                                        
 ProtectKernelModules=                                       Service cannot load or read kernel modules                                 
 CapabilityBoundingSet=~CAP_SYS_MODULE                       Service cannot load kernel modules                                         
 CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG                   Service cannot issue vhangup()                                             
 CapabilityBoundingSet=~CAP_SYS_BOOT                         Service cannot issue reboot()                                              
 CapabilityBoundingSet=~CAP_SYS_CHROOT                       Service cannot issue chroot()                                              
 PrivateMounts=                                              Service cannot install system mounts                                       
 CapabilityBoundingSet=~CAP_BLOCK_SUSPEND                    Service cannot establish wake locks                                        
 CapabilityBoundingSet=~CAP_LEASE                            Service cannot create file leases                                          
 CapabilityBoundingSet=~CAP_MKNOD                            Service cannot create device nodes                                         
 ProtectHostname=                                            Service cannot change system host/domainname                               
 CapabilityBoundingSet=~CAP_(CHOWN|FSETID|SETFCAP)           Service cannot change file ownership/access mode/capabilities              
 CapabilityBoundingSet=~CAP_SET(UID|GID|PCAP)                Service cannot change UID/GID identities/capabilities                      
 ProtectKernelTunables=                                      Service cannot alter kernel tunables (/proc/sys, …)                        
 RestrictAddressFamilies=~AF_PACKET                          Service cannot allocate packet sockets                                     
 RestrictAddressFamilies=~AF_NETLINK                         Service cannot allocate netlink sockets                                    
 RestrictAddressFamilies=~AF_UNIX                            Service cannot allocate local sockets                                      
 RestrictAddressFamilies=~…                                  Service cannot allocate exotic sockets                                     
 RestrictAddressFamilies=~AF_(INET|INET6)                    Service cannot allocate Internet sockets                                   
 CapabilityBoundingSet=~CAP_MAC_*                            Service cannot adjust SMACK MAC                                            
 RestrictSUIDSGID=                                           SUID/SGID file creation by service is restricted                           
 UMask=                                                      Files created by service are world-readable by default                  0.1

→ Overall exposure level for restic.service: 4.6 OK 🙂

Puanımız “4,6”: fena değil ama yine de artırabiliriz!

 

Yazının orijinalini buradan okuyabilirsiniz.