Als je een webserver beheert die onderdeel is van het internet weet je één ding zeker: je wordt aangevallen. Vierentwintig uur per dag, zeven dag in de week proberen hackers en scriptkiddies op de meest creatieve manieren je server binnen te dringen. Hoe bescherm je jezelf daartegen? In deze workshop leggen we stap voor stap uit hoe je een groot deel van de bedreigingen het hoofd kunt bieden.
Martijn de Meulder
Een van de wonderen van het moderne internet is de beschikbaarheid van serverinfrastructuur. Betaalde je jezelf vroeger blauw aan een gedeeld hostingaccountje met een hele batterij beperkingen, tegenwoordig kun je bij de grotere hostingproviders al voor 15 euro in de maand een virtual private server (VPS) huren. Met vier processorcores en acht gigabyte geheugen bieden deze genoeg kracht om enorme hoeveelheid webservers en databaseapplicaties op te draaien. Als je weet hoe je ermee om kunt gaan zijn de mogelijkheden eindeloos. Maar zoals zijn oom Ben als in de eerste Spidermanfilm al aan Peter Parker vertelt: ‘met grote kracht komt ook grote verantwoordelijkheid’. Dat geldt ook voor jou als je zo’n server huurt. Want zo’n krachtige server kun je ook geweldig inzetten voor doelen die jij vermoedelijk helemaal niet voor ogen hebt, zoals voor het versturen van miljarden spamberichten, het hosten van dubieuze content of het aanvallen van andere servers op het internet. Criminelen, hackers en scriptkiddies zijn dag en nacht op zoek naar slecht beveiligde machines. Ook bij jouw VPS komen ze aankloppen, kijk je toegangslogs er maar eens op na. Je krijgt er koude rillingen van als je ziet hoe vaak allerlei volk uit de hele wereld langskomt. Meestal zijn het portscans of andere eenvoudige methodes om een indruk te krijgen van hoe je server eruit ziet, vergelijkbaar met het rammelen aan de deur om te voelen of het slot het er goed op zit. Maar ze zijn er wel en als jij even verslapt zullen ze binnendringen en toeslaan.
Zero-day-exploits
Om dat te voorkomen, is het zinvol je te verdiepen in het beveiligen van je machine. We benadrukken dat een waterdichte methode niet bestaat. Altijd kan er ergens diep in je software een zero-day-exploit zitten (een nog ongepubliceerde kwetsbaarheid) die alleen door de makers van de software kan worden gepatcht. Maar met de maatregelen in deze workshop kun je je server in ieder geval tot een moeilijk te nemen vesting maken en zo de meeste aanvallers buiten de deur houden.
In deze workshop richten we ons op het beveiligen van een Linux-webserver met een zogenoemde LAMP-configuratie: met Linux, Apache, MySQL en PHP – de meestgebruikte webservercombinatie ter wereld. Wij gebruiken CentOS als besturingssysteem, maar de kennis kun je ook toepassen op bijvoorbeeld Ubuntu of een van de andere Linux-varianten. Het belangrijkste verschil voor de interpretatie van deze workshop is vooral de gebruikte packagemanager, het systeem voor softwarepakketbeheer. Op CentOS is dat yum, terwijl Ubuntu – gebaseerd op Debian – apt-get gebruikt. Ook kan een enkel configuratiebestand op een andere plek staan, maar als je zoekt op internet op de naam van het bestand in combinatie met je besturingssysteem zul je snel de locatie weten. De configuratiebestanden zelf zullen in alle gevallen precies hetzelfde zijn.
Ook gaan we ervan uit dat je de webserver met bovenstaande software al draaiende hebt. We gebruiken de editor nano in de voorbeelden, heb je deze nog niet geïnstalleerd dan kun je dat doen met het commando yum install nano. Of als je Ubuntu/Debian gebruikt: sudo apt-get install nano. Wanneer je fan van vi of vim bent, kun je natuurlijk ook deze editors gebruiken.
Houd je server actueel
Zorg ervoor dat de software op je server altijd up-to-date is om oude lekken geen kans te geven. Gebruik het commando sudo yum check-update om te zien of er updates voor je systeem zijn. Zit er wat voor je bij? Tik dan yum update in waarna de pakketten worden bijgewerkt.
Deze manier van updaten is in de praktijk natuurlijk vrij lastig omdat je zelf alles moet doen. Je kunt het pakketbeheer ook automatiseren met yum-cron. Om deze service te installeren en activeren, gebruik je het volgende commando:
sudo yum install yum-cron
Kijk het configuratiebestand na en pas deze eventueel aan je wensen aan met:
sudo nano /etc/yum/yum-cron.conf
Bij alle opties zul je voldoende uitleg vinden om er de juiste beslissingen bij te maken. Let wel op de optie apply_updates, deze staat standaard op no. Maar om automatische updates uit te laten voeren – en dat wil je – moet je deze veranderen in yes.
Start nu de service en kijk de status na met deze commando’s:
sudo systemctl enable yum-cron.service sudo systemctl start yum-cron.service sudo systemctl status yum-cron.service
Om nu deze service altijd te laten starten, gebruik je de volgende twee commando’s:
sudo chkconfig yum-cron on sudo service yum-cron start
Ubuntu en Debian
Ook op Ubuntu is er een dergelijke service, ‘unattended upgrades’ genoemd. Deze kun je op een vergelijkbare manier configureren en installeren. Installeer de service met:
apt-get install unattended-upgrades
En bewerk daarna het configuratiebestand met:
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
Haal hier de beide slashes weg voor de regel met het woord updates en open het volgende bestand:
sudo nano /etc/apt/apt.conf.d/20auto-upgrades
Plaats daar de volgende regels in om iedere twee dagen te controleren op updates:
APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Download-Upgradeable-Packages "1"; APT::Periodic::AutocleanInterval "2"; APT::Periodic::Unattended-Upgrade "1";
Test ten slotte of het werkt:
sudo unattended-upgrades --dry-run –debug
Alles in orde? Gefeliciteerd, je server houdt zichzelf nu bij de tijd.
Beveilig ssh
Ssh (Secure shell) is een onmisbaar gereedschap voor het onderhoud van je server, het zorgt ervoor dat je door een versleuteld kanaal verbinding maakt met je machine en de opdrachtregel kunt gebruiken. Ssh werkt in een standaardinstallatie echter met een gebruikersnaam en een wachtwoord, en dat is een gapend gat in de beveiliging. Wachtwoorden kunnen worden geraden met zogenoemde brute-force-aanvallen. Het beste kun je de toegang tot je server met inlognaam en wachtwoord helemaal verwijderen. Ssh biedt daarvoor ondersteuning, je kunt met een sleutelpaar toegang krijgen: de publieke sleutel staat op je server, de private sleutel staat op de machine waarmee je toegang wilt hebben tot de server. Heeft iemand deze sleutel niet (iedereen buiten jezelf), dan wordt deze meteen geweigerd door de server.
Installeren doe je als volgt. Als eerste moet je de sleutels genereren. Download daarvoor het programma PuTTYgen vanaf www.puttygen.com. Start PuTTYgen na installatie en druk op de knop Generate. Na het genereren zie je de publieke sleutel in het venster verschijnen, kopieer deze naar het klembord. Geef in dit venster ook het wachtwoord op, en bewaar de publieke en private sleutel in een bestand door op de daarvoor aangegeven knoppen te drukken.
Ssh werkt standaard met een inlognaam en een wachtwoord: een gapend beveiligingsgat
Laatste keer met wachtwoord
Nu je dat hebt gedaan, kun je inloggen op je server (met ssh natuurlijk, maar voor de laatste keer nog met inlognaam en wachtwoord). Kopieer nu de publieke sleutel uit het PuTTYgen-venster en open het bestand ~/.ssh/authorized_keys met het commando:
sudo nano ~/.ssh/authorized_keys
Plak daarin de publieke sleutel die je zojuist hebt gekopieerd. Bestaat de directory .ssh in je home-directory nog niet – dat kan goed als je een nieuwe server configureert – maak deze dan eerst aan met mkdir .ssh. Zet daarna de permissies in een veilige stand met:
sudo chmod 700 ~/.ssh sudo chmod 600 ~/.ssh/authorized_keys restorecon -Rv ~/.ssh
Als je met een Linux-client werkt (zoals het hoort!) of met macOS, dan heb je PuTTYgen en bovenstaande instructie niet nodig, je kunt je sleutelpaar genereren én meteen naar ~/.ssh kopiëren met de volgende serie commando’s (aangenomen naar je Homebrew hebt geïnstalleerd op je systeem):
sudo brew install ssh-copy-id ssh-keygen -t rsa ssh-copy-id -i [hier het pad naar de zojuist aangemaakte sleutel] inlognaam@serveradres
Vervang de aanduiding [hier het pad naar de zojuist aangemaakte sleutel] door het volledige pad inclusief bestandsnaam.
Testen
Je kunt nu de installatie testen door je ssh-client opnieuw te configureren, hoe je dat doet hangt natuurlijk af van de software die je gebruikt. Wij gebruiken zelf Termius (www.termius.com). Druk daar op de configuratie van je server en scrol naar onderen. Verwijder het wachtwoord, maar laat je gebruikersnaam staan. Druk op Key en in het venster dat volgt op de groene knop + key. In het venster dat je ziet, kun je de inhoud van het bestand met de private sleutel kopiëren dat je zojuist met PuTTYgen hebt opgeslagen. Geef daar ook het wachtwoord op dat je hebt ingegeven in PuTTYgen en sla de gegevens op. Nu kun je verbinding maken met de server. Lukt dat? Gefeliciteerd, je kunt nu overgaan op de laatste stap: het verbieden van toegang met inlognaam en wachtwoord.
Alleen nog met sleutels
Het verbieden van het gebruik van wachtwoorden doe je door op je server het sshd-configuratiebestand te bewerken met het commando:
sudo nano /etc/ssh/sshd_config
Zoek naar de regel PasswordAuthentication en veranderd yes in no. Sluit nano af en herstart de ssh-service met:
sudo systemctl restart sshd
Wel even testen natuurlijk vanaf je lokale computer of je echt niet meer kunt aanmelden met inlognaam en wachtwoord. Als dat mislukt heb je een enorme stap voorwaarts gedaan in het beveiligen van je server.
Actieve bewaking met Fail2ban
Je hoeft niet ál het beveiligingswerk zelf te doen, je kunt met Fail2ban ook een automatische bewakingsrobot op je server installeren. Fail2ban scant de logbestanden van de serversoftware die je hebt draaien, zoals ssh, Apache en ftp, op zoek naar kwaadaardige activiteit zoals inlogpogingen en zoektochten naar bekende zwakheden. Ontdekt het een poging tot inbraak, dan past Fail2ban zelf de regels van je firewall aan om de ip-adressen die verantwoordelijk zijn voor het ongewenste gedrag alle toegang tot je systeem te ontzeggen. In Fail2ban-terminologie: het ip-adres wordt in de ‘jail’ geplaatst.
Fail2ban zit niet in de standaard CentOS-distributie, maar in de Extra Packages for Enterprise Linux (EPEL) van Red Hat. Installeer de package met de commando’s:
sudo yum install epel-release sudo yum install fail2ban
Voor Ubuntu hoef je EPEL niet te installeren, dit commando is genoeg:
sudo apt-get install fail2ban
Kopieer dan het standaard configuratiebestand en open het in nano:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local sudo nano /etc/fail2ban/jail.local
Jails
Lees in dit bestand rustig de opties door die op jouw machine van toepassing zijn, vooral ook de instellingen onder het kopje JAILS, waar de gevangenissen voor aanvallers van de verschillende diensten op je server worden ingesteld. De meeste opties hoef je niet te wijzigen, let echter op de optie enabled = true in de ssh-jail-sectie, die staat nog niet aan. Haal het hekje (#) voor deze regel weg.
Ben je tevreden met de instellingen? Sluit dan de editor af, voeg Fail2ban toe aan de standaard op te starten diensten van je server en start de service met:
sudo systemctl enable fail2ban sudo systemctl start fail2ban
Wil je weten of Fail2ban draait? Dan kun je de status ervan controleren met:
sudo fail2ban-client status
Zien welke inbrekers een mislukte poging op je ssh-dienst hebben gedaan? Gebruik dan de opdracht:
sudo fail2ban-client status sshd
Welke ip-adressen zijn verbannen? Al is dat meestal pas na een paar uur of een paar dagen zinvol:
sudo zgrep 'Ban' /var/log/fail2ban.log*
Wil je een live log zien van malicieuze pogingen?
sudo tail -F /var/log/fail2ban.log
Ftp-toegang beveiligen
Als je een webserver draait, is de kans dat je ook een ftp-server hebt natuurlijk bijzonder groot. Ftp is een geweldig protocol dat ook heel makkelijk werkt. Het grote nadeel ervan is dat bestanden, wachtwoorden en inlognamen bij een standaardinstallatie onversleuteld worden verstuurd. Dat is niet verstandig, het maakt je kwetsbaar voor allerlei ‘man-in-the-middle’-aanvallen. Niet alleen op internet, maar bijvoorbeeld ook bij het gebruiken van een openbare hotspot (zonder vpn). Daarom gaan we de bestandsoverdracht beveiligen met een sleutel. We richten ons Vsftpd, op dit moment de meest gebruikte Linux-ftp-server en we gaan ervan uit dat je deze inmiddels draaiende hebt.
Het idee is dat je een sleutel en een certificaat genereert, en deze op je server bewaart. Maak daartoe eerst een directory aan:
sudo mkdir /etc/ssl/private
Genereer je certificaat-sleutelpaar met het volgende commando:
openssl req -x509 -nodes -days 3650 -newkey rsa:1024 -keyout /etc/ssl/private/ftp_certificaat.pem -out /etc/ssl/private/ftp_certificaat.pem
Beantwoord de vragen die aan je worden gesteld. Het belangrijkst is die van de hostnaam: deze moet overeenkomen met de hostnaam van je server.
Configuratiebestand instellen
Stel nu het ftp-serverconfiguratiebestand in met:
sudo nano /etc/vsftpd/vsftpd.conf
En voeg de volgende regels toe aan het einde van het bestand:
ssl_enable=YES allow_anon_ssl=NO force_local_data_ssl=YES force_local_logins_ssl=YES ssl_tlsv1=YES ssl_sslv2=NO ssl_sslv3=NO rsa_cert_file=/etc/ssl/private/ftp_certificaat.pem rsa_private_key_file=/etc/ssl/private/ftp_certificaat.pem
Herstart je server:
systemctl restart vsftpd
Het is nu niet meer mogelijk om zonder versleutelde verbinding contact te maken met je ftp-server, precies zoals we dat wilden. Stel sftp in als de standaard verbindingsmethode van je client en maak verbinding. Je ftp-client – wij gebruiken FileZilla – zal een overzicht van de door jou gebruikte serversleutel laten zien. Accepteer deze, daarna zal de client verbinding maken met je server.
Versterk je MySQL-database
Geen moderne website kan zonder goede database en MySQL is daarvoor doorgaans de standaardkeuze. Met het dichttimmeren van de MySQL-installatie kom je al een heel eind als je het mysql-hardening-script op je systeem draait dat je met de installatie van de software krijgt meegeleverd. Daarmee kun je in één beweging wachtwoorden beheren, anoniem gebruik tegengaan, externe verbindingen naar je database onmogelijk maken en verwijder je testdata:
sudo mysql_secure_installation
Volg de instructies zorgvuldig en je komt een heel eind. Verder geldt dat het goed is om je gebruikers te beperken in hun bewegingsvrijheid: geef ze alleen toegang tot de hoogstnoodzakelijke databases. En mocht je toch netwerkverbindingen willen toestaan, versleutel ze. Hoe je dat instelt gaat voorbij de essentie van dit verhaal, je kunt in het diepe duiken aan de hand van dit artikel op de website Medium.com: www.tiny.cc/5mysql.
MySQL en php
Besteed wat extra aandacht de manier waarop je MySQL via scripts zoals php gebruikt. De klassieke methode is die met het gebruik van de mysqli-driver. Deze is inherent onveilig als je parameters uit de url accepteert en in database-query’s opneemt. Je kunt dan het slachtoffer worden van MySQL-injection-aanvallen. Een veel modernere en stabielere methode vind je in de vorm van een database-abstractielaag als PDO (PHP Data Objects), die je helpt je query’s op relatief eenvoudige wijze te beveiligen. Start met lezen op www.phpdelusions.net/pdo.
En ten tweede is er PHPMyAdmin, deze php-frontend voor MySQL is niet voor niets enorm populair en maakt het beheer van je databases veel eenvoudiger. Zorg dat de toegangspoort ertoe niet makkelijk te vinden is (zie ook het kader ‘Security through obscurity’). Dat doe je door het configuratiebestand te openen:
sudo nano /etc/httpd/conf.d/phpMyAdmin.conf
Onder Ubuntu vind je dit bestand op /etc/apache2/conf.d/phpmyadmin.conf. Verander daar deze regel in iets creatievers:
Alias /phpMyAdmin /usr/share/phpMyAdmin
Bijvoorbeeld:
Alias /pcm_masterclass_toegang /usr/share/phpMyAdmin
Daarna open je PHPMyAdmin door naar https://servernaam.nl/pcm_masterclass_toegang te gaan.
En als je toch in dit bestand bezig bent, je kunt de toegang tot PHPMyAdmin beperken tot alleen het (vaste) ip-adres van je client-pc, door direct onder de start van <Directory /usr/share/phpMyAdmin/> het volgende toe te voegen:
Order Deny,Allow Deny from All Allow from 1.2.3.4
Waarbij je 1.2.3.4 vervangt met jouw eigen ip-adres. Zo sluit je heel de wereld buiten, behalve jezelf. Sluit de editor af en herstart apache met:
sudo systemctl restart apache
En controleer of het werkt.
Beveilig je Apache webserver
Apache is van zichzelf al een behoorlijk veilige webserver. Maar het is goed om zelf nog het een en ander af te stellen. Daarom drie snelle tips voor een betere Apache:
Stap 1: versleutel al je verkeer
Dat doe je met een ‘Let’s Encrypt’-certificaat en de volgende commando’s. We gaan ervan uit dat je al een domeinnaam aan de server hebt gekoppeld en deze als virtual host hebt geconfigureerd:
sudo yum install epel-release (mocht je deze nog niet hebben geïnstalleerd) sudo yum install certbot python2-certbot-apache mod_ssl sudo certbot install sudo certbot --apache
Volg de instructies – vergeet niet te selecteren dat al het gewone verkeer wordt doorgestuurd naar poort 443 – en herstart je webserver met:
sudo systemctl restart apache
Stap 2: verberg je softwareversies
Je server verraadt meer over zichzelf dan nodig is, geef de url van server maar eens op bij http://security.firewallmonitor.org. Dan zie je dat zaken als de Apache-versie, je besturingssysteem en php-versie zichtbaar zijn in zowel de footer van lege pagina’s als in de http-headers. Daar heeft helemaal niemand iets mee te maken. Je kunt ze gelukkig makkelijk verbergen, open het Apache-configuratiebestand met:
sudo nano /etc/httpd/conf/httpd.conf
Onder Ubuntu vind je dit bestand op /etc/apache2/conf/httpd.conf of apache2.conf. Onderaan dit bestand voeg je de volgende regels toe:
ServerSignature Off ServerTokens Prod
Scherm ook de php-versie af door php.ini te bewerken:
sudo nano /etc/php.ini
Wijzig de regel expose_php in expose_php = Off
Als je toch bezig bent, voorkom ook dat php meer informatie over fouten laat zien met:
display_errors = 0 display_startup_errors = 0
En maak uploads onmogelijk als dat kan, zo kunnen hackers in geen geval geen dubieuze scripts naar je server uploaden via het web:
file_uploads = 0
Sla php.ini op en herstart apache met:
sudo systemctl restart apache
Stap 3: voorkom browsen directory’s
Open het configuratiebestand van Apache met:
sudo nano /etc/httpd/conf/httpd.conf
Zoek naar de content directive en wijzig deze in:
<Directory /var/www/html/> Options -Indexes AllowOverride None Require all granted </Directory>
Als een directory niet is voorzien van een index.php of .html, dan zal je server niet meer laten zien welke bestanden er in staan. En ook nu geldt: herstart natuurlijk de webserver:
sudo systemctl restart apache
Tot slot
Je server is nu veel veiliger geworden. De meeste kwaadwillenden houd je nu buiten de deur. Maar vergeet niet dat veiligheid ook een werkhouding is, niet louter het instellen van software en hardware. Zorg dat je op de hoogte blijft van de ontwikkelingen op dit gebied, handel zelf op een veilige manier en maak je back-ups. Veilig ben je nooit honderd procent, maar als je het goed doet, dan kun je heel veel ellende voor zijn. En dat is waar het allemaal om is begonnen.
Security through obscurity
Het belangrijkste wat je moet doen om hackers buiten de deur van je server te houden is zorgen dat je software up-to-date is en dat je configuratie op orde is. Maar er is nog een stroming binnen het beveiligingsdenken die het verdient vermeld te worden: ‘security through obscurity’ zoals dit in de digitale wandelgangen wordt genoemd. Of zoals de Nederlandse overheid in zijn anti-inbraakcampagne aanduidt: ‘maak het ze niet te makkelijk’. Zorg dat je een goed slot op je deur hebt, maar het helpt ook als je zorgt dat die deur niet te vinden is. Veel software gebruikt immers standaardmethoden voor zijn installatie en locatie, zorg dat je daar vanaf wijkt. Een mooi voorbeeld is de database-administratiesoftware phpMyAdmin. Dat is een heel gemakkelijke webinterface voor MySQL die zichzelf standaard installeert op www.domein.nl/phpmyadmin. Dat is natuurlijk heerlijk voor hackers. Ze weten daardoor dat je deze software hebt draaien (en kunnen uitzoeken of er misschien een exploit voor is) én dat je server op MySQL draait. Ze kunnen ook proberen het wachtwoord te kraken. Het is in de configuratie van phpMyAdmin makkelijk om die locatie veranderen. Het is namelijk geen directory, maar een alias (zie de paragraaf ‘MySQL en php’). Dus verander dat echt! Weinig hackers zullen de locatie www.domein.nl/pcm_masterclass_toegang kunnen raden. Dat is een kleine maar belangrijke stap op weg naar meer veiligheid. Het is verstandig dat voor alle software met standaardlocaties te doen, denk bijvoorbeeld ook aan WordPress: www.domein.nl/wp-login is een klassieker in de poortscans. En let ook op alles onder de /vendor-directory die door Composer wordt geïnstalleerd.