Browse CTFs New CTF Sign in

Weak password policy exploit

crypto_symmetric_kdf Difficulty 1–5 30 min certifiable

Theory

Why This Matters

Weak password policies and credential-based attacks are the leading cause of web application breaches. The 2012 LinkedIn breach exposed 117 million SHA-1 unsalted password hashes, of which approximately 90% were cracked within days of the dump being published. The 2019 Collection #1 breach database contained 773 million unique email/password combinations, forming the foundation for credential stuffing attacks that continue to affect applications today. NIST SP 800-63B (2017) reversed the previous guidance on mandatory complexity rules and periodic rotation, demonstrating that the industry has learned from a decade of policy failures. Understanding how policies are assessed — and how attackers exploit weak policies — is essential for both penetration testers and security architects designing authentication systems.

Core Concept

A password policy is the set of rules governing what passwords users may create: minimum length, character class requirements (uppercase, lowercase, digits, symbols), prohibition on previously used passwords, and maximum age. The security goal is to ensure the password space is large enough that brute-force attacks are computationally infeasible within the threat model.

Policy analysis begins with identifying the actual constraints: testers register accounts with boundary-condition passwords to determine the minimum length, required character classes, and any prohibited patterns. A policy requiring only 6 characters with no other constraints allows a password space of approximately 26^6 ≈ 300 million lowercase-only passwords — crackable in seconds with modern GPU hardware. NIST SP 800-63B recommends a minimum of 8 characters with no mandatory complexity rules, and maximum length of at least 64 characters.

Online brute-force tests passwords against the live application, which is rate-limited by network latency, server processing, and — if implemented — lockout and CAPTCHA controls. Tools like Hydra and Burp Suite Intruder automate online attacks. The limiting factor is the application's lockout threshold and response speed.

Credential stuffing uses breach-derived username:password pairs from repositories such as the RockYou wordlist, HaveIBeenPwned-correlated dumps, and the Collections series. It exploits password reuse: users who reuse passwords from other breached services are immediately vulnerable when those pairs are tested against a new target. Unlike brute-force, each pair is attempted only once, staying below per-account lockout thresholds.

Password spraying tests a small number of high-probability passwords (e.g., Password1, Summer2024!, Welcome1) against a large number of accounts. Because the same password is tested only a few times per account, it evades per-account lockout while making progress across the full user population.

bcrypt cost factor analysis assesses the offline cracking resistance of stored hashes if a database dump is obtained. The bcrypt cost factor (work factor) determines how many iterations are performed; a cost of 10 takes approximately 100ms per hash on modern hardware, making large-scale offline cracking expensive. A cost factor below 10 is a reportable finding in a security assessment.

Technical Deep-Dive

Policy testing via boundary-condition registration:

# Test minimum length
curl -s -X POST https://target.example.com/register 
  -d "username=test_user&password=a&[email protected]" | grep -i "password"
# Repeat with 2,3,4,5,6,7,8 characters to find the minimum

# Test character class requirements
# Attempt: all lowercase, all uppercase, digits only, special chars only
for pw in "aaaaaaaa" "AAAAAAAA" "12345678" "!@#$%^&*"; do
  result=$(curl -s -X POST https://target.example.com/register 
    -d "username=test_user_pw&password=$pw&[email protected]")
  echo "$pw: $(echo $result | grep -o 'invalid|success|error' | head -1)"
done

Online brute-force with Hydra:

hydra -l [email protected] 
      -P /usr/share/wordlists/rockyou.txt 
      target.example.com 
      http-post-form "/login:email=^USER^&password=^PASS^:Invalid credentials" 
      -t 4 
      -w 3 
      -V 
      -o hydra_output.txt

Password spray with Burp Suite Intruder (Pitchfork mode):

POST /login HTTP/1.1
Host: target.example.com
Content-Type: application/x-www-form-urlencoded

username=§user_from_list§&password=Password1

-- Payload Set 1: usernames from enumerated list
-- Single password: Password1 (or cycle through 3-5 candidates to stay under lockout)
-- Attack type: Sniper (one list) or use cluster bomb for multiple passwords

bcrypt cost factor assessment from a hash:

# bcrypt hash format: $2b$COST$SALT+HASH
# Example: $2b$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy
# Cost factor = 10 (field between second and third $)
# Cost 10 = ~100ms/hash on modern hardware
# Cost 8  = ~25ms/hash → 4x faster cracking = reportable
# Cost 6  = ~6ms/hash  → critical finding

# Offline crack with hashcat (bcrypt = mode 3200)
hashcat -m 3200 -a 0 
  hashes.txt 
  /usr/share/wordlists/rockyou.txt 
  --status

Security Assessment Methodology

  1. Enumerate the password policy — Register test accounts with boundary-condition passwords (1 char, 7 chars, 8 chars; all-lowercase; no symbols) to determine the actual enforced minimum length and character requirements. Compare against NIST SP 800-63B recommendations.
  2. Check HaveIBeenPwned API integration — NIST recommends blocking passwords found in breach corpora. Test whether common breach passwords (Password1, rockyou top-100 entries) are accepted by the registration form.
  3. Test online brute-force with Hydra — Using a test account with a known weak password (created during testing), confirm that Hydra can successfully authenticate. This validates that the brute-force methodology works for the target before applying it to the actual assessment scope.
  4. Assess lockout and CAPTCHA — Run Hydra with -t 10 and monitor at which attempt (if any) the application begins returning lockout responses or CAPTCHA challenges. Document the threshold and the lockout duration.
  5. Test password spraying — Submit Password1, Welcome1, and the current month+year (e.g., May2026) against 10–20 enumerated usernames. If any succeed, the population has predictably weak passwords and no effective lockout on spray patterns.
  6. Review stored hash strength if accessible — If a database dump is in scope (via SQL injection finding, or as part of a code/infrastructure review), assess the hashing algorithm and cost factor. MD5 or SHA-1 without salt is a critical finding; bcrypt with cost < 10 is a medium finding.

Defensive Countermeasure — Enforce a minimum length of 12 characters with no mandatory complexity rules (per NIST SP 800-63B), check new passwords against the HaveIBeenPwned Pwned Passwords API (k-anonymity model), store all passwords with bcrypt at cost factor ≥ 12 or Argon2id with memory ≥ 64 MB, and implement account-scoped lockout after 5 failures combined with a cross-account password-spray detector that triggers on multiple accounts failing authentication with the same password within a short window.

Common Assessment Errors

  • Stopping at policy documentation without testing enforcement — A policy document may specify minimum 12 characters, but the application may only enforce 6. Always empirically test the policy via registration boundary conditions.
  • Using only rockyou.txt — The rockyou.txt list is optimised for cracking residential user accounts. Corporate targets require organisation-specific wordlists: company name, domain, city, product names, combined with year and special character appends.
  • Not testing the password change endpoint separately — Registration and password change flows sometimes have different policy enforcement. A registration requiring 12+ characters may allow a change to 6 characters.
  • Ignoring the maximum length limit — Applications with a maximum password length below 64 characters force truncation, which can reduce entropy. A maximum of 20 characters is a reportable policy weakness per NIST guidance.
  • Conflating online and offline cracking — Online attacks are rate-limited; offline attacks against leaked hashes are CPU/GPU-limited. Document which attack model applies and the corresponding time-to-crack estimate when reporting.
  • Not documenting credential stuffing tooling — Hydra is for brute-force; Snipr, Sentry MBA, and Storm are credential-stuffing tools optimised for matching breach pairs. The report should clarify which attack class was demonstrated and at what success rate.

NICE Framework Alignment

Code Knowledge/Skill/Task Statement How This Card Develops It
K0007 Knowledge of authentication, authorisation, and access control methods Covers password policy design principles, NIST SP 800-63B guidance, and the attack classes that weak policies enable
K0065 Knowledge of policy-based and role-based access controls Explains how password policy interacts with access control: a guessable credential bypasses all downstream policy
S0001 Skill in conducting vulnerability scans and recognising vulnerabilities in security systems Develops Hydra, Burp Intruder, and hashcat usage for online brute-force, password spraying, and offline hash cracking
T0028 Conduct and/or support authorised penetration testing on enterprise network assets Provides a complete credential security assessment methodology from policy enumeration through offline hash cracking

Further Reading

  • NIST Special Publication 800-63B: Digital Identity Guidelines — Authentication and Lifecycle Management — NIST (Grassi, Garcia, Fenton)
  • OWASP Testing Guide v4.2, OTG-AUTHN-007: Testing for Weak Password Policy — OWASP Foundation
  • Hashcat Wiki: Example Hashes and Attack Modes — hashcat.net documentation

Challenge Lab

Reinforce your learning with a hands-on generated challenge based on this card's competency.