Web Security
Beginner
2 min read
OWASP Top 10 2021: A01–A04 with Examples
Example
<?php
// A01: Broken Access Control — IDOR example and fix
// VULNERABLE: uses user-supplied ID directly without ownership check
// GET /api/invoices/4729
public function showInvoice(int $invoiceId): JsonResponse
{
// BAD: Any authenticated user can read any invoice by guessing the ID
$invoice = Invoice::findOrFail($invoiceId);
return response()->json($invoice);
}
// SECURE: enforce ownership (or RBAC) on every object access
public function showInvoice(int $invoiceId): JsonResponse
{
$invoice = Invoice::where('id', $invoiceId)
->where('user_id', auth()->id()) // ownership check
->firstOrFail(); // 404 if not owned
return response()->json($invoice);
}
// A03: Injection — command injection and fix
// VULNERABLE: unsanitised user input passed to shell
public function convertImage(string $filename): void
{
// BAD: attacker sends filename = "img.jpg; rm -rf /var"
exec("convert uploads/{$filename} output/{$filename}.png");
}
// SECURE: use escapeshellarg() and restrict characters
public function convertImage(string $filename): void
{
if (!preg_match('/^[\w\-]+\.(jpg|png|gif)$/i', $filename)) {
throw new \InvalidArgumentException('Invalid filename');
}
$safeFilename = escapeshellarg("uploads/{$filename}");
$safeOutput = escapeshellarg("output/{$filename}.png");
exec("convert {$safeFilename} {$safeOutput}");
}
// A04: Insecure Design — missing rate limit on password reset
// SECURE: throttle password reset requests to prevent enumeration + abuse
// Route::post('/password/reset')->middleware('throttle:5,1');
Related Resources
Web Security Reference
Complete tag & property list
Web Security How-To Guides
Step-by-step practical guides
Web Security Exercises
Practice what you've learned
More in Web Security