OWASP Top 10 in Laravel: wat het framework regelt en wat jij doet
Terug naar blog

OWASP Top 10 in Laravel: wat het framework regelt en wat jij doet

Bijgewerkt 8 min leestijd

Laravel neemt je veel beveiligingswerk uit handen. Niet alles. De OWASP Top 10:2025 laat per risico zien waar het framework stopt en jouw code begint.

Laravel neemt je veel beveiligingswerk uit handen. Niet alles. De OWASP Top 10:2025 laat per risico zien waar het framework stopt en jouw code begint.

Hieronder lopen we de tien categorieën langs. Per categorie: wat Laravel standaard doet, en waar developers het in de praktijk misdoen. Voor de volledige context van OWASP zie /security/owasp.

A01: Broken Access Control (inclusief SSRF)

Dit is de nummer één, en in Laravel-projecten ook de meest voorkomende fout. Laravel geeft je gates en policies. Het dwingt ze niet af.

Wat het framework biedt:

  • Policies per model, gekoppeld aan authorize() en can-middleware
  • Gates voor losse acties
  • Route model binding

Waar het misgaat:

  • Een controller haalt Order::find($id) op zonder te checken of de order van de ingelogde gebruiker is.
  • Een route is wel beveiligd met auth, maar niet met een policy. Ingelogd is niet hetzelfde als bevoegd.
  • Een nieuwe API-route vergeet de middleware.
php
// Fout: elke ingelogde gebruiker kan elke order openen
$order = Order::findOrFail($id);

// Beter: de policy beslist
$order = Order::findOrFail($id);
$this->authorize('view', $order);

SSRF zit sinds de laatste editie in deze categorie. Doet je app requests naar een URL die een gebruiker aanlevert (webhook, afbeelding importeren, preview)? Dan kan een aanvaller je server naar interne adressen laten praten. Valideer hosts tegen een allowlist en blokkeer interne IP-bereiken.

Test hierop. Schrijf per policy een test die bewijst dat gebruiker A niet bij de data van gebruiker B kan.

A02: Security Misconfiguration

Hier gaat het vaak mis door haast. Laravel heeft goede defaults, maar de configuratie in productie is van jou.

De bekendste fout: APP_DEBUG=true op een live omgeving. Dan toont Laravel bij een fout een uitgebreide foutpagina. Die kan je configuratiewaarden, paden en soms credentials laten zien.

Controleer in productie:

  • APP_DEBUG=false
  • APP_ENV=production
  • Een gegenereerde, geheime APP_KEY
  • Het .env-bestand niet bereikbaar via de webserver (document root is public/)
  • Geen debugtools zoals Telescope of Debugbar open voor iedereen
nginx
root /home/app/current/public;

Wijst je root naar de projectmap in plaats van public/, dan staat je .env mogelijk gewoon online. Dat zien we vaker dan je zou denken. Vermijd het door de webroot strikt op public te zetten en dat te testen.

Een kort overzicht staat in onze Laravel security checklist.

A03: Software Supply Chain Failures

Nieuw in de 2025-lijst. Je Laravel-app bestaat grotendeels uit code van anderen: Composer-pakketten, NPM-pakketten, eventueel een Docker-image.

Wat helpt:

  • composer audit in CI, met een falende build bij bekende kwetsbaarheden
  • Het composer.lock-bestand committen en uitrollen
  • Weinig, goed onderhouden pakketten in plaats van veel
  • Pakketten die niet meer onderhouden worden vervangen

Waar het misgaat: pakketten die jaren niet zijn bijgewerkt, en frameworks waar je achterloopt. Een voorbeeld uit de praktijk: de kwetsbaarheid CVE-2025-54068 in Livewire v3 raakte ook Filament-apps. Lees Livewire en Filament updates voor het volledige verhaal.

Hetzelfde patroon zie je in Magento, zie extensies en supply chain-risico.

A04: Cryptographic Failures

Laravel doet veel goed. Je hoeft zelf geen cryptografie te bouwen, en dat is precies de bedoeling.

Wat het framework regelt:

  • Hash::make() gebruikt standaard bcrypt of Argon2 voor wachtwoorden
  • Crypt::encryptString() versleutelt met je APP_KEY
  • Het encrypted-cast voor Eloquent-attributen
  • HTTPS-afdwinging via middleware of de webserver

Waar het misgaat:

  • Wachtwoorden of tokens zelf hashen met md5 of sha1
  • Gevoelige velden (bijvoorbeeld BSN, IBAN, API-sleutels van klanten) leesbaar in de database
  • APP_KEY in git of gedeeld tussen omgevingen
  • Geen HTTPS op een interne of staging-omgeving met echte data

Let op bij het wijzigen van APP_KEY. Versleutelde data en sessies zijn daarna niet meer te lezen. Plan dat dus bewust.

A05: Injection

Eloquent en de query builder gebruiken parameter bindings. SQL-injectie via de gewone methoden is daarmee grotendeels afgedekt. Blade escapet uitvoer standaard met {{ }}.

Het gaat mis bij omwegen:

php
// Kwetsbaar
DB::select("SELECT * FROM users WHERE email = '$email'");

// Veilig
DB::select('SELECT * FROM users WHERE email = ?', [$email]);

Let op deze plekken:

  • DB::raw(), whereRaw(), orderByRaw() met gebruikersinvoer
  • orderBy($request->input('sort')) zonder allowlist op kolomnamen
  • {!! $content !!} in Blade met data die niet van jou komt
  • Shell-commando's met gebruikersinvoer (exec, shell_exec)

Voor XSS geldt: gebruik {{ }} tenzij je zeker weet dat de HTML veilig is. Moet je HTML van gebruikers tonen, gebruik dan een bewezen sanitizer en geen eigen regex.

A06: Insecure Design

Dit is geen codefout maar een ontwerpfout. Een feature werkt prima en is toch onveilig, omdat niemand over misbruik nadacht.

Voorbeelden:

  • Een wachtwoord-reset die onbeperkt pogingen toestaat
  • Een kortingscode-endpoint zonder limiet, waarmee je codes kunt raden
  • Een export die alle klanten teruggeeft zonder logging
  • Een gebruikersrol die zichzelf kan upgraden

Laravel helpt met de rate limiter, maar je moet bepalen waar die nodig is. Stel bij elke nieuwe feature één vraag: hoe misbruikt iemand dit?

Een korte sessie met het team voor je bouwt, levert meer op dan een audit achteraf. Meer over testen op dit soort fouten: /security/pentest.

A07: Authentication Failures

Laravel biedt met Breeze, Jetstream, Fortify en Sanctum degelijke bouwstenen. Wachtwoorden worden gehasht, sessies worden geregenereerd bij login en er is login-throttling.

Waar het misgaat:

  • Eigen login-logica geschreven, met fouten
  • Geen rate limiting op login en wachtwoord-reset
  • Geen 2FA voor beheerders
  • Lange levensduur van API-tokens, zonder intrekken
  • Verschillende foutmeldingen voor "gebruiker bestaat niet" en "wachtwoord fout", waardoor je bestaande accounts verraadt

Gebruik waar mogelijk wat het framework levert, en schrijf geen eigen authenticatie als het niet hoeft. Zet 2FA aan voor alle beheerdersaccounts, ook in je Filament-panel.

php
RateLimiter::for('login', function (Request $request) {
    return Limit::perMinute(5)->by($request->ip() . '|' . $request->input('email'));
});

A08: Software or Data Integrity Failures

Hier gaat het om vertrouwen in code en data zonder dat je de integriteit controleert.

In Laravel kom je dit tegen bij:

  • Deserialisatie van data die niet vertrouwd is (unserialize op invoer)
  • Webhooks die je accepteert zonder de handtekening te controleren
  • CI/CD-pipelines waarin iedereen kan deployen
  • Updates of plug-ins die zonder controle worden binnengehaald

Controleer bij elke webhook van een betaalprovider of externe dienst de signature. Accepteer de payload niet op basis van alleen een URL die "niemand kent".

php
// Controleer de handtekening voordat je de payload verwerkt
abort_unless(hash_equals($expected, $received), 403);

Gebruik hash_equals voor vergelijkingen van geheimen. Het voorkomt timing-aanvallen.

A09: Security Logging & Alerting Failures

Zonder logging merk je een inbraak pas als de klant belt. En dat is meestal te laat.

Laravel logt via Monolog en kan naar bestanden, syslog of externe diensten. Het framework weet alleen niet wat voor jou belangrijk is.

Log in elk geval:

  • Mislukte en geslaagde logins van beheerders
  • Wijzigingen in rollen en rechten
  • Exports en bulkacties
  • Geweigerde autorisaties (403's)

Log geen wachtwoorden, tokens of volledige betaalgegevens. Zorg verder dat iemand naar de logs kijkt, of dat een alert afgaat. Een log die niemand leest is een archief, geen bewaking.

Voor het grotere plaatje: incident response en monitoring.

A10: Mishandling of Exceptional Conditions

Ook nieuw. Het gaat om hoe je app omgaat met fouten en onverwachte situaties.

Voorbeelden uit Laravel-apps:

  • Een try/catch die de fout negeert, waardoor een betaling als geslaagd geldt terwijl hij faalde
  • Een uitzondering die gevoelige gegevens in de response lekt
  • Een externe API die uitvalt, waarna je code "fail open" werkt en toegang geeft
  • Queue-jobs die stil mislukken zonder melding

Houd deze regel aan: bij twijfel weiger je toegang, niet verleen je die. Een mislukte autorisatiecheck mag nooit leiden tot "dan laten we het maar toe".

Zorg dat failed_jobs bewaakt wordt en dat onverwachte fouten een melding geven. Toon gebruikers een nette foutpagina, en bewaar details in je logs.

Overzicht

OWASP 2025Laravel regeltJij doet
A01 Access ControlGates, policiesPolicies afdwingen, SSRF-checks
A02 MisconfigurationGoede defaultsAPP_DEBUG=false, webroot public/
A03 Supply ChainComposercomposer audit, updates
A04 CryptographicHash, CryptGeen eigen crypto, sleutelbeheer
A05 InjectionBindings, Blade-escapingRaw queries vermijden
A06 Insecure DesignRate limiterMisbruik doordenken
A07 AuthenticationBreeze, Fortify, Sanctum2FA, throttling
A08 IntegritySigned URLsWebhook-signatures
A09 LoggingMonologWat loggen, wie kijkt
A10 Exceptional ConditionsException handlerFail closed

Waar begin je?

Heb je een bestaande Laravel-app en weinig tijd? Begin met deze volgorde:

  1. Controleer APP_DEBUG, webroot en .env-toegang.
  2. Draai composer audit en update wat openstaat.
  3. Loop alle routes na op ontbrekende autorisatie.
  4. Zoek naar DB::raw, whereRaw en {!! !!}.
  5. Zet rate limiting en 2FA aan op login en beheer.

Dat zijn vijf uur werk dat meer risico wegneemt dan een los pentest zonder opvolging. Voor een diepere controle kijken we ook naar /security/audit.

Veelgestelde vragen

Is Laravel standaard veilig?

Grotendeels voor de basis: SQL-bindings, CSRF-bescherming, hashing en output-escaping zijn ingebouwd. Autorisatie, configuratie in productie, updates en logging blijven jouw verantwoordelijkheid.

Wat is de meest gemaakte fout in Laravel-apps?

Ontbrekende autorisatie. Een route is ingelogd-only, maar controleert niet of de gebruiker bij dat specifieke record mag. Dat is precies A01 Broken Access Control.

Moet ik mass assignment nog fixen?

Ja. Gebruik $fillable of $guarded bewust, en geef nooit $request->all() zonder validatie aan create() of update(). Gebruik $request->validated() of een form request.

Wat is er nieuw in de OWASP Top 10:2025?

Twee nieuwe categorieën: A03 Software Supply Chain Failures en A10 Mishandling of Exceptional Conditions. SSRF zit nu onder A01 Broken Access Control.

Hoe vaak moet ik een Laravel-app laten testen?

Bij grote wijzigingen en daarnaast periodiek, bijvoorbeeld jaarlijks voor een app met klantdata of betalingen. Een pentest zonder opvolging heeft weinig waarde, plan dus ook tijd om bevindingen te herstellen.

Wil je weten waar jouw Laravel-applicatie staat ten opzichte van deze lijst? Wij kijken mee, zeggen eerlijk wat nodig is, en geven je een concreet lijstje. Zie /security/laravel en /laravel, of stuur ons een bericht via /contact.

Ruthger Idema

Geschreven door Ruthger Idema

15+ jaar ervaring in e-commerce development. Gespecialiseerd in Magento, Shopify en Laravel maatwerk.

Meer over ons team →
Deel dit artikel:

Wil je jouw e-commerce naar het volgende niveau?

Plan een vrijblijvend gesprek met onze experts over Magento, Shopify of Laravel maatwerk.

Plan een Tech Check