Revisiting Email Spoofing

31 Dec 2018 • Written by alxk

Revisiting Email Spoofing

Email spoofing is still a thing and organizations are at risk of receiving legitimate-looking phishing emails from spoofed domains.

This post will give a cursory overview of the methods used to prevent email spoofing and introduce a tool to remotely identify domains with misconfigured anti-spoofing measures. It will then show a practical example of spoofing a popular service’s domain to send a phishing email.

I will also outline an interesting way I was able to bypass an organization’s external email filter to phish employees with internal emails.

SPF, DKIM and DMARC

Email dates from the days the Internet was a trusted network and people were expected to behave. As such, the original protocols simply trust senders to be who they say they are. You can send an email claiming to be Google, the President or anyone else from any box on the Internet using a tool like sendmail.

The onus is on recipients to verify the identity of email senders. To this end, three methods were introduced. These are explained in a cursory and rather simplified manner in this post; readers interested in a more detailed introduction are encouraged to start by the respective Wikipedia pages.

Sender Policy Framework (SPF)

SPF lets recipients know which IP addresses a domain owner expects his emails to originate from. To enable SPF, the domain owner must configure a special DNS TXT record. An SPF record for the fictional Contoso organization is shown below:

$ dig +short txt contoso.com
"v=spf1 ip4:147.243.128.24 ip4:147.243.128.25 -all"

This record indicates that the owners of contoso.com expect emails from @contoso.com to originate from either 147.243.128.24 or 147.243.128.25 on the Internet. If the recipient is getting this email via a TCP connection from another source IP, the email should fail SPF validation.

The qualifier of the last argument all is important:

DomainKeys Identified Mail (DKIM)

DKIM allows senders to sign emails by adding an email header containing a signature and the information necessary to fetch the public key needed to validate the signature.

An example DKIM signature header is shown here:

DKIM-Signature: v=1; a=rsa-sha256; d=example.com; s=news;
c=relaxed/relaxed; q=dns/txt; t=1126524832; x=1149015927;
h=from:to:subject:date:keywords:keywords;
bh=MHIzKDU2Nzf3MDEyNzR1Njc5OTAyMjM0MUY3ODlqBLP=;
b=hyjCnOfAKDdLZdKIc9G1q7LoDWlEniSbzc+yuU2zGrtruF00ldcF
VoG4WTHNiYwG

In the example above, the bh value is a hash of the email body while the b value contains the signature. Recipients can use the s selector value to fetch the public key via DNS:

$ dig +short txt news._domainkey.example.com
"k=rsa; t=s; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChK0RIGEj4ahkPXIhENbmXC6Cu2Q1eVNDM6nZdrJGR2p4jWYNVGQ/EYQRC35Qu+rBcvNvayv8igvCou1A9Y6xso1ls6MCMpT3LjatFo+U+qfMI9Uh6P0sQ+NNS7NAGc0GGl8bAxi+mbG0AHgbgrB6DTJwAz7uGd0IzjPtPdn5EuQIDAQAB"

Domain Message Authentication Reporting & Conformance (DMARC)

DMARC is simply a way to tell recipients how to treat emails that fail SPF and DKIM validation, and where to send reports to help domain owners identify dubious activity and debug issues. DMARC is also configured via a DNS TXT record:

$ dig +short txt _dmarc.contoso.com
"v=DMARC1; p=reject; rua=mailto:report@contoso.com; ruf=mailto:d@contoso.com;"

The policy value p tells recipients how to treat emails that fail SPF and DKIM validation. A policy of reject, as you guessed it, instructs recipients to discard such emails. The rua and ruf values specify emails to send two different types of diagnostic reports to.

The Good

Regardless of SPF and DMARC configurations, you are unlikely to be able to fool robust email providers like GMail.

Google has the big data and the heuristics to provide anti-spam and anti-phishing measures that don’t rely on SPF and DMARC. I briefly tried spoofing domains with lax SPF and DMARC records to a Gmail address: all emails landed in the spam box (but were not rejected).

The Bad

If you start checking the SPF and DMARC records for a lot of organizations you’ll notice weak configurations are plentiful. SPF soft fails are widespread and DMARC policies other than reject and quarantine are quite common.

Even github.com has a none DMARC policy, meaning GitHub doesn’t want recipients to reject any emails from @github.com, even if both SPF and DKIM fail:

$ dig +short txt _dmarc.github.com
"v=DMARC1; p=none; rua=mailto:dmarc@github.com"

The reason is that many companies rely on third-parties to send emails on their behalf for marketing and other purposes.

SPF records can be hard to keep accurate when third parties can’t provide an extensive list of IP addresses, and the ephemeral nature of many modern services means these addresses could change on a regular basis. Sharing DKIM keys with third parties may also be logistically difficult (not the mention the security implications).

Rather than risk legitimate emails getting blocked, many organizations favor lax email validation rules.

As a result, we can probably send emails as @github.com to most people who are not behind a decent email filter like GMail’s.

Note that even when main domains, such as contoso.com, have SPF and DMARC adequately configured, the organization likely has other domains. What do the DNS records look like for contoso-sales.com?

The Ugly

Firstly, a number of organizations have SPF, DKIM and DMARC validation turned off on their inbound email filtering systems (remember that it is up to recipients to validate inbound emails). I can’t give any meaningful metric as I’ve only sampled a negligible number in the grand scheme of things, but I’ve seen it enough to believe that the possibility should not be discarded by red teams and pentesters.

Reasons for having inbound validation disabled range from the good old “it’s the default configuration” to an explicit desire to have email “just work”. Given the amount of misconfigured DNS records out there, it’s not surprising that organizations would find legitimate, if invalid, inbound emails getting blocked.

Naturally, disabled validation leaves the organizations open to some clever phishing attacks impersonating trusted external sources with rigid email validation rules. But even with validation enabled, there are plenty of reputable domains with lax validation policies to abuse.

Note that you will likely not be able to send emails from @contoso.com to another @contoso.com email address even if the SPF and DMARC records are poorly configured, and even if inbound email validation is disabled. Trying to deliver an internal email from an external source should usually fail.

Spoofing Third Parties

The easiest way to tell if an organisation is enforcing validation is to give it a spin. Contoso is actually enforcing DMARC so you can’t send them an email from @google.com:

$ apt install opensmtpd sendmail
$ printf "Subject: Chrome Security Update\n\nAn important security update is available for Chrome. It is important that you update now https://www.google-chrome-update.com/download" | sendmail -i -t -v -f "security.update@google.com" -t "john.wick@contoso.com"
...
050 >>> MAIL From:<security.update@google.com>
050 250 2.1.0 Sender ok
050 >>> RCPT To:<john.wick@contoso.com>
050 >>> DATA
050 250 2.1.5 Recipient ok
050 354 Enter mail, end with "." on a line by itself
050 >>> .
050 550 5.7.0 Email rejected per DMARC policy

Even then, GitHub and its DMARC p=none flies right through:

$ printf "Subject: GitHub Password Reset\n\nHey John, it's time to reset your GitHub password: https://github-account-manager.com/reset" | sendmail -i -t -v -f "security@github.com" -t "john.wick@contoso.com"
...
050 >>> MAIL From:<security.update@github.com>
050 250 2.1.0 Sender ok
050 >>> RCPT To:<john.wick@contoso.com>
050 >>> DATA
050 250 2.1.5 Recipient ok
050 354 Enter mail, end with "." on a line by itself
050 >>> .
050 250 2.0.0 8xy123pkud-1 Message accepted for delivery

Spoofing GitHub lands directly into John Wick’s Contoso inbox. His client even conveniently fetched the domain’s favicon:

github spoof

I submitted multiple open bug bounty reports to various companies in the same situation as GitHub, knowing that they were likely already aware of the issues. As suspected, the reports were acknowledged, thanks were given, but issues with these configurations are known, intentional and will not be fixed.

Bypassing External Filters (Sometimes)

Phishing-aware organizations will configure their inbound mail filter to tag external emails with some kind of warning to their employees. This can take the form of a subject line prefix (Subject: "EXTERNAL: Hello World") or of a message added to the body of the email (THIS MESSAGE ORIGINATES FROM OUTSIDE YOUR ORGANIZATION. BE CAREFUL.).

Let’s assume that the fictional company ACME (acme.org) is a subsidiary of Contoso (contoso.com). Given the relationship, the Sys Admins at Contoso have decided to not enforce the external filter for acme.org, and vice-versa. As a result emails between ACME and Contoso essentially appear as internal communications, whereas emails from other sources are tagged as external.

Unfortunately acme.org is configured with a DMARC policy of none:

$ dig +short txt _dmarc.acme.org
"v=DMARC1; p=none; rua=mailto:dmarc@acme.org"

At this point, you’ve probably guessed it: on a recent engagement I was able to send emails to @contoso.com impersonating any source from @acme.org, bypassing the external filter and blending in as internal communication. This opens the door to all kinds of phishing attacks such as impersonating Sys Admins, management, HR or an automated internal system.

If we wanted to receive email responses to these phishing attempts, we could try setting the Reply-To header to an external email address we can read.

mailspoof

mailspoof is a tool I wrote to quickly scan a large list of domains for misconfigured SPF and DMARC records.

Conclusion

If you’re a red team:

If you’re an organization:


kubelet: anonymous to cluster-admin
Security-focused CI/CD Pipeline