
Joomla beveiligen: security hardening in de diepte
De meeste Joomla-sites worden niet gehackt door slimme, gerichte aanvallen. Ze worden gehackt vanwege een verouderde extensie, een zwak wachtwoord of een instellingen die nooit zijn aangepast. Security hardening houdt in dat je die gemakkelijke toegangswegen afsluit voordat iemand er gebruik van maakt.
Dit artikel legt stap voor stap uit hoe je een Joomla-site hardent. Het behandelt de basis voor eigenaren en redacteuren, de dagelijkse instellingen voor beheerders, en de technische details voor ontwikkelaars. Je leert hoe je de core en extensies up-to-date houdt, gebruikersaccounts beschermt met sterke wachtwoorden en multi-factor authenticatie, de beveiligingsinstellingen in de Algemene configuratie afstelt, de webserver hardent, de juiste HTTP security headers verstuurt, je logs in de gaten houdt, en begrijpt welke beschermingen Joomla al voor je ingebouwd heeft.
Beveiliging is geen product dat je installeert. Het is een reeks gewoontes, en Joomla biedt je de hulpmiddelen voor bijna al die gewoontes.
Het doel is eenvoudig: je met vertrouwen je Joomla-site laten hardenen, grotendeels met wat er al in Joomla zit.
1. De basis
1.1 Wat is security hardening?
Security hardening betekent het aantal manieren verkleinen waarop een aanvaller je site binnenkomt, en de schade beperken wanneer er toch iets misgaat. Het is niet een magische schakelaar. Het is een reeks kleine beslissingen in vier lagen:
| Laag | Voorbeelden |
|---|---|
| Server | PHP-versie, HTTPS, bestandsrechten, .htaccess-regels. |
| Joomla core | Updates, Algemene configuratie, sessie-instellingen, security headers. |
| Extensies | Updates, verwijderen wat je niet gebruikt, betrouwbare ontwikkelaars kiezen. |
| Mensen | Sterke wachtwoorden, multi-factor authenticatie, beperkte rechten. |
Elke laag telt. Een volledig gepatchte Joomla achter een zwak Super User-wachtwoord is nog steeds een open deur.
1.2 Hoe Joomla-sites echt gecompromitteerd raken
Jaar na jaar staan dezelfde oorzaken bovenaan de lijst:
- Verouderde extensies met bekende kwetsbaarheden.
- Verouderde Joomla core-versies.
- Zwakke of hergebruikte wachtwoorden op beheerdersaccounts.
- Achtergebleven bestanden: oude back-ups, testkopieen, verlaten componenten.
- Gecompromitteerde hosting-buren op slecht gescheiden shared servers.
Let op wat er niet hoog op de lijst staat: exotische zero-day-aanvallen. De meeste inbraken gebruiken problemen die al opgelost waren in een update die de site nooit installeerde. Dat is goed nieuws, want het betekent dat de effectiefste hardening-stappen ook de simpelste zijn.
1.3 Beveiliging is een proces
Je hardent een site een keer, maar je houdt hem elke week veilig: updates installeren, accounts controleren, logs bekijken, back-ups verifieren. Dit artikel volgt die volgorde, van de stappen met de grootste impact naar de fijnere details.
Naar boven2. Hou alles up-to-date
2.1 Core-updates
Joomla updaten is de meest effectieve beveiligingsmaatregel die je kunt nemen. Joomla kondigt beveiligingsfixes aan in de release notes, wat betekent dat elke release aanvallers ook precies vertelt wat er kapot was in de vorige versie. Vanaf het moment dat een security release uit is, worden niet-gepatchte sites doelwit.
Je updatet via Systeem → Update → Joomla. Sinds Joomla 6 verifieert het updatesysteem downloads met TUF (The Update Framework): de update-metadata is cryptografisch ondertekend, zodat een gemanipuleerde updateserver of een vergiftigde download je geen nep-Joomla-pakket kan aansmeren.
Joomla kan zichzelf ook updaten sinds versie 5.4. In de opties van Joomla Update kun je de site registreren voor automatische updates, zodat patch releases op de achtergrond installeren zonder op jou te wachten. Let op de reikwijdte: dit werkt alleen Joomla zelf bij en verder niets - je third-party extensies updaten nooit automatisch en blijven jouw taak (sectie 2.2). De dienst vereist dat je site bereikbaar is vanaf het internet, en met de optie backupcheck laat je Joomla eerst controleren op een recente back-up. Voor een site die niet elke week door een mens wordt bijgewerkt, zijn automatische updates een sterk vangnet.
Automatische updates zijn niet de enige professionele strategie. Op mijn eigen sites, en op websites van klanten met een onderhoudscontract, laat ik ze bewust uit: ik wil zelf bepalen wanneer een update draait. Als ik handmatig update en er daarna iets vreemds op de site verschijnt, is de update mijn eerste verdachte - een verband dat je makkelijk mist wanneer updates stilletjes op de achtergrond installeren.
Om handmatige updates werkbaar te houden over veel sites gebruik ik YourSites, een commercieel sitebeheerplatform dat je als Joomla-extensie op een eigen site installeert. Vanuit dat ene dashboard monitor en update ik alle Joomla-, WordPress- en ClassicPress-sites die ik onderhoud - en omdat het zelf gehost is, verlaat er nooit klantdata mijn eigen server, wat de opzet AVG-vriendelijk houdt. Kies de strategie die past bij hoe de site beheerd wordt: automatische updates voor een site waar niemand wekelijks naar kijkt, gecontroleerde centrale updates wanneer een professional erover waakt.
2.2 Extensie-updates
Extensies zijn aanvalsvector nummer een, dus neem hun updates net zo serieus als core-updates. Controleer regelmatig Systeem → Update → Extensies. Schakel de plugin Task - Update Notification in samen met de taakplanner, en Joomla e-mailt je wanneer er een nieuwe core-versie beschikbaar is, ook als niemand inlogt op de backend.
De backend is niet je enige kanaal. De meeste serieuze ontwikkelaars hebben een nieuwsbrief en mailen hun gebruikers over beveiligingsupdates - abonneer je voor elke extensie waar je op leunt. Een centraal dashboard zoals YourSites (sectie 2.1) houdt extensie-updates over al je sites tegelijk bij. En actief zijn in de Joomla-community levert meer op dan mensen verwachten: vrijwilligers en ontwikkelaars praten met elkaar, dus nieuws over een probleem bereikt je vaak eerder dan de formele release.
Het tempo is hier veranderd. AI-ondersteunde code-analyse heeft het goedkoop en snel gemaakt om grote hoeveelheden extensiecode op beveiligingsfouten te scannen, en beide kanten gebruiken het. Ontwikkelaars en beveiligingsonderzoekers vinden en repareren kwetsbaarheden in extensies van derden nu in een veel hoger tempo dan vroeger, en daarom zie je de laatste tijd zoveel security releases van extensies. Aanvallers gebruiken dezelfde technieken om sites te vinden die die fixes nog niet hebben geinstalleerd. Het gevolg: het veilige venster tussen een security release en actieve uitbuiting wordt steeds kleiner, dus installeer extensie-updates snel in plaats van "als ik er een keer aan toekom".
Een gestage stroom beveiligingsfixes van een ontwikkelaar is meestal een goed teken, geen slecht. Het betekent dat iemand de code actief controleert en reageert. De extensie om je zorgen over te maken is degene die nooit een beveiligingsfix publiceert.
Twee selectiegewoonten voorkomen de meeste ellende vooraf: installeer alleen extensies van betrouwbare ontwikkelaars met een staat van dienst, en kies bij voorkeur extensies die aansluiten op Joomla's eigen updatemechanisme, zodat nieuwe versies automatisch verschijnen onder Systeem → Update → Extensies. De officiele Joomla Extension Directory (JED) markeert die vermeldingen met "Uses Joomla! Update System" - beschouw een vermelding zonder dat kenmerk als een waarschuwingssignaal.
2.3 PHP en de server-stack
Een verouderde PHP-versie krijgt geen beveiligingsfixes meer, hoe actueel je Joomla ook is. Draai een PHP-versie die actief ondersteund wordt, en houd ook MariaDB/MySQL en de webserver bij. Als bonus zijn nieuwere PHP-versies meestal sneller.
Je hoeft die ondersteuningsdata niet te gokken. De officiele pagina met ondersteunde PHP-versies toont precies wanneer elke PHP-tak stopt met bugfixes en wanneer de periode van alleen-beveiligingsfixes eindigt. Voor de rest van de stack houdt endoflife.date dezelfde data bij voor MariaDB, MySQL en vrijwel elk ander onderdeel dat je draait. Zet de relevante data in je agenda en plan de upgrade voordat de ondersteuning stopt, niet nadat je host de overstap afdwingt.
2.4 Voordat je updatet
Updates zijn veel minder eng met een routine: maak een back-up, lees de release notes, update, en test de site. Beheer je een bedrijfskritische site, test de update dan eerst op een kopie van de site.
Naar boven3. Bescherm gebruikersaccounts
3.1 Sterke wachtwoordregels
Joomla laat je wachtwoordsterkte afdwingen voor alle gebruikers. Open Gebruikers → Beheren → Opties → Wachtwoordopties en stel in:
| Optie | Betekenis |
|---|---|
minimum_length |
Minimale wachtwoordlengte. Maak dit minstens 12. |
minimum_integers |
Minimaal aantal cijfers. |
minimum_symbols |
Minimaal aantal symbolen. |
minimum_uppercase / minimum_lowercase |
Minimaal aantal hoofdletters en kleine letters. |
Lengte wint van complexiteit: een lange wachtwoordzin is sterker en makkelijker te onthouden dan een korte cryptische reeks. Joomla slaat elk wachtwoord op als een gezouten bcrypt-hash, nooit als platte tekst, en vervangt oude hashes stilletjes door sterkere wanneer een gebruiker inlogt.
3.2 Multi-factor authenticatie
Zelfs een sterk wachtwoord kan lekken. Multi-factor authenticatie (MFA) vraagt om een tweede bewijs na het wachtwoord, en Joomla levert vijf methoden in de plugin-groep multifactorauth:
| Plugin | Tweede factor |
|---|---|
| Verificatiecode (TOTP) | Een 6-cijferige code uit een authenticator-app. |
| Passkeys (WebAuthn) | Een hardwaresleutel, vingerafdruk of passkey op je apparaat. De sterkste optie. |
| YubiKey | Een YubiKey hardware-token in OTP-modus. |
| Code per e-mail | Een eenmalige code per e-mail. Beter dan niets. |
| Vaste code | Een statische tweede code. Alleen om te testen, geen echte beveiliging. |
Gebruikers stellen hun methoden in op hun eigen profiel, en Joomla bewaart de aangemelde methoden in de tabel #__user_mfa. In Gebruikers → Beheren → Opties kun je MFA verplichten voor specifieke gebruikersgroepen; begin met elke groep die op de backend kan inloggen. Joomla vertraagt ook mislukte MFA-pogingen (de opties mfatrycount en mfatrytime), zodat een tweede factor niet ongemerkt gebruteforcet kan worden.
3.3 Super User-hygiene
- Houd het aantal Super Users zo klein mogelijk, het liefst een of twee.
- Gebruik een Super User-account nooit voor dagelijks redactiewerk. Gebruik daarvoor een Administrator- of Editor-account.
- Noem het account geen
admin, en hergebruik het wachtwoord nergens anders. - Geef iedereen een eigen account. Gedeelde accounts maken logs nutteloos en offboarding onmogelijk.
- Verwijder of blokkeer accounts van mensen die vertrokken zijn. Loop de gebruikerslijst een paar keer per jaar na.
3.4 Geef iedereen het minimum dat nodig is
Met de toegangsrechten van Joomla geef je een redacteur precies de rechten om artikelen te bewerken en niets meer. Wie geen extensies kan installeren, kan ook geen kwaadaardige extensie installeren, zelfs niet als het account gestolen wordt. Het principe heet least privilege: elk account krijgt de kleinste set rechten waarmee de persoon zijn werk nog kan doen.
Naar boven4. Belangrijke instellingen in de Algemene configuratie
4.1 Forceer HTTPS
Zet in Systeem → Algemene configuratie → Server de optie Forceer HTTPS (force_ssl) op Gehele site. Elk wachtwoord, elke sessiecookie en elk API-token reist dan versleuteld. Er is geen goede reden meer om ook maar een pagina over gewoon HTTP te serveren; certificaten zijn gratis met Let's Encrypt.
4.2 Verberg fouten in productie
Zet Foutrapportage (error_reporting) op Geen en houd Debug systeem (debug) uit op een live site. Foutmeldingen en debug-uitvoer onthullen bestandspaden, databasequery's en versiedetails, precies de verkenning die een aanvaller zoekt. Zet ze alleen aan terwijl je actief problemen onderzoekt, en daarna weer uit.
4.3 Sessies en cookies
| Instelling | Advies |
|---|---|
session_handler |
Houd Database aan, tenzij je een reden hebt (zoals Redis) om te wisselen. |
| Sessieduur | Zo kort als praktisch is. 15-30 minuten voor de backend is redelijk. |
session_metadata |
Aan laten: het voedt de "wie is online"-gegevens en laat je sessies zien die er niet horen te zijn. |
shared_session |
Uit laten, tenzij je echt een login voor site en administrator samen nodig hebt. Gescheiden sessies beperken schade. |
cookie_domain / cookie_path |
Leeg laten tenzij je zeker weet dat je ze nodig hebt; een verkeerde waarde kan cookies laten lekken naar buurdomeinen. |
4.4 Andere schakelaars om te kennen
- Site offline (
offline): gebruik het tijdens onderhoud, zodat half afgemaakte toestanden niet publiek zijn. De plugin Task - Site Status kan het inplannen. - Frontend bewerken (
frontediting): schakel het bewerken van modules en menu's vanaf de frontend uit als redacteuren het niet gebruiken. - Massamail (
massmailoff): schakel massamail uit als je het niet gebruikt; een gekaapte backend kan dan niet spammen vanaf jouw domein. - CAPTCHA (
captcha): schakel er een in voor registratie- en contactformulieren tegen bot-aanmeldingen en formulierspam.
4.5 De geheime sleutel
Je configuration.php bevat een waarde $secret die Joomla gebruikt voor token- en HMAC-berekeningen, bijvoorbeeld voor de API-tokens van de Web Services API. Behandel het hele bestand als een wachtwoord: plak het nooit in een forumbericht, een ticket of een publieke repository.
5. Server hardening
5.1 Activeer de meegeleverde regels
Joomla levert een kant-en-klare Apache-configuratie mee als htaccess.txt. Hernoem het naar .htaccess (toch al nodig voor SEF-URL's) en je krijgt meerdere beschermingen cadeau:
Options -Indexes: niemand kan door je mappen bladeren op zoek naar interessante bestanden.- Een
X-Content-Type-Options "nosniff"-header: browsers stoppen met het raden van bestandstypen, wat een klasse van content-smokkel-aanvallen blokkeert. - Een content security-regel voor geuploade SVG-bestanden, die anders scripts kunnen bevatten.
- Blokkeerregels die verzoeken met duidelijke aanvalspatronen in de URL weigeren voordat Joomla uberhaupt draait.
Op IIS is het equivalente bestand web.config.txt. Op nginx vertaal je de regels naar je server block, want nginx leest geen .htaccess-bestanden.
5.2 Extra bescherming voor de backend
De inlogpagina op /administrator is de meest aangevallen URL van elke Joomla-site. Bots bestoken hem de hele dag met wachtwoordpogingen. Populaire tegenmaatregelen, ongeveer op volgorde van moeite:
- Verplicht MFA voor alle backend-gebruikers (zie sectie 3). Dat maakt wachtwoord raden kansloos.
- Zet HTTP Basic-authenticatie of een IP-allowlist op de map
/administratorop serverniveau, zodat bots de Joomla-login nooit bereiken. - Gebruik een firewall of een fail2ban-achtig gereedschap op server- of hostingniveau om IP-adressen na herhaalde mislukkingen te blokkeren. Joomla core vergrendelt accounts niet na mislukte logins, dus rate limiting hoort in deze laag of in een beveiligingsextensie.
5.3 Kies je hosting bewust
Op goedkope shared hosting zonder goede scheiding kan een gecompromitteerde buursite soms bij jouw bestanden. Vraag je host hoe accounts van elkaar gescheiden zijn (bijvoorbeeld PHP-FPM-pools per gebruiker en open_basedir-restricties), of ze een web application firewall draaien, en hoe snel ze de stack patchen. Een paar euro per maand koopt hier veel veiligheid.
5.4 PHP hardening-instellingen
Een paar php.ini-instellingen sluiten deuren die Joomla zelf niet kan sluiten. Op managed hosting staan sommige al goed; op je eigen server stel je ze zelf in:
| Instelling | Aanbevolen | Waarom |
|---|---|---|
display_errors |
Off |
PHP-fouten op het scherm lekken paden en codedetails. Log ze in plaats daarvan (log_errors = On). |
expose_php |
Off |
Voorkomt dat PHP zijn versie in elke response-header aankondigt. |
allow_url_include |
Off |
Blokkeert het includen van externe bestanden, de klassieke remote-file-inclusion-aanval. |
open_basedir |
de paden van je site | Beperkt de bestandstoegang van PHP tot de eigen mappen van de site. |
disable_functions |
bijv. exec, shell_exec, system, passthru, proc_open, popen |
Verwijdert shell-functies die de meeste sites nooit nodig hebben, favoriet gereedschap van geuploade malware. |
Test de site na het wijzigen van open_basedir of disable_functions: een paar extensies gebruiken de strengere functies legitiem, en dat ontdek je liever op een testkopie dan in productie.
5.5 Database-account hardening
De databasegegevens in configuration.php verdienen dezelfde zorg als een Super User-account:
- Geef elke site een eigen database en een eigen databasegebruiker. Een gedeeld DB-account over sites heen betekent dat een gehackte site ze allemaal blootlegt.
- Geef die gebruiker alleen de rechten die Joomla nodig heeft op de eigen database - nooit globale rechten zoals
GRANT,SUPERofFILE, en geen toegang tot andere databases. - Gebruik een lang gegenereerd wachtwoord. Je typt het nooit; het staat alleen in
configuration.php. - Schakel externe databasetoegang uit tenzij je die echt nodig hebt. Een database die alleen op localhost luistert, kan niet vanaf het internet worden aangevallen.
5.6 Een web application firewall
Een web application firewall (WAF) inspecteert verzoeken voordat ze Joomla bereiken en blokkeert bekende aanvalspatronen: SQL-injectiepogingen, kwaadaardige uploads, agressieve bots. Gangbare opties zijn Cloudflare (als proxy voor je site, inclusief rate limiting en botbescherming) en ModSecurity met de OWASP Core Rule Set op je eigen Apache of nginx.
Een WAF is een ondersteunende laag, geen vervanging voor updates: hij kan een verse extensie-kwetsbaarheid "virtueel patchen" en je tijd kopen, maar de echte oplossing blijft de update installeren. Biedt je host een WAF, zet hem dan aan; draai je een eigen server, dan is ModSecurity plus de Core Rule Set het standaard startpunt.
Naar boven6. HTTP security headers
6.1 De ingebouwde HTTP Headers-plugin
Joomla levert een plugin System - HTTP Headers (plg_system_httpheaders) mee die moderne browser-beveiligingsheaders verstuurt zonder aan de serverconfiguratie te komen. Schakel hem in onder Systeem → Plugins en stel in:
| Header | Waartegen hij beschermt |
|---|---|
X-Frame-Options |
Clickjacking: andere sites kunnen jouw pagina's niet in een verborgen frame tonen. |
Strict-Transport-Security (HSTS) |
Protocol-downgrades: browsers weigeren je site ooit nog over gewoon HTTP te laden. Opties voor max-age, subdomeinen en preload. |
Referrer-Policy |
Het lekken van volledige URL's van jouw pagina's naar sites waarnaar je linkt. |
Cross-Origin-Opener-Policy |
Andere vensters die een scriptbare verwijzing naar jouw pagina's houden. |
Content-Security-Policy (CSP) |
Cross-site scripting: de browser voert alleen scripts uit die jij expliciet toestaat. |
6.2 Een Content Security Policy uitrollen
CSP is de krachtigste header en tegelijk degene waarmee je je site het makkelijkst breekt, omdat templates en extensies scripts van veel plekken laden. De plugin ondersteunt een veilig uitrolpad:
- Schakel CSP in in de modus Report-Only. De browser meldt overtredingen in de console maar blokkeert niets.
- Klik door de site en de backend, verzamel wat er zou breken, en voeg de benodigde directives toe.
- Schakel van report-only naar afdwingen zodra de console schoon blijft.
De plugin kan ook nonces en script-hashes genereren voor inline scripts, zodat je het gevaarlijke sleutelwoord unsafe-inline kunt vermijden. Test HSTS eerst met een korte max-age; de preload-optie is bijna onomkeerbaar, dus schakel die pas in als je zeker weet dat elk subdomein voor altijd HTTPS draait.
7. Bestanden, mappen en rechten
7.1 Verstandige bestandsrechten
Op een typische Linux-host horen bestanden 644 te zijn en mappen 755, in eigendom van het account waaronder PHP draait. Gebruik nooit 777; daarmee mag elk proces op de server in je bestanden schrijven. Als een extensie alleen met 777 werkt, vertelt die extensie je iets over zijn kwaliteit.
Je kunt een stap verder gaan en configuration.php alleen-lezen maken (444). Joomla vraagt om het te versoepelen wanneer je de Algemene configuratie opslaat, en daarna zet je het terug.
7.2 Geen restanten in de webroot
Oude back-ups (site-backup.zip), databasedumps (dump.sql), phpinfo-bestanden en vergeten testkopieen (/old/, /backup/) zijn cadeautjes voor aanvallers, die precies op deze namen scannen. Bewaar back-ups buiten de webroot, en verwijder wat je niet meer nodig hebt. De plugin Task - Check Files kan volgens schema op te grote bestanden scannen, wat ook verdwaalde archieven vangt.
7.3 Verplaats wat niet publiek hoort te zijn
Joomla laat je de mappen tmp en log verplaatsen via Pad naar de tijdelijke map en Pad naar de logmap in de Algemene configuratie. Wijs beide naar een plek buiten de webroot, zodat de inhoud nooit gedownload kan worden. Vooral logbestanden kunnen paden en gebruikersnamen lekken.
Sinds Joomla 5 kunnen nieuwe installaties verder gaan en de hele site serveren vanuit een aparte publieke map: alleen de toegangspunten en assets staan in de webroot (JPATH_PUBLIC), terwijl de applicatiecode, configuratie, logs en tijdelijke bestanden een niveau hoger staan, buiten bereik van de webserver. Begin je een nieuw project, overweeg deze indeling dan vanaf dag een.
7.4 Upload-instellingen
Houd in Inhoud → Media → Opties de lijst met toegestane extensies zo kort als je redactie nodig heeft. Wees voorzichtig met SVG-uploads: SVG is een XML-formaat dat scripts kan bevatten. Moet je het toch toestaan, dan bevat de meegeleverde .htaccess een regel die voorkomt dat geuploade SVG's scripts uitvoeren.
8. Verklein het aanvalsoppervlak
8.1 Verwijder wat je niet gebruikt
Elke geinstalleerde extensie is code die een kwetsbaarheid kan bevatten, zelfs als hij uitgeschakeld is. Ga naar Systeem → Beheren → Extensies en deinstalleer (niet alleen uitschakelen) extensies die je niet gebruikt. Minder extensies betekent ook snellere updates en minder conflicten.
8.2 Kies extensies als een scepticus
- Kies bij voorkeur extensies van ontwikkelaars die changelogs publiceren en op beveiligingsmeldingen reageren.
- Controleer de Vulnerable Extensions List (VEL) op de Joomla-website voor en na het installeren.
- Vermijd verlaten extensies: jaren geen update is een rode vlag, geen teken van stabiliteit.
- Installeer nooit nulled of illegale commerciele extensies. Ze zijn een bekend malwarekanaal.
8.3 Schakel ongebruikte toegangspunten uit
- Gebruik je de Web Services API niet, schakel dan de plugins in de groep
api-authenticationen de plugin-groep Web Services uit. - Gebruik je nooit HTTP Basic-authenticatie voor de API, houd die plugin dan uitgeschakeld en vertrouw op tokens (zie sectie 12).
- Schakel frontend-registratie uit (Gebruikers → Opties → Gebruikersregistratie toestaan) als de site geen bezoekersaccounts nodig heeft.
8.4 Over security by obscurity
Het hernoemen van de database-prefix, het verbergen van versienummers of het maskeren van de login-URL maakt het voor oppervlakkige scanners iets lastiger, maar houdt geen vastberaden aanvaller tegen. Doe deze dingen als ze je weinig moeite kosten, maar reken ze nooit als echte bescherming. Updates, MFA en least privilege doen het zware werk.
Naar boven9. Monitoring, logging en geplande taken
9.1 Actielogs: wie deed wat
De gebruikersactielog (com_actionlogs met de plugin System - User Actions Log) registreert backend-activiteit: logins, extensie-installaties, artikelbewerkingen, configuratiewijzigingen. Bekijk hem onder Gebruikers → Gebruikersactielog. Na een incident beantwoordt deze log de cruciale vraag "wat is er gebeurd, en met welk account?". De plugin Task - Delete Action Logs ruimt oude regels volgens schema op, zodat de tabel niet eindeloos groeit.
9.2 Log mislukte logins
De plugin System - Log schrijft mislukte inlogpogingen naar een logbestand (hij abonneert zich op het event onUserLoginFailure). Een plotselinge golf mislukkingen in dat bestand is je vroege waarschuwing voor een wachtwoord-raad-aanval. De plugin Task - Rotate Logs voorkomt dat logbestanden onbeperkt groeien.
9.3 Zet de taakplanner aan het werk
De taakplanner (com_scheduler) draait onderhoudstaken die je beveiliging stilletjes ondersteunen:
| Taak-plugin | Beveiligingswaarde |
|---|---|
updatenotification |
E-mailt je wanneer er een Joomla-update beschikbaar is. |
rotatelogs |
Roteert logbestanden. |
deleteactionlogs |
Ruimt de gebruikersactielog op. |
sessiongc |
Ruimt verlopen sessies op. |
checkfiles |
Vindt te grote bestanden, zoals vergeten archieven. |
globalcheckin |
Checkt items in die vergrendeld achterbleven door verdwenen gebruikers. |
Trigger de taakplanner betrouwbaar met een echte cronjob of de webcron-URL, niet alleen met backend-bezoeken.
9.4 Kijk ook van buitenaf
Vul de interne logs aan met een externe uptime-monitor en het liefst een periodieke malwarescan van de gerenderde site. Google Search Console waarschuwt je wanneer Google je site markeert; die waarschuwing hoort nooit het eerste moment te zijn waarop je van een hack hoort, maar sluit hem toch aan.
Naar boven10. Back-ups: je vangnet
10.1 Hardening omvat ook herstel
Geen enkele hardening neemt het risico volledig weg, dus een geteste back-up hoort bij beveiliging. Een goede back-uproutine volgt de 3-2-1-regel: drie kopieen van je data, op twee verschillende soorten opslag, waarvan een weg van de webserver. Een back-up die alleen op de gehackte server staat, wordt samen met de site versleuteld of verwijderd.
10.2 Wat een Joomla-back-up moet bevatten
- Alle bestanden, inclusief
configuration.php, templates en de mapimages. - Een dump van de complete database.
Gereedschappen zoals Akeeba Backup verpakken beide in een herstelbaar archief en kunnen het automatisch naar externe opslag sturen. Welk gereedschap je ook gebruikt: test een restore minstens een keer, op een aparte locatie. Een ongeteste back-up is een hoop, geen plan.
10.3 Back-ups na een incident
Bewaar meerdere generaties back-ups. Als een site al weken gecompromitteerd was voordat je het merkt, bevat de back-up van gisteren de backdoor ook, en ben je blij met een oudere, schone versie om mee te vergelijken.
10.4 Als het toch misgaat: incident response
Ontdek je een hack, weersta dan de neiging om meteen verdachte bestanden te gaan verwijderen. Werk vier fasen in volgorde af:
- Indammen: haal de site offline en vervang elk toegangsgegeven - Joomla-wachtwoorden, API-tokens, het databasewachtwoord, hosting-, FTP- en SSH-accounts. Ga ervan uit dat ze allemaal bekend zijn.
- Onderzoeken: gebruik de actielogs, de log van mislukte logins en de toegangslogs van de server om te achterhalen wanneer en hoe de aanvaller binnenkwam. Noteer de tijdstempels van gewijzigde bestanden.
- Opruimen: zet een back-up terug van voor de inbraak, of maak de bestanden schoon aan de hand van een verse Joomla-download en een schone extensieset. Update daarna alles, want het oorspronkelijke gat zit er meestal nog.
- Herstellen en leren: breng de site weer online, houd de logs een paar weken scherp in de gaten, en repareer de kernoorzaak - de verouderde extensie, het zwakke wachtwoord, de ontbrekende MFA.
De meest gemaakte fout is stap 2 overslaan: een site die wordt schoongemaakt zonder het toegangspunt te kennen, raakt meestal binnen dagen opnieuw besmet via dezelfde deur.
Naar boven11. Onder de motorkap (ontwikkelaarsblik)
11.1 Wat Joomla al beschermt
De Joomla core verdedigt tegen de klassieke webaanvallen, en weten hoe helpt je die bescherming intact te houden:
| Aanval | Verdediging in de core |
|---|---|
| SQL-injectie | De database-API met prepared statements en parameter binding. |
| Cross-site scripting (XSS) | Invoerfiltering (InputFilter), uitvoer-escaping en de CSP header-plugin. |
| Cross-site request forgery (CSRF) | Een formuliertoken per sessie, gecontroleerd bij elk verzoek dat iets wijzigt. |
| Wachtwoorddiefstal uit de database | Gezouten bcrypt-hashes; platte wachtwoorden worden nooit opgeslagen. |
| Timing-aanvallen op tokens | Vergelijkingen in constante tijd via Crypt::timingSafeCompare(). |
11.2 CSRF-tokens in je eigen code
Elk formulier dat data wijzigt heeft het token nodig. In de formulierlayout:
<?php echo Joomla\CMS\HTML\HTMLHelper::_('form.token'); ?>
En in de controller die het verzoek ontvangt:
$this->checkToken(); // throws on a missing or invalid token
Sla je dit over, dan kan elke willekeurige website jouw formulier versturen namens een ingelogde gebruiker.
11.3 Veilig query'en
Plak gebruikersinvoer nooit in SQL. Bind hem:
use Joomla\Database\ParameterType;
$query = $db->getQuery(true)
->select($db->quoteName('id'))
->from($db->quoteName('#__content'))
->where($db->quoteName('created_by') . ' = :userId')
->bind(':userId', $userId, ParameterType::INTEGER);
11.4 Escape bij uitvoer
Invoer filteren is niet genoeg; escape op het moment van uitvoer, in de layout:
<?php echo $this->escape($item->title); ?>
De vuistregel: filter invoer, escape uitvoer, en laat de databaselaag waarden quoten. Elke verdediging vangt gevallen op die de andere missen.
11.5 Controleer rechten, geen aannames
Controleer in componenten de autorisatie expliciet voordat je iets doet:
$user = $this->getUserFactory()->loadUserById($userId);
if (!$user->authorise('core.edit', 'com_example')) {
throw new \Exception(Text::_('JERROR_ALERTNOAUTHOR'), 403);
}
Een knop verbergen is cosmetica; de controle in de code is de beveiliging.
11.6 Waar de beveiligingsdata staat
| Tabel | Rol |
|---|---|
#__users |
Accounts, bcrypt-wachtwoordhashes, blokkeer- en activatievlaggen. |
#__user_mfa |
Aangemelde multi-factor authenticatiemethoden per gebruiker. |
#__action_logs |
De regels van de gebruikersactielog. |
#__session |
Actieve sessies (met de database-sessiehandler). |
#__extensions |
Welke extensies en plugins ingeschakeld zijn. |
12. De Web Services API beveiligen
12.1 Tokens, geen wachtwoorden
De Joomla API authenticeert met de plugin-groep api-authentication. Kies de Token-plugin boven Basic-authenticatie: een token kun je los intrekken, terwijl een gelekt Basic-wachtwoord het hele account compromitteert. Een typische aanroep:
curl -H "X-Joomla-Token: <token>" \
https://example.test/api/index.php/v1/users
12.2 Houd de token-kring klein
Standaard mogen alleen Super Users met een token authenticeren. De parameter allowedUserGroups van de plugin User - Joomla API Token verruimt dat; verruim zo min mogelijk, en maak voor elke integratie een aparte gebruiker met weinig rechten in plaats van een Super User-token uit te delen. Een API-gebruiker heeft exact dezelfde rechten als dezelfde gebruiker op de website, dus least privilege geldt ook hier.
12.3 Gebruik je de API niet?
Schakel de API- en Web Services-plugins dan helemaal uit. Een toegangspunt dat uit staat, kan niet worden aangevallen. Je zet ze weer aan op de dag dat je echt headless toegang nodig hebt.
Naar boven13. SEO en metadata
Beveiliging en SEO hangen sterker samen dan het lijkt. Een gehackte site is een SEO-ramp: zoekmachines herkennen geinjecteerde spamlinks, doorway-pagina's en malware snel, markeren de site met een waarschuwing, en posities waar je jaren aan bouwde verdwijnen in dagen. De blocklist-status daarna opruimen duurt veel langer dan de hack zelf.
De positieve kant: HTTPS is een bevestigd rankingsignaal, en de redirect naar HTTPS bundelt je URL's. Security headers zoals HSTS laten browsers je domein vertrouwen. En een bijgewerkte, snelle, stabiele site is precies waar zoekmachines bezoekers naartoe willen sturen. Elk uur dat je aan hardening besteedt, beschermt stilletjes ook je zoekverkeer.
Naar boven14. Veelvoorkomende fouten en valkuilen
14.1 "De site werkt, dus ik blijf eraf"
Symptoom: een site draait jaren zonder updates omdat iedereen bang is iets te breken.
Oplossing: hoe langer je wacht, hoe riskanter de uiteindelijke update wordt, en hoe langer bekende kwetsbaarheden open blijven. Update in kleine, frequente stappen met back-up, in plaats van een grote riskante sprong.
14.2 Debug-modus aan in productie
Symptoom: bezoekers zien databasequery's, bestandspaden of PHP-meldingen onderaan pagina's.
Oplossing: zet Debug systeem uit en zet Foutrapportage op Geen in de Algemene configuratie. Onderzoek fouten in de logbestanden.
14.3 Back-ups opgeslagen in de webroot
Symptoom: backup.zip of dump.sql is downloadbaar voor iedereen die de naam raadt, en geeft je hele site weg inclusief configuration.php.
Oplossing: bewaar back-ups buiten de webroot en buiten de server. Verwijder verdwaalde archieven nu; scanners zoeken er continu naar.
14.4 Iedereen is Super User
Symptoom: vijf mensen delen twee Super User-accounts, "omdat dat makkelijker is".
Oplossing: een account per persoon, minimale rechten per rol, MFA op elk backend-account. Logs worden betekenisvol en een gestolen redacteurswachtwoord betekent niet langer een gestolen site.
14.5 Extensies uitgeschakeld in plaats van verwijderd
Symptoom: de extensielijst staat vol uitgeschakelde restanten van experimenten van jaren geleden.
Oplossing: deinstalleer ze. Bestanden van uitgeschakelde extensies staan nog op de schijf en sommige blijven direct bereikbaar. Deinstalleren verwijdert de code en de update-zorgen.
14.6 Een CSP die de site ooit brak, dus hij blijft uit
Symptoom: iemand schakelde de Content-Security-Policy-header in, het template brak, en de hele HTTP Headers-plugin ging voorgoed uit.
Oplossing: schakel de plugin met de veilige headers (X-Frame-Options, Referrer-Policy, HSTS) meteen weer in, en rol CSP apart uit in report-only-modus tot de browserconsole schoon blijft.
Naar boven15. Best practices
Als je maar een paar dingen uit dit artikel onthoudt, onthoud dan deze:
- Update Joomla, extensies en PHP snel. Deze ene gewoonte voorkomt de meeste hacks.
- Verplicht MFA voor elk backend-account, en houd het aantal Super Users minimaal.
- Forceer HTTPS op de hele site, en schakel de HTTP Headers-plugin in.
- Deinstalleer ongebruikte extensies; check de Vulnerable Extensions List voordat je nieuwe kiest.
- Houd foutrapportage en debug-modus uit in productie.
- Bewaar back-ups extern volgens de 3-2-1-regel, en test een restore.
- Zet de gebruikersactielog en het loggen van mislukte logins aan, en lees ze ook echt.
- Laat de taakplanner de terugkerende klusjes doen: update-notificaties, logrotatie, sessie-opruiming.
- Ontwikkelaars: controleer CSRF-tokens, bind queryparameters, escape uitvoer, en controleer rechten in code.
16. In het kort
UPDATES Systeem > Update > Joomla / Extensies
Task - Update Notification plugin + taakplanner
Joomla 6 verifieert core-updates met TUF-ondertekening
ACCOUNTS Gebruikers > Beheren > Opties
wachtwoordregels: minimum_length 12+
MFA-plugins: TOTP, Passkeys, YubiKey, E-mail, Vast
MFA per groep verplicht; weinig Super Users; geen gedeelde accounts
CONFIG force_ssl Gehele site
error_reporting Geen debug Uit
sessieduur kort shared_session Uit
SERVER hernoem htaccess.txt > .htaccess (-Indexes, nosniff)
bestanden 644 / mappen 755, configuration.php 444
tmp- + log-mappen buiten de webroot
geen back-ups/dumps in de webroot
php.ini: display_errors Off, expose_php Off,
allow_url_include Off, open_basedir ingesteld
DB: eigen gebruiker per site, minimale rechten,
alleen localhost
WAF: Cloudflare of ModSecurity + OWASP Core Rule Set
HEADERS System - HTTP Headers plugin
X-Frame-Options, HSTS, Referrer-Policy, COOP
CSP: start Report-Only → repareer → afdwingen
MONITOR Gebruikers > Gebruikersactielog (com_actionlogs)
System - Log plugin (mislukte logins)
taakplanner: rotatelogs, deleteactionlogs, sessiongc
API kies Token boven Basic auth
smalle allowedUserGroups, aparte API-gebruikers
ongebruikt? schakel de API-plugins uit
DEV checkToken() op elk formulier
bind() parameters, escape() uitvoer
$user->authorise() voordat je iets doet
HERSTEL 3-2-1 back-ups, meerdere generaties, geteste restore
gehackt? indammen > onderzoeken > opruimen > herstellen
ruim nooit op zonder het toegangspunt te vinden
Naar boven17. Samenvatting
Een Joomla-site hardenen is geen heldendaad in een keer, maar een stapel verstandige gewoonten:
- Updates eerst: core (ondertekend met TUF, optioneel automatisch), extensies en PHP. Verouderde software veroorzaakt de meeste hacks.
- Accounts: sterke wachtwoordregels, multi-factor authenticatie met de ingebouwde plugins, weinig Super Users, least privilege voor iedereen.
- Configuratie: overal HTTPS, fouten en debug verborgen, korte sessies.
- Server: de meegeleverde
.htaccess-regels, verstandige rechten, geen restanten of back-ups in de webroot. - Headers: de HTTP Headers-plugin levert bescherming tegen clickjacking, plus HSTS en CSP, zonder aan de server te komen.
- Zichtbaarheid: actielogs, logs van mislukte logins, geplande onderhoudstaken en externe monitoring.
- Herstel: externe, geteste back-ups in meerdere generaties voor de dag dat er toch iets misgaat.
- Code: de Joomla core verdedigt tegen SQL-injectie, XSS en CSRF; ontwikkelaars houden die belofte in stand met tokens, gebonden parameters en uitvoer-escaping.
Geen van deze stappen is op zichzelf moeilijk. Samen veranderen ze je site van een makkelijk doelwit in een die aanvallers overslaan voor zachtere prooi.
Weet je niet zeker waar je site vandaag staat, dan is een gestructureerde security review de logische eerste stap: controleer de versies, de accounts, de instellingen en de logs in precies de volgorde van dit artikel. Zo'n methodische audit is exact het werk dat een Joomla-specialist regelmatig doet, en die vindt meestal de twee of drie deuren die ertoe doen voordat iemand anders dat doet.
Naar boven

Peter is Joomla specialist en Linux admin voor snelle, veilige en schaalbare websites.












