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
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:188.8.131.52 ip4:184.108.40.206 -all"
This record indicates that the owners of
contoso.com expect emails from
@contoso.com to originate from either
220.127.116.11 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:
-allis a hard fail: if the email fails SPF validation, the
contoso.comowners want the email to be discarded.
~allwould be a soft fail; if the email fails SPF validation, the
contoso.comowners wish the email to be allowed through, but perhaps be treated as slightly suspicious (by, for example, raising a spam score).
+allwould result in a pass regardless of the sources in the preceding arguments.
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:firstname.lastname@example.org; ruf=mailto:email@example.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
ruf values specify emails to send two different types of diagnostic reports to.
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).
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
quarantine are quite common.
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:firstname.lastname@example.org"
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
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
$ 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 "email@example.com" -t "firstname.lastname@example.org" ... 050 >>> MAIL From:<email@example.com> 050 250 2.1.0 Sender ok 050 >>> RCPT To:<firstname.lastname@example.org> 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 "email@example.com" -t "firstname.lastname@example.org" ... 050 >>> MAIL From:<email@example.com> 050 250 2.1.0 Sender ok 050 >>> RCPT To:<firstname.lastname@example.org> 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
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.
acme.org is configured with a DMARC policy of
$ dig +short txt _dmarc.acme.org "v=DMARC1; p=none; rua=mailto:email@example.com"
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 is a tool I wrote to quickly scan a large list of domains for misconfigured SPF and DMARC records.
If you’re a red team:
- Enumerate your target’s parent and subsidiary companies and their domains, as well as any external SaaS they may use.
- Identify domains with weak SPF and DMARC configurations.
- You may be able to bypass external filters by spoofing parent and subsidiary companies.
- You may be able to spoof a trusted external SaaS to harvest credentials or entice a download (note that there are legal considerations around spoofing a third-party unrelated to your engagement).
If you’re an organization:
- Review your inbound email filtering solution: ensure SPF, DKIM and DMARC validation are enabled. Emails that fail validation should be quarantined.
- If you need to whitelist external domains, or treat them as internal domains, check that the domains’ SPF and DMARC records are well configured so that they cannot be spoofed.
- Review your own SPF and DMARC records. You want SPF to hard fail and DMARC to have a
rejectpolicy for both domains and subdomains.
- Ensure all of your domains have SPF and DMARC configured. Even if
contoso.comis properly configured, you don’t want attackers sending emails from