Perché conta
Un servizio non-root compromesso è meno grave di uno root — ma può comunque leggere dati, scrivere dove non dovrebbe, aprire connessioni, tentare escalation. La difesa in profondità dice: assumi che il servizio verrà bucato, e limita cosa potrà fare allora. systemd offre per questo uno dei sandbox più semplici da attivare in tutto Linux: poche righe nella unit mettono il processo in un recinto di filesystem, privilegi e syscall. Eppure è tra le funzioni meno usate. Rimediamo.
Misurare prima: systemd-analyze security
systemd ti dà un voto di esposizione per ogni servizio. Parti da qui per sapere dove intervenire.
|
|
Le direttive che contano
Si aggiungono nel blocco [Service], idealmente via drop-in (systemctl edit myapp.service) così non
tocchi la unit originale.
|
|
Ciascuna chiude una categoria di abusi: NoNewPrivileges spegne il trucco del SUID; ProtectSystem=strict
rende impossibile scrivere binari di sistema; PrivateTmp isola i file temporanei; SystemCallFilter
blocca intere famiglie di syscall (es. quelle per caricare moduli kernel) che un servizio normale non
usa mai.
Un esempio completo
|
|
DynamicUser=true è un bonus: fa girare il servizio sotto un utente effimero creato al volo e distrutto
allo stop — zero account da gestire, isolamento massimo (usalo solo con servizi che non hanno bisogno di
un UID stabile).
Applicare e verificare
|
|
Il rischio pratico: una direttiva troppo stretta impedisce al servizio di funzionare (es. non può
scrivere dove gli serve). Si procede per gradi, guardando i log: se il servizio si lamenta di un
percorso, lo aggiungi a ReadWritePaths; se di una syscall negata, allenti il filtro.
Domanda: se il servizio gira già sotto un utente non privilegiato dedicato, non è già abbastanza isolato? Che cosa aggiunge davvero tutto questo sandboxing, a parte il rischio di romperlo?
Girare sotto un utente dedicato è il primo strato e il più importante, ma protegge solo lungo un asse —
i permessi DAC — e lascia aperti molti altri che il sandboxing chiude. Pensa a cosa può fare un servizio
compromesso che gira come utente myapp non privilegiato, senza sandbox: può leggere ogni
file leggibile da "altri" sul sistema (e sono tanti: /etc/passwd, configurazioni, log, codice di altre
app), può scrivere in /tmp file che altri processi leggono (attacchi via file temporanei), può tentare di
sfruttare un binario SUID per salire a root, può aprire connessioni di rete verso l'esterno per
esfiltrare o scaricare un secondo stadio, può leggere le home degli utenti se i permessi lo consentono,
può provare syscall esotiche per sfruttare vulnerabilità del kernel. L'utente dedicato non ferma nulla di
tutto questo, perché sono tutte azioni che un utente normale può fare. Il sandboxing di systemd
chiude ciascuna di queste strade: ProtectSystem=strict + ReadWritePaths riduce
il filesystem a sola lettura tranne la sua cartella, quindi non scrive da nessun'altra parte;
ProtectHome gli nasconde le home; PrivateTmp gli dà un /tmp separato, neutralizzando
gli attacchi via temporanei; NoNewPrivileges rende inutile qualsiasi SUID, chiudendo la via
di escalation; SystemCallFilter gli toglie le syscall che non userebbe mai, riducendo la
superficie del kernel sfruttabile; RestrictAddressFamilies limita i tipi di socket. Ogni
direttiva trasforma "cosa potrebbe fare un attaccante da dentro quel servizio" in un recinto molto più
piccolo. Sul rischio di romperlo: è reale ma gestibile — si procede per gradi guardando i log, e il voto
di systemd-analyze security ti guida. Il costo è qualche minuto di tuning una volta; il
beneficio è che una compromissione del servizio resta confinata invece di diventare un piede dentro il
sistema. Questo è esattamente il senso della difesa in profondità: non un muro solo, ma tanti recinti.
Conclusione
Con una manciata di direttive — NoNewPrivileges, ProtectSystem, PrivateTmp, capabilities azzerate,
filtro seccomp — systemd mette ogni servizio in una gabbia, e systemd-analyze security misura i
progressi. È difesa in profondità quasi gratuita. I servizi, però, sono anche processi che consumano
risorse: la prossima linea di difesa riguarda processi, risorse e
cgroups.