Broken Authentication System
Production-ready skill that handles skill, should, used, user. Includes structured workflows, validation checks, and reusable patterns for security.
Broken Authentication System
Identify and test authentication and session management vulnerabilities in web applications. This skill covers credential testing, session fixation, token analysis, MFA bypass techniques, password reset flaws, and OAuth/OIDC misconfiguration testing — all within authorized security testing contexts.
When to Use This Skill
Choose Broken Authentication System when you need to:
- Test login mechanisms for credential stuffing and brute force resistance
- Analyze session tokens for predictability, entropy, and lifecycle issues
- Identify MFA implementation weaknesses and bypass paths
- Audit OAuth 2.0 and OIDC implementations for authorization flaws
Consider alternatives when:
- You need to implement secure authentication from scratch (use API Security Best Practices)
- You need to test API-specific auth issues (use API Fuzzing skill)
- You need identity provider configuration review (use vendor-specific security guides)
Quick Start
pip install requests jwt PyJWT
import requests import time import hashlib from collections import Counter class AuthTester: """Test authentication mechanisms for security weaknesses.""" def __init__(self, target_url): self.target = target_url.rstrip('/') self.session = requests.Session() self.findings = [] def test_lockout_policy(self, login_endpoint, username, max_attempts=20): """Test if account lockout is enforced.""" print(f"Testing lockout policy for: {username}") results = [] for i in range(max_attempts): resp = self.session.post( f"{self.target}{login_endpoint}", json={"username": username, "password": f"wrong_pass_{i}"}, timeout=10 ) results.append({ 'attempt': i + 1, 'status': resp.status_code, 'time': resp.elapsed.total_seconds() }) # Check for lockout indicators if resp.status_code == 429: print(f" Rate limited after {i+1} attempts") return results if 'locked' in resp.text.lower(): print(f" Account locked after {i+1} attempts") return results self.findings.append({ 'issue': 'No account lockout detected', 'detail': f'{max_attempts} failed attempts without lockout', 'severity': 'HIGH' }) print(f" WARNING: No lockout after {max_attempts} attempts") return results def analyze_session_tokens(self, login_endpoint, credentials, count=20): """Collect and analyze session token entropy.""" tokens = [] for i in range(count): s = requests.Session() resp = s.post(f"{self.target}{login_endpoint}", json=credentials, timeout=10) cookies = dict(s.cookies) for name, value in cookies.items(): if 'session' in name.lower() or 'token' in name.lower(): tokens.append(value) s.close() if tokens: # Check for patterns lengths = [len(t) for t in tokens] unique = len(set(tokens)) print(f"\nSession Token Analysis:") print(f" Collected: {len(tokens)} tokens") print(f" Unique: {unique}") print(f" Length range: {min(lengths)}-{max(lengths)}") if unique < len(tokens): self.findings.append({ 'issue': 'Duplicate session tokens generated', 'severity': 'CRITICAL' }) # Check for sequential patterns if len(tokens) >= 2: diffs = [] for j in range(1, len(tokens)): try: diff = int(tokens[j], 16) - int(tokens[j-1], 16) diffs.append(diff) except ValueError: break if diffs and len(set(diffs)) == 1: self.findings.append({ 'issue': 'Sequential session tokens detected', 'severity': 'CRITICAL' }) return tokens # Usage (authorized testing only) # tester = AuthTester("https://target.example.com") # tester.test_lockout_policy("/api/login", "admin")
Core Concepts
Authentication Vulnerability Types
| Vulnerability | Description | OWASP Ref |
|---|---|---|
| Credential stuffing | Automated login with leaked credentials | A07:2021 |
| Brute force | Exhaustive password guessing | A07:2021 |
| Session fixation | Forcing a known session ID on the victim | A07:2021 |
| Session hijacking | Stealing active session tokens (XSS, MITM) | A07:2021 |
| Weak tokens | Low-entropy or predictable session identifiers | A02:2021 |
| Token leakage | Tokens in URLs, logs, or referrer headers | A02:2021 |
| MFA bypass | Skipping MFA via direct API calls or race conditions | A07:2021 |
| Password reset flaws | Predictable reset tokens, no rate limiting | A07:2021 |
| OAuth misconfig | Open redirects, CSRF in OAuth flow, token theft | A07:2021 |
JWT Security Analysis
import jwt import json import base64 import requests def analyze_jwt(token): """Analyze a JWT token for security issues.""" findings = [] # Decode without verification to inspect claims parts = token.split('.') if len(parts) != 3: print("Not a valid JWT format") return findings # Decode header header = json.loads( base64.urlsafe_b64decode(parts[0] + '==') ) print(f"Algorithm: {header.get('alg', 'MISSING')}") print(f"Type: {header.get('typ', 'MISSING')}") # Check algorithm issues if header.get('alg') == 'none': findings.append({ 'issue': 'JWT uses "none" algorithm', 'severity': 'CRITICAL', 'detail': 'Token signature can be removed entirely' }) elif header.get('alg', '').startswith('HS'): findings.append({ 'issue': f'JWT uses symmetric algorithm ({header["alg"]})', 'severity': 'MEDIUM', 'detail': 'Vulnerable to brute-force key guessing if key is weak' }) # Decode payload payload = json.loads( base64.urlsafe_b64decode(parts[1] + '==') ) print(f"Claims: {json.dumps(payload, indent=2)}") # Check expiration import time exp = payload.get('exp') if exp is None: findings.append({ 'issue': 'JWT has no expiration (exp) claim', 'severity': 'HIGH' }) elif exp - time.time() > 86400: findings.append({ 'issue': f'JWT expiration too long: {(exp - time.time())/3600:.0f} hours', 'severity': 'MEDIUM' }) # Check for sensitive data in payload sensitive_keys = ['password', 'secret', 'ssn', 'credit_card', 'api_key'] for key in payload: if any(s in key.lower() for s in sensitive_keys): findings.append({ 'issue': f'JWT contains potentially sensitive claim: {key}', 'severity': 'HIGH' }) for f in findings: print(f"[{f['severity']}] {f['issue']}") return findings # analyze_jwt("eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiYWRtaW4iLCJyb2xlIjoiYWRtaW4ifQ.xxx")
Configuration
| Parameter | Description | Default |
|---|---|---|
target_url | Target application URL | Required |
login_endpoint | Authentication endpoint path | "/api/login" |
lockout_threshold | Max attempts before expected lockout | 5 |
token_sample_size | Number of tokens to collect for analysis | 20 |
brute_force_delay | Delay between attempts (seconds) | 0.5 |
jwt_wordlist | Key wordlist for JWT brute force | Common secrets |
proxy | HTTP proxy for traffic inspection | None |
timeout | Request timeout (seconds) | 10 |
Best Practices
-
Test both the happy path and edge cases — Beyond testing wrong passwords, test: empty credentials, very long passwords (10,000+ chars), special characters, SQL injection in username field, null bytes, and Unicode characters. Authentication parsers often have unexpected behavior with unusual input.
-
Verify session invalidation on logout and password change — After a user logs out or changes their password, old session tokens should be immediately invalid. Test by saving a session token, triggering logout/password change, then replaying the old token. Many applications fail to invalidate server-side sessions.
-
Test MFA bypass systematically — Common MFA bypasses: skip the MFA step by directly accessing post-auth URLs, use an old valid TOTP code, manipulate response parameters to skip MFA verification, test race conditions where MFA can be bypassed by sending multiple simultaneous requests.
-
Check for credential leakage in responses and logs — Verify that login responses don't return different error messages for valid vs invalid usernames (user enumeration). Check that passwords aren't logged in server logs, URL parameters, or browser history.
-
Test password reset token security — Request multiple reset tokens and check for sequential or predictable patterns. Test if old reset tokens are invalidated when a new one is requested. Verify that reset tokens expire after use and after a time limit.
Common Issues
Login timing differences reveal valid usernames — Applications that hash passwords only for existing users show measurable timing differences between valid and invalid usernames. A consistent 50ms difference over 100 requests is statistically significant. Mitigate by always performing the hash operation regardless of username validity.
Session tokens persist after server-side logout — Many applications only clear the client-side cookie on logout without invalidating the server-side session. The old token remains valid if replayed. This is a common finding that requires server-side session store invalidation.
OAuth redirect_uri validation is insufficient — Applications that validate redirect URIs with string prefix matching (e.g., allowing https://example.com.evil.com) instead of exact matching are vulnerable to token theft via open redirect. Test with subdomain variations, path traversal, and parameter injection.
Reviews
No reviews yet. Be the first to review this template!
Similar Templates
Full-Stack Code Reviewer
Comprehensive code review skill that checks for security vulnerabilities, performance issues, accessibility, and best practices across frontend and backend code.
Test Suite Generator
Generates comprehensive test suites with unit tests, integration tests, and edge cases. Supports Jest, Vitest, Pytest, and Go testing.
Pro Architecture Workspace
Battle-tested skill for architectural, decision, making, framework. Includes structured workflows, validation checks, and reusable patterns for development.