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.