Lab 07: OWASP A07 — Authentication Failures

Objective

Exploit authentication weaknesses on a live server from Kali Linux: enumerate valid usernames through different error messages, brute-force a login with no rate limiting, demonstrate a weak 32-bit session token vulnerability, crack SHA-256 and MD5 password hashes with hashcat, and show how credential stuffing works at scale — then implement bcrypt-based hardened auth.

Background

Authentication Failures is OWASP #7 (2021). The 2019 Capital One breach (100M records) used a misconfigured IAM role. Credential stuffing — using leaked passwords from one breach to attack another service — succeeds because 65% of users reuse passwords. The National Institute of Standards and Technology (NIST SP 800-63B) specifically requires: no knowledge-based questions, bcrypt/Argon2 password hashing, rate limiting on login, and session tokens with ≥128 bits of entropy. Most breaches exploit at least one of these gaps.

Architecture

┌─────────────────────┐        Docker Network: lab-a07         ┌─────────────────────┐
│   KALI ATTACKER     │ ─────── HTTP attacks ─────────────▶   │   VICTIM SERVER     │
│  innozverse-kali    │                                         │  innozverse-cybersec│
│  curl, hashcat,     │ ◀────── responses ───────────────────  │  Flask :5000        │
│  john, python3      │                                         │  (weak auth, MD5)   │
└─────────────────────┘                                         └─────────────────────┘

Time

45 minutes

Tools

  • Victim: zchencow/innozverse-cybersec:latest

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


Lab Instructions

Step 1: Environment Setup

⚠️ Note: Substitute /tmp/victim_a07.py with any writable path on your host if /tmp is not available.


Step 2: Launch Kali + Recon


Step 3: Username Enumeration — Different Error Messages

📸 Verified Output:

📸 Verified Output:

💡 Username enumeration turns a random attack into a targeted one. Once an attacker knows admin, alice, and bob are valid users, they only need to crack 3 accounts instead of guessing both username and password. Fix: always return the same error message regardless of whether the username or password was wrong — {"error": "Invalid credentials"}. Add the same artificial delay to prevent timing-based enumeration.


Step 4: Password Brute-Force — No Rate Limiting

📸 Verified Output:


Step 5: Harvest and Crack Password Hashes

📸 Verified Output:

📸 Verified Output:

💡 MD5 and SHA-256 are not password hashing algorithms — they are general-purpose hashing algorithms. They are designed to be fast, which means an attacker with a GPU can try billions of hashes per second. bcrypt, scrypt, and Argon2id are designed to be slow (deliberately expensive to compute), making brute-force infeasible. The Python equivalent: bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12)).


Step 6: Weak Session Token Entropy

📸 Verified Output:


Step 7: Credential Stuffing Simulation

📸 Verified Output:


Step 8: Cleanup


Remediation

Vulnerability
Root Cause
Fix

Username enumeration

Different error messages

Single message: {"error": "Invalid credentials"}

No brute-force protection

No rate limit

Max 5 attempts/15min per IP; exponential backoff

Weak password hashing

SHA-256/MD5 (fast)

bcrypt.hashpw(pw, bcrypt.gensalt(rounds=12))

Weak session token

secrets.token_hex(4) = 32-bit

secrets.token_hex(32) = 256-bit

Hash endpoint

/api/hashes exposes all hashes

Remove entirely; never expose hashes via API

Summary

Attack
Tool
Result

Username enumeration

curl

Found 3 valid usernames from error message difference

Password brute-force

curl loop

admin:admin cracked in 4 attempts

Hash cracking (SHA-256)

john

admin cracked from rockyou.txt

Hash cracking (MD5)

john

alice and bob cracked from rockyou.txt

Credential stuffing

python3

2/5 accounts compromised with reused passwords

Weak token demo

python3

32-bit vs 256-bit token entropy comparison

Further Reading

Last updated