Disclaimer: This article is not an “Email Spoofing 101”. Spoofing examples are presented only for testing and prevention purposes.
Ensuring email security might be one of the most important and most difficult tasks an administrator must face. Every day, servers process thousands of emails and controlling such a big mail flow is not easy. No wonder hackers focus on this channel when they plan attacks. They use various tricks to make users think that opening a suspicious attachment is a good idea.
One of the tricks they use is email spoofing.
What is email spoofing?
Email spoofing is a very popular attack method. The sender modifies message headers so that emails appear as sent from someone else. Hackers use it, for example, to impersonate employees of a company to obtain login credentials, personal data, or other confidential information. Two most common ways to protect your organization from external spoofing attacks are:
- An SPF record – a list of IP addresses which are authorized to send emails from a domain.
- DKIM check – an email authentication method. It enables you to sign and verify email messages using public and private keys. The public keys, published in the DNS records are used to verify if the message comes from the original sender. You cannot configure it on the Exchange Server natively – you require a plugin for SMTP gateway.
Both ways give good results when fighting with external spoofing. The problem starts when we come across internal spoofing when one employee tries to impersonate a colleague. It might be a joke, or to achieve some benefits – either way, it can sabotage a company in a number of ways:
- Cause chaos,
- Induce material damage,
- Harm data integrity,
- Damage the company reputation.
What is worse, fighting internal spoofing attempts requires a slightly different approach. I will now present how to prevent internal email spoofing in an Exchange organization. But first, a quick specification of the test environment:
For presentation and test purposes I will use the following machines:
– Windows Server 2012 as a Domain Controller. The domain name is domain128.lab , IP 192.168.23.1
– Windows Server 2012 R2 with Exchange 2016 CU3, IP 192.168.23.2, 192.168.170.79
– Windows 10 with Outlook 2013, IP 192.168.23.3
– Windows 7, IP 192.168.23.4
Now for the proper part. I will show how email spoofing attacks are performed and how to prevent them:
Internal email spoofing
First, let us see how an employee can masquerade as another user when sending an email. A single PowerShell cmdlet is enough to achieve that. In the example below, email@example.com impersonates firstname.lastname@example.org and sends an email to email@example.com
The cmdlet used by user1 is as follows:
Send-MailMessage –SmtpServer 192.168.23.2 –To firstname.lastname@example.org –From email@example.com –Subject “It`s me user3” –Body “Send me your report”
Of course, such email should not do any harm. If the user2 replies to the message, the email will go to user3, not the attacker. The problem is that after some modifications, Send-MailMessage can send HTML emails with malicious links or attach an infected file. I will not go through examples of how spoofing can be used to harm an organization, but believe me; there are many.
The same trick can be achieved by using the Telnet Client. The Telnet Client is not installed by default, but you can go to Control Panel > Programs > Turn Windows features on or off and select Telnet Client there to turn it on. To test internal email spoofing, run cmd.exe and connect to your server on port 25 by inserting:
Telnet 192.168.23.2 25
Just remember to substitute the IP address with yours.
Next, using SMTP commands, you can send an email:
HELO domain128.lab (connects to your domain)
MAIL FROM: firstname.lastname@example.org (address of the user you want to impersonate)
RCPT TO: email@example.com (your victim’s address)
DATA: it enables you to specify subject and body of your email. Enter a full stop (.) in a new line to finish data input.
Both methods end with the same result:
For a more realistic situation, a similar attack deployed in a different environment looks like that:
As you can see, the email does not differ from any other message, sent by normal means. It is very easy for the recipient to fall for this trick. As an administrator, you can detect such action in Exchange logs, but in a larger organization with a lot of users and intensive mail flow, it will be troublesome, to say the least. Not to mention that the harm can be done before such an attempt is detected. So why Exchange permits such behavior? And how to block it?
In a default Exchange deployment, a Receive connector is created. Default Frontend (your server’s name) is configured so that it:
- receives from all IP addresses
- Uses the default SMTP port 25 to receive emails
- Enables emails from anonymous users
This last point is what enables internal users to abuse the mailing system. Unfortunately, turning the permissions for anonymous users off would also block receiving emails from external email addresses. Well, I do not know in what environment that would be a reasonable option.
How to prevent internal email spoofing
There are probably many third party solutions which fight this threat, but in this article, I will only present how to rule out spoofing inside an organization using native Exchange mechanisms. There are two methods I will demonstrate:
- How to block spoofing attempts using SPF record,
- How to prevent internal spoofing with a dedicated Receive connector
Using SPF record
As I have already mentioned while describing external attacks, one of the most popular (and effective) weapons against spoofing attempts is using the SPF record. See the syntax of an SPF record, below:
V=spf1 ip4:your_server’s IP –all
To put it simply, SPF records reside in DNS zone file. They specify IP addresses of servers which are allowed to send emails from a certain domain (more on creating SPF record). The mechanism can be used to secure internal correspondence analogically to the way it is normally used for external communication. For this method to work for internal email spoofing, you will need to configure three elements:
- An SPF record in local DNS,
- Antispam functionality in Exchange Server,
- A Sender ID agent.
Before I walk you through the configuration process, I will talk about its major drawback. To block internal email spoofing completely using this method, you have to include all IP addresses which are allowed to send emails in your network (this includes printers, applications, and other web objects). This is not the most convenient solution if you have a vast network with loads of various devices. But if you do not have an overwhelming infrastructure and you know it like the back of your hand, the solution should work well.
Step by step walkthrough
- First, you should create the txt record on your DNS server in the local domain. In my case, the record will look like this:
v=spf1 ip4:192.168.23.2 ip4:192.168.170.79 ip4:192.168.169.51 –all
192.168.23.2 and 192.168.170.79 are the IP addresses of my Exchange Server, while 192.168.169.51 is the IP address of my web printer in another subnetwork. The printer sends emails to Exchange.
- The next step is the installation of Exchange Antispam Agent. You can use PowerShell to do that. The cmdlet is:
Successful installation should look like that:
- Now for the changes to apply, restart your MSExchangeTransport service:
- Provide all Exchange Servers’ IP addresses:
I have to provide two addresses because my Exchange Server has two network interfaces.
- We are almost done. Now, you have to configure a rule which rejects emails from addresses which are not included in your SPF record. The PowerShell cmdlet is:
Set-SenderIdConfig –SpoofedDomainAction Reject
- All that is left is to test if the current configuration successfully blocks internal spoofing attempts, as it should. I will use the same cmdlet I presented at the beginning of the article. Instead of sending an email, the attacker should get the following error:
As you can see, the Exchange server blocks the attempt and displays error 5.7.1 “Sender ID <PRA> Not Permitted.
The effect will remain the same even if the user enters their own mailbox in the –From attribute:
Finally, let us check what happens if I try to masquerade as another user on a machine with IP address 192.168.169.51 (the one I added to the local SPF record before):
The mail went through without a problem:
This example shows another drawback of the SPF record method. Because the authentication bases on the sender’s IP, the wrong configuration will not guarantee that your company is completely guarded against internal spoofing.
Implementing this method does not influence sending emails from email clients (Outlook, OWA or ActiveSync) because they use RPC or MAPI over HTTP through a different port (443 or 80).
Using a dedicated Receive connector
The second method is creating an additional Receive connector on the port 25. The connector controls the local network and lets through only emails from domain users. This approach uses a different authorization method. Instead of using IPs, it uses domain credentials (login and password). The change of the authorization method generates one problem – all internal Exchange connections have to be authorized. In other words, every web device and application which sends emails to Exchange requires a domain account (or, at least, they can have one, common account).
As I have mentioned before, the connector will be set for the TCP port 25. But, as you may know, there is already a Receive connector, which accepts anonymous connections from SMTP servers on port 25. So how can this connector coexist with the one you are about to create? And how does Exchange know which one to choose? Exchange Server is quite intelligent when it comes to this. The server will always choose the more precise connector for each connection. The Receive connector I configure is defined for LAN networks, while the default one applies to all connections. Hence, for internal SMTP connections, Exchange will always choose the new connector, specified for LAN.
Step by step walkthrough
The second method, apart from being more secure, is easier to implement. That is because it requires only to create a new Receive connector. You can use a nice PowerShell cmdlet for that. I will use Internal Client SMTP name for the connector so that I can identify it easily later. Remember, the IP ranges are personalized for my environment:
New-ReceiveConnector –Name ”Internal Client SMTP” –TransportRole FrontendTransport –Usage Custom –Bindings 0.0.0.0:25 –RemoteIPRanges 192.168.23.0/24,192.168.170.0/24 –AuthMechanism TLS,Integrated –PermissionGroups ExchangeUsers
I should also be able to create it in Exchange Administration Center > Mail Flow > Receive Connectors > New:
The settings are analogical to those used in the cmdlet above. The connector should be internal, and the role should be set to Frontend Transport… Unfortunately, the default Role is Hub Transport, and it seems I cannot change it to the option I need. Let us go on and see what happens, anyway.
The next page is very important – that is where you have to specify all LAN networks you have in your organization. In my case, it is 192.168.23.0/24 and 192.168.170.0/24.
That is where Exchange throws an error.
The values that you specified for the Bindings and RemoteIPRanges parameters conflict with the settings on Receive connector “ENV128-E2016\Default Frontend ENV128-E2016”. Receive connectors assigned to different Transport roles on a single server must listen on unique local IP address & port bindings.
It seems that Exchange does not like having two connectors with different Transport roles listening to the same port. But the two roles are different only because an option was grayed out… Which is peculiar, considering the fact that a single cmdlet did not throw any errors. You can check if you encounter the same bug, but my advice is to just go with the PowerShell.
The connector (regardless of how you create it) should appear on the list:
Now for the testing. user1 will try to send a message to firstname.lastname@example.org as email@example.com.
The PowerShell command already used a couple of times in this article does not send an email this time. The error code is different from the one which appeared using the previous method: 5.7.60 SMTP; Client does not have permission to send as this sender.
Ok, what if the user tries the same trick after providing his/her credentials?
Good, still no luck. But when the same user stops trying to appear as someone else:
The cmdlet does its job. The today’s victim, firstname.lastname@example.org can read the message along with its original sender:
Internal spoofing attempts are also blocked if the malicious user tries using telnet:
As an Exchange Server administrator, you have to be aware that the default Exchange deployment is not enough to protect your users from malicious emails. Fortunately, you can use this guide to prevent internal email spoofing once and for all. Both methods is based on native Exchange mechanisms, all you need is a little effort.