Almost one-half of email providers, some of them leading providers, are vulnerable to an email/username verification attack with no apparent mitigating controls. This is my attack code and research.
I’m not going to spend a ton of time explaining things to the nth degree. If things alluded to here don’t make sense to you, and you wish to understand, read more here: https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol
In Jan 2018, I had the need to verify a list of email addresses, but did not want to send an email. I popped open a terminal window and attempted to manually verify a known good email address against one of the largest email providers.
As can be seen, their mail server happily told me the email address was valid without actually completing the full “send mail” dialog over SMTP, or even getting to the “DATA” section.
Since I’ve seen many providers in the past give an “okay, proceed” to invalid addresses as an attempt to mitigate this vulnerability, I wanted to confirm the email server would give me a “not found” message for non-existent addresses. IMO, and based on what I see as the spirit of OWASP-AT-002, the email server should give the same message. I repeated the above with a non-existent email address.
They just confirmed this one as invalid.
Going back to (IMO) the spirit of OWASP-AT-002, an attacker can not only verify a list of suspected usernames for provider X, but could even enumerate the valid usernames. Since this is for email, the attacker could also generate a list of validated email addresses for use in phishing/spam. If this was allowed to be performed on a mass scale (thousands of requests per hour) without any sort of rate limiting, it would be even more serious.
As you’ll see below, some of the providers allowing this are industry leaders in the email space. My guess is they do not see the implications carrying much risk and/or have chosen to strictly follow RFC guidelines about SMTP which actually encourages this behavior. Since a user does not typically send email via raw SMTP commands, I can’t imagine this decision offers any benefit for user experience.
Side note: RFC 821 (circa 1982) even specifies a “VRFY” command to explicitly request verification from the server. Back in the days of low bandwidth networks and (relatively) weak servers, it’s understandable why VRFY’ing an address (a few bytes) before sending the full message (hundreds/thousands of bytes) would be preferred.
IMO, the security vs. usability debate clearly needs to go to security on this one. One should not give differing messages (at the SMTP level) to the interactive systems for valid vs invalid email addresses unless there is a pressing need. A receiving email server should tell the sending system “okay, proceed” for any email address it receives. After the session is complete, the server should decide what to do with the email. It should not notify the sending server in the middle of the SMTP session.
I remember setting up an MS Exchange server in the early 2000s and purposely configuring the server to pretend addresses were valid while sending them to a black hole. It’s interesting to note, as you’ll see below, Microsoft-managed email providers (among others) were actually the winners in this regard.
Note: This does not exclude one from bouncing emails destined for invalid accounts. Assuming that bounce comes a few seconds later, well after the SMTP session is terminated, it would severely impact an attacker’s ability to brute force email addresses.
What if you do have some pressing need to allow verification mid-SMTP session? I suggest you implement rate limiting and integrate SBL (Spamhaus Block List), or similar, into the SMTP session, pre-DATA.
Note: The email providers I discovered in my research that I’m calling “vulnerable”, presumably have none of the above mitigations, as I was never blocked or throttled.
Here’s the exploit code I created, and tested, that leverages the vulnerability on all vulnerable email servers. It works by skipping domains known to implement good security practices (“faking it” and/or SBL), while actually reaching out to servers that have never blocked the attempts before. Sequence would be: (1) assume all servers are vulnerable, (2) run this script, (3) detect if a server blocks the attempts at some point (by monitoring the logs), (4) pause the script, (5) blacklist the server (so the script will skip it), (6) resume the script.
I tread carefully on this one. The last thing I wanted to do is affect the availability of an email provider while conducting legitimate security research. As such, I used a relatively small list of email addresses (676,322) and throttled my script to run over a period of about 48 hours. That’s about 10 emails per second. For some of the bigger providers (Gmail, Yahoo, Hotmail, etc), the effective rate was about one email per second against a given email provider. Given these providers (probably) see 100s of thousands of transactions per second, I was confident my one transaction per second would not cause them issues.
Here are the results after running my exploit code. As mentioned above, if they failed to implement any mitigations to prevent a bulk user enumeration attack, they are flagged as vulnerable.