Lab 04: OWASP A04 — Insecure Design

Objective

Exploit business logic vulnerabilities on a live server from Kali Linux: brute-force a login with no rate limiting, exploit a race condition to redeem a single-use coupon 8 times simultaneously, commit refund fraud by controlling the refund amount client-side, predict and forge a timestamp-based password reset token, and skip the payment step in a checkout workflow entirely.

Background

Insecure Design is OWASP #4 (2021) — vulnerabilities baked into the application's architecture before a line of code is written. No patch fixes these; they require redesign. Race conditions exploiting time-of-check to time-of-use (TOCTOU) gaps have stolen millions from financial apps. In 2022, a DeFi protocol lost $182M to a flash loan race condition. Predictable reset tokens have been used to take over accounts at Twitter, GitHub, and major banks.

Architecture

┌─────────────────────┐        Docker Network: lab-a04         ┌─────────────────────┐
│   KALI ATTACKER     │ ─────── HTTP attacks ─────────────▶   │   VICTIM SERVER     │
│  innozverse-kali    │                                         │  innozverse-cybersec│
│  curl, hydra,       │ ◀────── responses ───────────────────  │  Flask API :5000    │
│  python3 threads    │                                         │  (race, logic bugs) │
└─────────────────────┘                                         └─────────────────────┘

Time

45 minutes

Prerequisites

  • Lab 01 completed (two-container setup)

Tools

  • Victim: zchencow/innozverse-cybersec:latest

  • Attacker: zchencow/innozverse-kali:latest (curl, hydra, python3)


Lab Instructions

Step 1: Environment Setup — Launch Victim Server

📸 Verified Output:


Step 2: Launch Kali Attacker

Inside Kali:


Step 3: Brute-Force Login — No Rate Limiting

📸 Verified Output:

💡 No rate limiting means an attacker can try thousands of passwords per second. rockyou.txt has 14 million entries — against an unprotected endpoint, it completes in minutes. Defence: max 5 attempts per 15 minutes per IP + username, exponential backoff, CAPTCHA after 3 failures, and account lockout notifications.


Step 4: Race Condition — Coupon Redeemed 8× Simultaneously

📸 Verified Output:

💡 The race window exists between the check and the update. Thread 1 reads uses=0 < max_uses=1 ✓, then sleeps 50ms (DB latency). Threads 2–8 also read uses=0 before Thread 1's update commits. All 8 pass the check. The fix: UPDATE coupons SET uses=uses+1 WHERE code=? AND uses < max_uses — the WHERE clause makes the check and update atomic in the database.


Step 5: Refund Fraud — Client-Controlled Amount

📸 Verified Output:


Step 6: Predict Password Reset Token

📸 Verified Output:


Step 7: Skip Payment in Checkout Workflow

📸 Verified Output:

💡 Multi-step workflows must enforce step order server-side. The client says "I've paid" by skipping the payment URL — the server must verify payment actually occurred via an authoritative record (e.g., a payment gateway reference ID stored in the session). Never trust client-supplied state about workflow progress.


Step 8: Cleanup

On your host:


Remediation

Vulnerability
Root Cause
Fix

No brute-force protection

No rate limiting on login

Max 5 attempts/15min per IP + username; lockout + notify

Race condition (coupon)

Check-then-act with DB latency gap

Atomic SQL: UPDATE ... WHERE uses < max_uses — check rows affected

Client-controlled refund

Server uses client-supplied amount

Server fetches order amount from DB; never trust client

Double refund

No refunded flag checked

Add refunded BOOLEAN column; check before processing

Predictable reset token

MD5(username+timestamp) — 8 chars

secrets.token_urlsafe(32) — 256-bit CSPRNG, 15-min expiry

Workflow skipping

No server-side state machine

Store step completion in server session; verify each step before allowing next

Summary

Attack
Tool
Result

Login brute-force

hydra + curl

Cracked alice's password from wordlist

Race condition

python3 threads

8 simultaneous coupon redemptions (limit was 1)

Refund fraud

curl

Claimed $5000 on a $49.99 order

Token prediction

python3

Forged reset token via timestamp brute-force in <10 tries

Workflow skip

curl

Got order confirmed without payment step

Further Reading

Last updated