0x230 - Time-Based Email Enumeration

0x230 - Time-Based Email Enumeration

This week I reviewed several AI-generated pentest reports.

The client has setup an AI agent to hack their app, configured it with credentials and let it do its job.

While this produced ~10-12 reports, the work didn't end here.

They needed someone to look through all these reports and:

  1. Reproduce the findings to confirm if it's real (some were actual hallucinations with made-up HTTP responses)

  2. Verify and decide how critical the findings actually are (a few of the "critical" ones were more like "medium")

However, one vulnerability in particular caught my attention.

A vulnerability that I (and probably many pentesters) would have overlooked.

A time-based email enumeration.


Common Email Enumeration

Common places for email enumerations include:

  1. Login

  2. Register

  3. Password Reset

You try one of these functions with a known (already registered) email.

You check the HTTP response.

Then you try it again with an invalid (non-existing) email.

You look for differences between the two responses: Email already exists vs. Email not found.

Based on this difference you can infer if a user already has an account on the app or not.

However, in this case all responses were ambiguous/generic i.e: If the email is registered, an email will be sent.


Time-Based Email Enumeration

What surprised me in this case was that the AI was still able to enumerate emails using the differences in the server's response time.

The technique is nothing new.

You can read more about it here.

But many pentesters would've probably overlook it and move on concluding that the app is not vulnerable.

However the AI caught it.


How it worked:

  1. The AI tested the Login form with an existing account and invalid password

  2. Got Incorrect email or password

  3. Then checked again the Login form with a non-existing account

  4. Got again Incorrect email or password

  5. Tested both scenarios ~5 times

  6. Compared the HTTP response time

  7. Noticed that for existing account with invalid password -> 500 milliseconds

  8. Noticed that for non-existing account -> 200 milliseconds

  9. Concluded that this can be used for enumeration

The difference was minimal. Easy to overlook for a human.

But when I tried to reproduce the finding -> it was indeed consistent across multiple checks.

Everytime an existing account was checked -> the server took longer to reply.


References

  • https://passkwall.medium.com/timing-based-username-enumeration-whats-a-fix-versus-mitigation-8a0f8c7191f2

  • https://www.pentestpartners.com/security-blog/time-based-username-enumeration/

  • https://portswigger.net/web-security/authentication/password-based/lab-username-enumeration-via-response-timing

Pentest Tips & Tricks

Buy nowLearn more

A01 - Broken Access Control

  • 0x02 - Broken Auth in 30 Seconds
  • 0x19 - Account Takeover via Open Redirect
  • 0x40 - Info Leak to Account Takeover
  • 0x42 - Auth Bypass with 0-based UUIDs
  • 0x64 - Pentesting Admin Accounts
  • 0x77 - Another Way to Bypass 2FA
  • 0x81 - Seven Ways to Bypass 403
  • 0x122 - Finding Orphaned Privileges
  • 0x123 - Deleted Page Gave Me Owner Access
  • 0x158 - ATO With Cached Magic Links
  • 0x183 - Run Postman Collections for BAC
  • 0x184 - Exploiting Half-Open Sessions
  • 0x187 - File Access Bypass using Chatbots
  • 0x188 - HTTP Response Manipulation
  • 0x192 - The Silent ATO

A02 - Cryptographic Failures

  • 0x06 - JWT Exfil from Source Page
  • 0x29 - Automating JWT Pentests
  • 0x49 - Cracking JWT Tokens
  • 0x75 - Validating Leaked API Keys
  • 0x96 - Token Randomness Analysis
  • 0x130 - Bypass Encryption w/ JS Debugger
  • 0x132 - Reset Token to Backdoor Trick
  • 0x152 - Cracking Password Reset Tokens

A03 - Injection Attacks

  • 0x01 - XSS via Custom Named Tags
  • 0x11 - Email Field Payload Injection
  • 0x12 - XML Formatted XSS Payloads
  • 0x15 - SSRF for Internal Network Scanning
  • 0x18 - Burp Hackvertor for Advanced Injection
  • 0x25 - OOB Template Injection via SMS
  • 0x35 - HTML Injection for Phishing Emails
  • 0x36 - File Read via Login Wallpapers
  • 0x52 - XSS in SVG Images
  • 0x76 - XSS via Phone Number Field
  • 0x80 - Race Conditions with Turbo Intruder
  • 0x89 - XSS via PostMessage
  • 0x90 - XSS via HREF URLs
  • 0x91 - Invading the DOM
  • 0x115 - Real-World Reflected XSS
  • 0x143 - Full-Width Characters Bypass
  • 0x145 - Exploiting Blind HTML Injection
  • 0x151 - File Upload + CSP + WAF Bypass = XSS

A04 – Insecure Design

  • 0x17 - Exploiting Race Conditions
  • 0x22 - Phishing via Signup Forms
  • 0x37 - Open Redirect via REGEX Bypass
  • 0x44 - No Email Verification Abuse
  • 0x62 - Location Spoofing Tricks
  • 0x99 - Loop Denial of Service
  • 0x100 - Infinite Trial Period
  • 0x141 - Why Pentesters Love Blacklists
  • 0x153 - Business Logic Abuses
  • 0x163 - DoS in Sparse Fieldsets API
  • 0x165 - When Cronjobs Implode
  • 0x173 - Test Credit Cards
  • 0x175 - Pay Me Baby One More Time
  • 0x195 - Business Logic Bug in Snapchat

A05 – Security Misconfiguration

  • 0x05 - DB Dump via Underscore Wildcards
  • 0x28 - Azure Subdomain Takeover at Scale
  • 0x32 - Command Injection in Azure Webapps
  • 0x34 - File Upload Bypass in Firebase
  • 0x38 - Dir Listing via Range Header Abuse
  • 0x41 - Crashing Apps with Large Inputs
  • 0x47 - CORS Misconfig Exploitation
  • 0x85 - Escalating Debug Log Pages
  • 0x121 - File Upload Bypass via ZIPs
  • 0x144 - Bypassing Firewalls Whitelisting
  • 0x179 - Leaking Source Code with Fuzzing

A06 – Vulnerable Components

  • 0x48 - Finding NPM Dependency Confusion
  • 0x53 - Using Collaborator as Email Inbox
  • 0x65 - Can't Find Dependency Confusion?
  • 0x83 - Hacking GitHub CI/CD Workflows
  • 0x88 - Attacking GWT-RPC Apps
  • 0x102 - File Upload Bypasses for 2025
  • 0x108 - Bypassing Geolocation Restrictions
  • 0x118 - Exploiting Dangling JS Dependencies
  • 0x127 - Denial of.. Wallet?!
  • 0x156 - Triggering OOM With Bomb GIFs
  • 0x196 - Reversing Blazor Web Apps

A07 – Identification and Authentication Failures

  • 0x07 - GraphQL Crash via Recursive Queries
  • 0x23 - Private Email Leak via Google SSO
  • 0x27 - Email Spoof via Client-Side Bypass
  • 0x43 - Email Spoof via DMARC Policy Abuse
  • 0x59 - File Access Bypass via Referer in CDN
  • 0x95 - How the Microsoft MFA was Bypassed
  • 0x133 - Authentication Bypasses for 2025
  • 0x166 - Data Leakage Through Updates
  • 0x197 - Bypass Auth with GraphQL
  • 0x198 - Wrong Email, Right Token

Recon & Attack Surface

  • 0x04 - Reading Intercom Widget Messages
  • 0x14 - Hidden Endpoints via Link Headers
  • 0x30 - Hidden API Endpoints in WADL Files
  • 0x39 - SSRF in PDF Generators
  • 0x58 - Google Maps API Key Testing
  • 0x66 - Attack Surface via Timing Attacks
  • 0x69 - Finding CSRF through Methods Change
  • 0x79 - Attack Paths in API Docs
  • 0x84 - Finding Only Exploitable CVEs
  • 0x86 - Email Enumeration with Slack
  • 0x98 - Scanning OpenAPI with SOAPI
  • 0x110 - Exploiting Typos in DNS Records
  • 0x106 - Finding Backups From the Past
  • 0x120 - Reverse Engineering APIs
  • 0x135 - Secrets in GitHub Garbage
  • 0x147 - Checking Ports for Exfiltration
  • 0x186 - New Era of Secret Detection
  • 0x189 - NextJS Paths Recon
  • 0x199 - Reversing JS Apps

Tooling & Automation

  • 0x08 - Better Folder Enumeration
  • 0x13 - Optimizing Payload Lists
  • 0x20 - Firebase Pentest with Artillery
  • 0x21 - Auto-Finding Dangerous JS Functions
  • 0x24 - GraphQL Voyager for Circular Refs
  • 0x26 - Burp + Python for Pentest Automation
  • 0x31 - Automating Pentests with Bamdas
  • 0x33 - Hiding Uninteresting HTTP Headers
  • 0x51 - Auto-Finding Injectable Parameters
  • 0x55 - No Collaborator? No Problem!
  • 0x57 - Missed Request Smuggling Vulns
  • 0x60 - Burp Fuzzing Insertion Points
  • 0x61 - Modifying Requests on the Fly
  • 0x63 - Reviewing Scanner Payloads in Burp
  • 0x73 - Websocket Pentesting Extension
  • 0x74 - UUID Bruteforce with Custom Lists
  • 0x78 - Blind XSS Hunting in Seconds
  • 0x87 - SQLMap Command Generator
  • 0x93 - Bypassing URL Validation
  • 0x101 - So You Decided to Password Spray?
  • 0x105 - The Offsec Toolkit
  • 0x136 - API Scanning Automation FTW
  • 0x137 - Optimizing Burp Scanner
  • 0x160 - Source Code in Plain Sight
  • 0x174 - Comment Crusader
  • 0x176 - 429 Too Many Request
  • 0x177 - Maximizing Tricks Value
  • 0x180 - Replaying POST Payloads in Browser
  • 0x194 - The Kasada Anti-Bot
  • 0x202 - CSP Bypass Search

Creative, Strategic, and Mindset

  • 0x00 - Sandbox Escape in Point of Sale (POS)
  • 0x09 - Bypassing CAPTCHA - Techniques
  • 0x16 - Path Traversal - Techniques
  • 0x45 - Exploiting Online Compilers
  • 0x50 - Payload Gen with SCAMMPERR
  • 0x54 - Tracking Users with Image URLs
  • 0x56 - Domain Blacklist Bypass w/ Azure DNS
  • 0x70 - Pentesting SIP Protocols
  • 0x71 - RickRolling a Payment Terminal
  • 0x82 - Exploiting Hop-by-Hop Headers
  • 0x94 - When SQLmap Fails: 3 Tips
  • 0x103 - What's Response Filter DoS
  • 0x104 - Train Your (Hacker) Imagination
  • 0x107 - Should We Avoid Burp Collaborator?
  • 0x109 - How to Write Exploits
  • 0x119 - Is Google Sabotaging Hackers?
  • 0x124 - Find Your Crush on Dating Apps
  • 0x125 - Unveiling the Web's Secrets
  • 0x129 - Honey, I'm h̶o̶m̶e̶ payload!
  • 0x131 - How to Exploit Slopsquatting
  • 0x134 - Are Browsers Sabotaging Hackers?
  • 0x139 - Look Where Others Haven’t
  • 0x140 - Making Exploits More Reliable
  • 0x142 - Github Issues for Inspiration
  • 0x148 - Web Attack Escalations
  • 0x150 - How to Hack an ATM
  • 0x154 - The Rule of #3
  • 0x161 - Three Pentesting Mistakes I Made
  • 0x190 - OWASP Top Ten 2025
  • 0x200 - Smart Input Data

Bug Bounty $$$

  • 0x03 - Maximizing Vulns Impact
  • 0x46 - Weaponizing XSS for Maximum Impact
  • 0x67 - Unlocking Premium for Free
  • 0x97 - Is This in Scope?
  • 0x111 - Leaking YouTube Emails for $10K
  • 0x112 - $4,000 Bounty for Clickjacking?
  • 0x116 - $1000 Privacy Loophole Exploit
  • 0x146 - High Demand Bounties ($50k+)
  • 0x155 - Get 1,500$ For Your Research
  • 0x157 - Don't Track Me!
  • 0x162 - $350,000 Bounties for HTTP/1.1
  • 0x164 - Three Tips for BB Reports
  • 0x169 - How I Hacked 500 Routers
  • 0x170 - How I Hacked My Hotel
  • 0x171 - Amazon Payment Bypass
  • 0x178 - API Key Rotation
  • 0x181 - Deleting Messages With Emojis 😂
  • 0x182 - Cache Poisoning Profile Pics
  • 0x185 - Bug Bounty Helper
  • 0x193 - The 600,000$ Discount Bug
  • 0x201 - Getting $13,337 for HTML Injection
  • 0x208 - The $200k BugBounty Extension
  • 0x215 - $55,000 for Spring Boot Actuator

AI/ML/LLM/MCP

  • 0x68 - Top 10 AI Chatbot Attack Ideas
  • 0x72 - Stealing AI Chatbot Prompts
  • 0x92 - Scanning Docs with NotebookLM
  • 0x113 - What is Burp's Shadow Repeater
  • 0x114 - Is Nuclei AI Worth It?
  • 0x117 - Email Assistant Account Takeover
  • 0x126 - Formatting XSS Payloads
  • 0x128 - What's a Model Context Protocol (MCP)
  • 0x138 - Vibe Coding -> More Hacking
  • 0x149 - RCE in MCP Inspector
  • 0x159 - Recon the Cursor
  • 0x167 - LLM Bypass via Alternative Language
  • 0x168 - Hacking MCP Servers
  • 0x172 - Building & Breaking AI Agents
  • 0x191 - AI Liberating Prompts

Latest Tips & Tricks

  • 0x203 - Bypass TLS Fingerprinting
  • 0x204 - Inject in Tooltip Message
  • 0x205 - 3 Levels of BAC Difficulty
  • 0x206 - Quick File Secrets Recon?
  • 0x207 - Modifying JS On the Fly
  • 0x209 - Hacking WorkOS Intents
  • 0x210 - Quick Kubernetes Checklist
  • 0x211 - Update/Read Parallel Intruder
  • 0x212 - Subdomain Takeover + Image Injection
  • 0x213 - Hacking Webapps Through SSH
  • 0x214 - Recon for Protocols
  • 0x216 - Top 10 Hacks of 2025
  • 0x217 - The Hidden Attack Surface
  • 0x218 - HTTP Anomaly Rank
  • 0x219 - Making $10k With Cookie Bombing
  • 0x220 - Attacking Metadata
  • 0x221 - Look for Developer Mode
  • 0x222 - Catch-All Email Address
  • 0x223 - Attacking Workflows
  • 0x224 - Hacking Single Page Applications
  • 0x225 - Browser-Based API Pentesting
  • 0x226 - Finding XSS Others Missed
  • 0x227 - Extracting Metadata at Scale
  • 0x228 - Abusing Arrays for Extra Privileges
  • 0x229 - Simple DoS with SSO
  • 0x230 - Time-Based Email Enumeration
  • 0x231 - Logging of Sensitive Tokens
  • 0x232 - Exploiting Gemini With Google Maps
  • 0x233 - Bypassing the AI Triager
  • 0x234 - How To Build an Exploit Writer
  • 0x235 - 66,000$ Bounty for Facebook ATO
  • 0x236 - Bypass Instagram "Pay or Consent"
  • 0x237 - How AI Manipulates You To Spend Money
  • 0x238 - Burp Suite Notes
  • 0x239 - Reverse Trusted Integrations
  • 0x240 - Unauthenticated Websocket Attack
  • 0x241 - Too Poor To Do Bug Bounty
  • 0x242 - Quick & Free Reverse DNS
  • 0x243 - Finding Internal IP Addresses for SSRF
  • 0x244 - Short Lived JWT Token Automation
  • 0x245 - 1-click RCE in Electron Apps
  • 0x246 - Unauth Read/Write To S3 Buckets
  • 0x247 - Account Takeover using CRLF
  • 0x248 - Preview Token -> BAC
  • 0x249 - DOM-Based XSS & Phishing
  • 0x250 - Consistency Beats Talent