In deze blogpost gaan we dieper in op een aantal veelvoorkomende Laravel beveiligingsfouten die ik ben tegengekomen in projecten, persoonlijk heb gemaakt of zelfs ben tegengekomen op door Stack Overflow goedgekeurde antwoorden. We zullen het kort hebben over bestandsvalidatie, massatoewijzing en Laravel's query builder. Het doel van deze blog is om te laten zien hoe kleine, gemakkelijk te vermijden fouten een grote impact kunnen hebben op de beveiliging van je applicatie. En hopelijk om te voorkomen dat je ze in de toekomst maakt. Dus laten we beginnen!

Bestand valideren

Laravel biedt een robuust en veilig bestandssysteem waarmee ontwikkelaars bestanden kunnen opslaan en ophalen uit lokale of cloud-opslag. Hieronder staat wat code, rechtstreeks van Stackoverflow, om het uploaden van een avatar naar een profiel af te handelen:

Kun je zien hoe een aanvaller misbruik zou kunnen maken van het volgende fragment?

public function storeImage(Request $request)
{
	$request->validate([
		'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
	]);

	$imageName = Str::random(16) . '.' . $request->image->getClientOriginalExtension();

	Storage::disk('public')->putFileAs("avatars", $request->image, $imageName);

	return back()->with('success','You have successfully uploaded your avatar!');
}

Stel, een aanvaller wil een .html bestand met een XSS (Cross-site scripting) payload uploaden naar je server. Je zou verwachten dat Laravel's server-side validatie image en mimes:jpeg,png,jpg,gif,svg dit zou oplossen.

Sidenote: Dit is geen bug in Laravel, maar gewoon hoe mime type controle werkt.

De cruciale fout die wordt gemaakt is het gebruik van Laravel's getClientOriginalExtension methode om de extensie van het bestand direct uit het verzoek te halen. In plaats daarvan willen we in dit scenario gebruik maken van:

$request->image->extension();

Dit zal het mime type van het bestand raden op basis van de inhoud van het daadwerkelijke bestand in plaats van wat wordt ontvangen van de client.

Een andere veilige manier om hiermee om te gaan is door Laravel's put methode te gebruiken om bestanden op te slaan:

Storage::disk('public')->put(Str::random(16), $request->image);

Dit zal automatisch je bestandsnaam vervangen door een willekeurige hash en de juiste extensie toevoegen.
De belangrijkste afleiding hier is om nooit te vertrouwen op gebruikersinvoer, vooral als het gaat om het uploaden van bestanden.

 

 

A registration form for a user

Massa toewijzing

Kun jij het beveiligingslek in deze code vinden?

Gebruikersmodel

class User extends Model {

    protected $fillable = ['username', 'email', 'password', 'role'];

}

Registercontroller

class RegisterController
{
  public function create(Request $request) 
  {
    $request->validate([
      'username' => 'required|string',
      'email' => 'required|email|unique:users',
      'password' => 'required|string|min:12|confirmed',
    ]);

    $user = new User();
    $user->role = 'guest'
    $user->fill($request->all());
    $user->save();

    return response()->json(['success' => true],201);
  }
}

Als een kwaadwillende gebruiker het registratieverzoek vervalst en "rol": "admin" toevoegt aan de payload van het formulier. Laravel zou deze gebruiker graag toegang geven tot je hele systeem.

Dit komt doordat $request→all() niet alleen gevalideerde gegevens uit het verzoek haalt, maar ALLE gegevens. In combinatie met de rol die is toegevoegd aan de $fillable property van het model, zou de gebruiker worden aangemaakt met de rol "admin".

Voorkom dit door $request→validated() te gebruiken om alleen gevalideerde invoer op te halen uit je request. Of zorg ervoor dat je invulbare eigenschappen correct zijn ingesteld.

Bonuspunten als je hebt gezien dat het wachtwoord in platte tekst wordt opgeslagen ;)

Query builder parameterbinding

SQL-injectie is een veel voorkomende aanvalsvector voor webtoepassingen, en Laravel is daarop geen uitzondering. Het treedt op wanneer een aanvaller kwaadaardige SQL-code kan invoeren in de invoervelden of query-strings van een webtoepassing.

Hier is een voorbeeld van SQL-injectie met behulp van de query builder van Laravel:

//User input
$search = "1; DROP TABLE users;";

DB::table('users')->whereRaw("name = " . $search)->get();

Deze code is kwetsbaar voor SQL-injectie omdat de aanvaller willekeurige SQL-code kan uitvoeren door de variabele $search in te stellen op een tekenreeks die SQL-opdrachten bevat. In dit geval kan de aanvaller de hele tabel users verwijderen door $search in te stellen op "1; DROP TABLE users;".

Om SQL injectie aanvallen te voorkomen, moet je altijd gebruik maken van Laravel's query builder of parameter binding bij het construeren van SQL queries.

Voorbeeld van parameter binding:

$search = "1; DROP TABLE users;";

DB::table('users')->whereRaw("name = ?", $search)->get();

Conclusie

Hoewel de bovenstaande voorbeelden voor sommigen voor de hand liggend kunnen zijn, hoop ik dat dit artikel het belang illustreert van een goed begrip van de innerlijke werking van een framework, zelfs als het naadloos lijkt om te gaan met beveiliging. Ondanks Laravel's beginnersvriendelijke aard en geminimaliseerde overhead voor ontwikkelaars, vergeet niet om voorzichtig te blijven en zelfgenoegzaamheid te vermijden.

Op zoek naar Laravel-experts?

Auteur: Robbe Reygel
PHP developer

More insights

Cross-platform applicaties met React Native

Nog nooit was het ontwikkelen van native mobiele applicaties zo toegankelijk als vandaag. Bij Codana doen we dit door gebruik te maken het React Native, een open-source framework dat werd ontwikkeld door Meta.

Auteur: Jinse Camps
Architect | Analyst
Jinse Camps
dev

Laracon EU 2024

Een fantastisch leerrijke ervaring om met een hoop Laravel gepassioneerde mensen te inspireren! Iets wat niet gemist kan worden en heel veel voeling geeft met de community. Wat een top evenement! Wie zien we volgende edities? 😮

Auteur: Noah Gillard
PHP / Laravel Developer
Noah Gillard AI generated Face
laracon codana persoon

Een efficiënt datamanagementsysteem voor toerisme

Een TDMS of Tourist Data Management System, is simpelweg een platform dat data uit verschillende bronnen ophaalt, intern al dan niet automatisch verwerkt en deze gegevens terug aanbiedt aan externe platformen.

Auteur: Tom Van den Eynden
Web Architect | Coordinator
Tom Van den Eynden
laptop

Systemen voor gegevensbeheer in toerisme

In dit artikel verkennen we wat een TDMS is, waarom het essentieel is voor de toerisme-industrie, en hoe technologieën zoals Laravel en ElasticSearch het verschil kunnen maken. 

Auteur: Tom Van den Eynden
Web Architect | Coordinator
Tom Van den Eynden
tdms

Test Driven Development - toepassing op een project

TDD, of voluit Test Driven Development, is een aanpak van ontwikkeling waarbij we vertrekken van het schrijven van tests. 

Auteur: Sarah Jehin
PHP developer
Sarah Jehin
development

De OSLO-standaard: hoe gestandaardiseerde gegevensuitwisseling ons verder brengt

De OSLO-standaard is een term die je misschien wel eens hebt horen vallen in de context van gegevensuitwisseling en digitale transformatie, maar wat houdt het precies in en wat zijn de voordelen ervan?

Auteur: Benjamin Verhaegen
PHP Developer
benjamin_verhaegen
shaking_hands_black_white