iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Exercises

Six exercises that walk through real OWASP Top 10 bugs and their minimum fixes. Try each before peeking; the answer is the exact line you would write in a PR.

Six OWASP exercises with fixes

EXAMPLE
# ============================================================
# Drill 1 — A01 Broken Access Control
# ============================================================
# VULNERABLE
# Route::get('/orders/{id}', fn($id) => Order::find($id));
#
# TASK: scope the lookup to the authenticated user.
# SOLUTION
# Route::get('/orders/{id}', fn(Request $r, $id) =>
#     $r->user()->orders()->findOrFail($id)
# )->middleware('auth');

# ============================================================
# Drill 2 — A02 Cryptographic Failures
# ============================================================
# VULNERABLE (PHP)
# $hash = sha1($password . $salt);
#
# TASK: replace with a real password hasher.
# SOLUTION
# $hash = password_hash($password, PASSWORD_ARGON2ID);
# // verify
# if (!password_verify($password, $hash)) abort(401);

# ============================================================
# Drill 3 — A03 Injection
# ============================================================
# VULNERABLE (Node, pg)
# const sql = \`SELECT * FROM users WHERE email = '${req.query.email}'\`;
# const r   = await pool.query(sql);
#
# TASK: parameterise.
# SOLUTION
# const r = await pool.query(
#     'SELECT id, name FROM users WHERE email = $1',
#     [req.query.email],
# );

# ============================================================
# Drill 4 — A05 Security Misconfiguration
# ============================================================
# VULNERABLE
# In .env on production: APP_DEBUG=true
#
# TASK: ship a CI check that fails when prod config exposes debug mode.
# SOLUTION (bash)
# # scripts/check-prod-config.sh
# if grep -E '^(APP_DEBUG|DEBUG)=true' .env.production; then
#   echo 'debug mode is on in production config' >&2; exit 1
# fi
# # In CI:
# # - name: prod config sanity; run: bash scripts/check-prod-config.sh

# ============================================================
# Drill 5 — A07 Authentication
# ============================================================
# VULNERABLE
# Login does not rotate session id after password change.
#
# TASK: regenerate the session on every auth event.
# SOLUTION (Laravel)
# public function changePassword(Request $r) {
#     $user = $r->user();
#     $user->update(['password' => Hash::make($r->password)]);
#     $r->session()->regenerate();             # new session id
#     auth()->logoutOtherDevices($r->password);  # forces others off
#     return back();
# }

# ============================================================
# Drill 6 — A10 SSRF
# ============================================================
# VULNERABLE
# $pdf = file_get_contents($_GET['url']);  // server-side fetch of user-supplied URL
#
# TASK: validate scheme + block private ranges.
# SOLUTION
# function safe_fetch(string $url): string {
#     $parts = parse_url($url);
#     if (($parts['scheme'] ?? '') !== 'https') abort(400);
#     $host = $parts['host'] ?? '';
#     $ip = gethostbyname($host);
#     if (filter_var($ip, FILTER_VALIDATE_IP,
#                    FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false)
#         abort(400, 'private range');
#     return file_get_contents($url);
# }
# Also: enable IMDSv2 on EC2 so SSRF cannot read instance creds.

# ============================================================
# Bonus — the WORST 'fix' to ship
# ============================================================
# - Telling the user to 'just be more careful'
# - Hiding the vulnerable endpoint behind 'security through obscurity'
# - Stripping characters with regex instead of parameterising
# - Lowering the severity to 'wont fix' because exploitation is 'hard'

# ============================================================
# Scoring
# ============================================================
# 6 / 6 -> ready for security code review
# 4 / 6 -> revisit owasp/cheatsheet
# < 6   -> a focused half-day with OWASP cheat sheet series

Why it matters

Every Top 10 fix should be expressible as a unit test on the route. The moment your test suite says "POST /orders/123 returns 403 when /123 belongs to another user", you have permanent protection against that specific bug class — and CI gates the next refactor against re-introducing it.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// Fill in: pick the #1 OWASP 2021 risk → "____ Access Control"
Try it Yourself »

Discussion

Loading…