De meeste gehackte Magento-shops zijn niet gehackt door een geniale aanvaller. Er stond een bestand open, een poort publiek of een map beschrijfbaar die dat niet…
De meeste gehackte Magento-shops zijn niet gehackt door een geniale aanvaller. Er stond een bestand open, een poort publiek of een map beschrijfbaar die dat niet hoefde te zijn.
Server hardening is het saaie werk dat een lek in je code een stuk minder duur maakt. Dit artikel loopt langs wat wij bij elke Magento-server controleren.
Wat hardening wel en niet doet
Hardening voorkomt geen kwetsbaarheden in Magento zelf. Als er een RCE in de applicatie zit, zoals bij CosmicSting (CVE-2024-34102) of SessionReaper (CVE-2025-54236), blijft patchen de enige echte oplossing.
Wat hardening wel doet:
- de schade beperken als een aanvaller binnenkomt;
- veelvoorkomende aanvalsroutes dichtzetten (uploads uitvoeren, bestanden lezen);
- voorkomen dat je database, cache en zoekmachine publiek bereikbaar zijn;
- zorgen dat je merkt wat er gebeurt.
Zie het als een brandwerende deur. Hij voorkomt de brand niet, hij houdt hem op één kamer. Voor de applicatiekant hebben we de Magento 2 security checklist.
1. Webroot: alleen pub/
Dit is de belangrijkste regel en tegelijk de meest overgeslagen. De webserver hoort naar pub/ te wijzen, niet naar de Magento-root.
Wijst je webroot naar de hoofdmap, dan zijn app/etc/env.php, composer.json, var/ en logbestanden potentieel via de browser op te vragen. Dat gaat meestal goed totdat een regel in je nginx-configuratie een keer afwijkt.
server {
listen 443 ssl;
server_name www.voorbeeld.nl;
set $MAGE_ROOT /var/www/magento;
root $MAGE_ROOT/pub;
# rest van de configuratie
}
Magento levert een nginx.conf.sample mee. Gebruik die als startpunt en pas hem aan, in plaats van zelf een config te bouwen. Controleer na elke Magento-upgrade of het voorbeeldbestand is aangepast.
2. Geen PHP uitvoeren in media/ en andere schrijfbare mappen
Veel webshell-aanvallen verlopen zo: de aanvaller krijgt via een kwetsbaarheid een bestand in pub/media en roept het aan. Als nginx daar PHP uitvoert, is het spel gespeeld.
Blokkeer PHP-uitvoer in alle mappen waar de webserver-gebruiker naartoe schrijft:
location ~ ^/(media|static)/.*\.php$ {
deny all;
}
location ~ ^/(media|static)/.*\.(phtml|php[0-9]?|phar)$ {
deny all;
}
Het Magento-voorbeeld bevat al een deel hiervan, maar controleer of het in jouw actieve config staat. Wij testen dit met een onschuldig testbestand: staat er een .php-bestand in media/ dat een tekst teruggeeft, en wordt die uitgevoerd? Dan staat er iets fout.
Blokkeer ook toegang tot dingen die nooit publiek horen te zijn:
location ~ /\.(git|svn|env|ht) {
deny all;
}
location ~* \.(sql|bak|old|orig|log|zip|tar|gz)$ {
deny all;
}
Voor een bredere lijst van zulke fouten, zie ons artikel over security misconfiguration.
3. Bestandsrechten en eigenaarschap
Het principe: de PHP-gebruiker mag alleen schrijven waar Magento echt moet schrijven.
Een veelgebruikte opzet:
- Eén gebruiker is eigenaar van de code (bijvoorbeeld de deploy-user).
- PHP-FPM draait onder een andere gebruiker, met alleen schrijfrechten op
var/,generated/,pub/media/enpub/static/(in productiemode wordt static niet runtime geschreven). - Code en configuratie zijn alleen-lezen voor de PHP-gebruiker.
Waarom dit helpt: zelfs als een aanvaller code kan uitvoeren als de PHP-gebruiker, kan hij dan geen bestaande PHP-bestanden in vendor/ of app/ aanpassen. Dat maakt het inbrengen van een backdoor in de kern moeilijker en makkelijker te detecteren.
Wat wij vaak zien: chmod -R 777 "omdat het dan werkt". Doe dat nooit. Het lost een eigenaarsprobleem op met een gat in de beveiliging.
Controleer ook:
app/etc/env.phpenapp/etc/config.phpniet wereld-leesbaar;- productiemode aan (
bin/magento deploy:mode:show); - geen
.git-map op de productieserver, deploy via artifacts of rsync.
4. PHP-FPM en php.ini
Eigen pool per site
Draai elke webshop in een eigen PHP-FPM-pool met een eigen gebruiker. Delen twee sites een pool, dan kan een gehackte site de bestanden van de ander lezen.
disable_functions: een afweging
Je kunt gevaarlijke functies uitzetten, zoals exec, shell_exec, system, passthru en proc_open. Dat maakt de meeste kant-en-klare webshells onbruikbaar.
Maar let op:
- Magento zelf en sommige extensies gebruiken een deel van deze functies, bijvoorbeeld voor image-verwerking of PDF-generatie.
- Een te agressieve lijst geeft kapotte cron-jobs en rare foutmeldingen.
Ons advies: begin met een lijst, test op staging inclusief cron, imports en PDF's, en pas dan toe op productie. Is het een garantie? Nee. Een aanvaller met PHP-uitvoering heeft vaak alternatieven. Het is een extra laag, geen oplossing. Over-engineeren hier levert bij een kleine shop weinig op ten opzichte van de rest van dit artikel.
open_basedir
Met open_basedir beperk je waar PHP bestanden mag lezen. Dat is nuttig als je meerdere sites op één server hebt. Neem de tijdelijke map en de Magento-root op in de lijst, en test of imports, exports en media-uploads nog werken.
Overige instellingen
expose_php = Off: verbergt de PHP-versie in headers.display_errors = Offin productie,log_errors = On.allow_url_include = Off(is dat meestal al).- Houd PHP zelf bij. Een recent voorbeeld is de PHP-RCE-kwestie die we beschreven in ons artikel over PHP2Shell (CVE-2026-109618 en CVE-2026-109619). Daar helpt geen enkele hardening-instelling tegen: je moet updaten.
5. Redis, OpenSearch en MySQL: nooit publiek
Dit is misschien de duurste fout en ook de meest vermijdbare. Een Redis zonder wachtwoord op een publiek IP is binnen uren gevonden door scanners. Hetzelfde geldt voor OpenSearch/Elasticsearch en MySQL.
Wat dat concreet betekent:
| Service | Standaardpoort | Wat we instellen |
|---|---|---|
| MySQL/MariaDB | 3306 | bind-address = 127.0.0.1 of privé-netwerk |
| Redis | 6379 | Alleen localhost of privé-netwerk, wachtwoord, geen FLUSHALL voor onbevoegden |
| OpenSearch | 9200 | Alleen localhost/privé, authenticatie als het netwerk gedeeld is |
| RabbitMQ | 5672/15672 | Alleen intern, beheer-UI niet publiek |
Controleer vanaf buiten je netwerk wat er open staat:
nmap -Pn -p 22,80,443,3306,6379,9200,5672,15672 jouw-server-ip
Alleen 80 en 443 (en SSH, zie hieronder) horen er open te staan. Daarnaast zet je een firewall aan die standaard alles blokkeert. Dat is ook een eis bij hosts die je goed kiest: zie onze pagina over Magento hosting.
Staat Redis ook voor sessies? Dan is een open Redis niet alleen dataverlies, maar ook sessie-overname. Dat is exact het type risico dat bij SessionReaper meespeelt.
6. SSH en toegang
- Alleen SSH-keys, geen wachtwoordlogin (
PasswordAuthentication no). - Root-login uit (
PermitRootLogin no). - Eén persoonlijk account per mens, geen gedeelde gebruiker.
- SSH beperken tot bekende IP's of een VPN, waar praktisch.
- Verwijder keys van ex-medewerkers en ex-leveranciers. Controleer
authorized_keysecht, niet alleen in je hoofd. - Een tool als fail2ban voor herhaalde loginpogingen.
Een kleine tip: gebruik aparte keys voor deploys. Een deploy-key die alleen kan deployen is veel minder risicovol dan een persoonlijke sleutel met sudo.
7. TLS en headers
Zet TLS 1.2 en 1.3 aan, oudere protocollen uit. Voeg basisheaders toe:
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Let op met HSTS en includeSubDomains: controleer eerst of al je subdomeinen HTTPS aankunnen, anders sluit je jezelf buiten. Magento zet zelf ook al een aantal headers. Voorkom dubbele of tegenstrijdige waarden.
8. Logging, logrotatie en monitoring
Logs zijn je geheugen na een incident. Zonder logs weet je niet hoe de aanvaller binnenkwam.
- Rouleer logs (
logrotate) en bewaar ze lang genoeg om een inbraak van weken terug te kunnen onderzoeken. Hoe lang precies hangt af van je situatie en de AVG. - Houd
access.log,error.log, PHP-FPM slowlog envar/logapart. - Stuur logs bij voorkeur naar een andere plek, zodat een aanvaller ze niet kan wissen.
- Zet monitoring op bestandswijzigingen in
app/,vendor/enpub/. Een eenvoudige hash-vergelijking tegen je git-repository vangt veel op.
Meer hierover: security logging voor webshops en ons incident response plan.
9. Updates van het besturingssysteem
Een server die al een jaar niet is bijgewerkt, is een server met bekende lekken. Zet automatische security-updates aan voor het OS, plan een maandelijks venster voor kernel-updates en herstarts, en houd een lijst bij van de versies van nginx, PHP, MySQL, Redis en OpenSearch. Zie ook Magento-versies en end of support, want ook onderliggende componenten verlopen.
Hardening-checklist
- [ ] Webroot is
pub/ - [ ] Geen PHP-uitvoer in
media/enstatic/ - [ ]
.git,.env, back-ups en logs niet publiek - [ ] Code alleen-lezen voor de PHP-gebruiker
- [ ] Geen
chmod 777 - [ ] Eigen PHP-FPM-pool per site
- [ ]
display_errorsuit,expose_phpuit - [ ] MySQL, Redis, OpenSearch, RabbitMQ alleen intern
- [ ] Firewall: standaard dicht
- [ ] SSH met keys, geen root, geen gedeelde accounts
- [ ] TLS-configuratie en basisheaders gecontroleerd
- [ ] Logrotatie en externe logopslag
- [ ] OS-updates en PHP-updates bijgehouden
Veelgestelde vragen
Is disable_functions verplicht voor Magento?
Nee. Het is een extra laag die sommige webshells onbruikbaar maakt, maar het kan ook legitieme functionaliteit breken. Test het op staging inclusief cron, imports en PDF-generatie. Ontbreekt de rest van de hardening, dan levert deze maatregel weinig op.
Waarom moet de webroot pub/ zijn?
Omdat dan alleen bestanden in pub/ via de webserver bereikbaar zijn. Configuratie, broncode, vendor/ en logs liggen buiten de webroot. Een fout in een nginx-regel kan dan niet meteen je env.php blootleggen.
Mag ik Redis of OpenSearch publiek bereikbaar maken voor een koppeling?
Liever niet. Gebruik een privé-netwerk, een VPN of een SSH-tunnel. Moet het publiek, dan met authenticatie, TLS en een IP-allowlist. Voor Redis zonder wachtwoord geldt: nooit publiek.
Hoe vaak moet ik mijn server laten controleren?
Na elke grote wijziging (nieuwe server, migratie, nieuwe PHP-versie) en minimaal jaarlijks. Een security audit kijkt ook naar de serverkant, niet alleen naar code.
Is dit ook van toepassing als mijn hoster alles beheert?
Deels. Een goede managed host regelt OS, firewall en veel PHP-instellingen. Vraag expliciet wat zij doen en wat jij zelf moet doen, bijvoorbeeld nginx-regels, bestandsrechten en toegangsbeheer. Dat grijze gebied is waar het misgaat.
Willen we meekijken naar je server? Wij doen hardening-reviews en beheren Magento-omgevingen via Magento support, met direct contact en zonder tussenlagen. Vraag het via /contact, of lees meer over Magento security.

Geschreven door Ruthger Idema
15+ jaar ervaring in e-commerce development. Gespecialiseerd in Magento, Shopify en Laravel maatwerk.
Meer over ons team →


