Services uitvoeren als unprivileged user
Voorkom dat een bug direct volledige servertoegang geeft. Gebruik een eigen systeemaccount of gebruik de DynamicUser functie binnen systemd voor veiligheid.
Waarom niet alles als root uitvoeren
Root kan alles op de machine doen: elk bestand lezen, elke instelling wijzigen, het hele systeem verwijderen. Wanneer u een service als root uitvoert, geeft u al die macht aan die service. Als de service een bug heeft die een aanvaller kan misbruiken, krijgt de aanvaller niet alleen de service, maar ook root, en root is het hele serverbeheer. Het uitvoeren als een onbevoegde gebruiker beperkt de schade. Een bug in een service die als een beperkt account draait, geeft een aanvaller alleen toegang tot wat dat account kan aanraken, wat vrijwel niets zou moeten zijn.
Dit is het principe van de minste privileges (least privilege): geef elk onderdeel van het systeem precies de toegang die het nodig heeft om zijn taak uit te voeren, en niets meer. Het is de meest effectieve methode om de impact van een compromis te beperken, en op een moderne server kost het bijna niets om toe te passen.
Een toegewezen account per service
De klassieke aanpak is om voor elke service een aparte systeemgebruiker aan te maken, die alleen de bestanden van die service bezit en niet kan inloggen. Een systeemaccount voor een webapp ziet er als volgt uit:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin appsvcElke flag is belangrijk. --system maakt er een serviceaccount van in plaats van een gebruikersaccount. --no-create-home slaat een home directory over die niet nodig is. --shell /usr/sbin/nologin betekent dat een aanvaller, zelfs als deze het account op enige wijze verkrijgt, er geen shell mee kan openen. Het account bestaat alleen om een proces en de bijbehorende bestanden te bezitten.
Geef die gebruiker vervolgens alleen de bestanden die nodig zijn, en niets meer:
sudo chown -R appsvc:appsvc /opt/myappNu leest en schrijft de service in zijn eigen directory en heeft hij geen reden om elders op de disk actief te zijn. Als de service ooit wordt misbruikt, zijn de bestanden die de aanvaller kan wijzigen beperkt tot /opt/myapp; het account kan nog steeds alles lezen wat wereldwijd leesbaar is, maar kan de rest van het systeem niet wijzigen.
Laat systemd het als die gebruiker uitvoeren
Zodra het account bestaat, kunt u systemd opdracht geven de service als deze gebruiker uit te voeren. In het unit-bestand regelt één regel dit:
[Service]
ExecStart=/opt/myapp/bin/server
User=appsvc
Group=appsvcUser=appsvc betekent dat het proces start met de beperkte privileges van dat account in plaats van die van root. Dit is de normale, gebruikelijke manier om een applicatie onder systemd uit te voeren, en het is de moeite waard om dit voor elke service waarvoor u een unit schrijft toe te passen.
Of sla het account volledig over met DynamicUser
systemd kan nog een stap verder gaan en een tijdelijke gebruiker voor u aanmaken, die alleen bestaat zolang de service draait. Stel DynamicUser=yes in en u beheert helemaal geen account:
[Service]
ExecStart=/opt/myapp/bin/server
DynamicUser=yes
StateDirectory=myappBij de start wijst systemd een ongebruikte user ID toe; bij het stoppen wordt deze vrijgegeven. De service krijgt ook een private /tmp, een read-only weergave van het grootste deel van het bestandssysteem, en een writable state directory onder /var/lib/myapp die door StateDirectory= wordt ingesteld en overgedragen. Voor een zelfvoorzienende service die alleen zijn eigen state directory nodig heeft, is DynamicUser=yes de weg met de minste inspanning voor sterke isolatie, omdat er geen langdurig account is dat een aanvaller als doelwit kan kiezen.
Units handmatig schrijven is foutgevoelig, en het correct instellen van de hardening-directives vormt de meeste waarde. De generator in de systemd service en timer guide kan deze opties voor u invullen, zodat de unit de eerste keer correct is.
Hoe dit past bij de rest
Least privilege is één laag, en het werkt samen met de andere lagen in plaats van deze te vervangen. Een default-deny firewall regelt wat de service kan bereiken; het uitvoeren als een onbevoegde gebruiker regelt wat de service kan doen als deze wordt misbruikt; en hardened SSH houdt aanvallers in de eerste plaats van de machine af. Geen enkele van deze maatregelen is op zichzelf voldoende, maar samen betekent het dat een bug in één service niet leidt tot een compromis van de hele server.
Voordat u verdergaat, kunt u een hardening-checklist voor de hele machine doorlopen en een gepersonaliseerde kopie genereren om mee te werken:
FAQ
Waarom mag ik een service niet als root uitvoeren?
Omdat root alles op de machine kan doen. Een service die als root draait en wordt misbruikt, geeft de aanvaller de volledige server in handen, niet alleen de service. Het uitvoeren van de service als een beperkt, onbevoegde account beperkt de schade tot wat dat account kan bereiken. Reserveer root voor administratie en voer elke langdurig draaiende service uit als een beperkte gebruiker.
Hoe maak ik een gebruiker aan die niet kan inloggen?
Voer sudo useradd --system --no-create-home --shell /usr/sbin/nologin NAME uit. De nologin shell betekent dat het account geen interactieve sessie kan openen, zelfs niet als de inloggegevens gestolen zijn. --system markeert het als een serviceaccount en --no-create-home slaat een home directory over die niet nodig is. Geef het eigenaarschap van alleen de eigen bestanden met chown.
Wat is systemd DynamicUser?
DynamicUser=yes vertelt systemd om een tijdelijke gebruiker voor de service aan te maken die alleen bestaat zolang de service draait, zodat u nooit een langdurig account hoeft te beheren. Het geeft de service ook een private /tmp, een grotendeels read-only weergave van het bestandssysteem, en een beheerde state directory. Het is de weg met de minste inspanning om een zelfvoorzienende service uit te voeren onder een tijdelijke, laag-geprivilegieerde identiteit.
Vervangt uitvoeren als een non-root gebruiker een firewall?
Nee. Ze beschermen verschillende zaken. Het uitvoeren als een onbevoegde gebruiker beperkt wat een service kan doen als deze wordt misbruikt, terwijl een firewall beperkt wat de service überhaupt kan bereiken. Gebruik beide, samen met hardened SSH, zodat elke laag de zaken dekt die de andere niet kan dekken.
Welke bestanden moet de servicegebruiker bezitten?
Alleen de bestanden die de service daadwerkelijk nodig heeft, en niets meer. Geef het account eigenaarschap van de eigen werkdirectory en de data, en laat de rest van de bestanden in bezit van root. Een goed patroon is sudo chown -R svc-app:svc-app /opt/svc-app voor de applicatiedirectory, terwijl configuratie onder /etc in bezit van root blijft en alleen leesbaar is voor de service. Het doel is dat als het proces ooit wordt misbruikt, de bestanden die het kan wijzigen beperkt zijn tot de eigen data, niet de rest van het systeem.