External mails with spoofed email also signed with DKIM
I don't know if this problem related to dkim-exchange, but emails from external server with spoofed sender got also signed.
Goto https://www.wormly.com/test_smtp_server and send sample email with fake sender with own domain name (from [email protected] to [email protected]). Check signature, it's signed.
Nice way to break in with spam or infected attachments.
Jep, that may be a problem. A solution to this would be to check where the mail comes from, i.e. have a list with trusted sender IPs. For that it is necessary to add an additional field in the Configurator, since mails may also come from other internal or even external trusted servers and should be signed.
I think it's question about directions, DKIM agent must sign only outbound emails, not inbound.
The question is if it is possible to get this information within the source code. I need to investigate that further...
In RoutingAgent we can use mailItem.Message.RootPart.Headers.FindFirst("Received"); to resolve IP and compare with permitted signers. In our case it will be our external IP or it can be another itemlist in GUI as you said above.
@AlexLaroche can you look at this and see if there's a solution? (add it to the new mime_kit branch)
@avoidik : Can you draw your Exchange architecture (Edge and Hub server, spam filtring, etc.) and what your email traffic is configure to do (who reveice from external, from internal, relay!?, who send from internal, etc.)? I don't need private information, just the architecture to understand how your environnement is setup.
My environment is Exchange2010 SP3 CU11. Check out idea in pull request.
Should the better fix be to only sign outgoing emails and ignore incoming emails regardless of sender?
AFAIK it's impossible in RoutingAgent, need to change superclass to something else and rewrite whole agent.
The real problem isn't the incoming or outgoing emails.
A email server just forward email if it isn't the final destination.
The problem is that permit sender isn't correctly manage for your domain.
Restrict who can send email from your domain name in your organization to your Exchange server/email server (use AUTH).
It's also a good idea to activate SPF.
Check the follow example:
ABC don't want to expose their exchange on the Internet.
XYZ offer email service for their clients.
ABC contact XYZ and ask them if they can fronted Internet for them so al their email traffic will be send from their server.
XYZ accept in exchange of some money.
ABC forward their traffic to XYZ and XYZ will send the traffic to destination.
When XYZ will receive traffic for ABC, XYZ will send the traffic to ABC.
If XYZ receive traffic from traffic HYZ (using domain ABC), XYZ should check and see that only ABC and XYZ can send traffic from ABC domain.
Without DKIM Agent or not, you currently have a infrastructure problem.
The problem isn't the agent.
Powershell :
# Don't receive from anonymous if it's an authoritative domain
Get-ReceiveConnector “My Internet ReceiveConnector” | Get-ADPermission -user “NT AUTHORITY\Anonymous Logon” | where {$_.ExtendedRights -like “ms-exch-smtp-accept-authoritative-domain-sender”} | Remove-ADPermission
If you want to use external email service that you use your domain, they will have to implement authentificate email relay : http://geekswithblogs.net/ksellenrode/archive/2014/05/03/156170.aspx
@AlexLaroche I think what avoidik meant is that the DkimSigner Agent is checking every mail, this means outgoing and incoming (since both are sent through SMTP). (Correct me if I'm wrong) If someone sends a mail to my exchange server with a spoofed (=wrong) From address which matches the DKIM Signer configuration, it gets signed, but it shouldn't.
@Pro : The DKIM agent should sign ALL emails that the routing service receive. The routing service use Outgoing connectors. His job is to take the message and send it to the destination. Nothing more!
Exchange is base on three main process (SmtpReceive, Routing, Delivery).
- SmtpReceive will receive all incoming email. (Incoming connectors)
- Routing will forward the email to destination or to the next relay. (Outgoing connectors)
- Delivery will take the email and putting in the good mailbox.
The main problem in the case of avoidik is that his server receive a email from a untrusted source for a authoritative domain (able to be trusted, owned domain) and he accept the email from any servers in the Internet!! Exchange receive email from SmtpReceive (Incoming Connectors), the mailbox isn't in the current server so Exchange take the email and pass it to Routing process (Outgoing connectors). The Routing process take is message (sign the email because it send the email and match the domain to sign) and send it to the destination server (where the mailbox is store).
You have to see Exchange has a trusted subsystem. You have to validate at the source (Incoming connectors configuration) if the sender is spoofed, not in the DKIM signer.
@AlexLaroche I think what @avoidik means here is the following scenario:
- Your Exchange server has the following accepted domain:
example.com - Now use telnet or some other tool to submit an email to your server:
EHLO example.org
MAIL FROM: <[email protected]>
RCPT TO: <[email protected]>
DATA
SUBJECT: Test Mail
.
This is a standard mail delivery from external mail servers to your exchange server.
Now here comes the interesting part:
This test email is also routed through the DKIM signer, this means it also tries to sign incoming emails. So if you modify the commands above to use an existing user:
MAIL FROM: <[email protected]>
RCPT TO: <[email protected]>
The DKIM signer also signs the email because it thinks that it was received internally. (Open relay is of course disabled) Unforunately the Recipient Header field contains the server's ip as the first field and thus this can't be used to distinguish between outgoing and incoming.
We need to investigate how this can be avoided. Maybe evaluate all the Recipient Header fields instead of just the first one (as proposed in https://github.com/Pro/dkim-exchange/pull/117)?
I got those results within my test environment.
See also: https://msdn.microsoft.com/en-us/library/office/dd877035%28v=exchg.150%29.aspx
I think the correct field to check is the MailItem.Recipients[0].RecipientCategory (https://msdn.microsoft.com/en-us/library/microsoft.exchange.data.transport.mailitem.recipients.aspx)
For the above telnet SMTP delivery this has the value Incoming.
For an outgoing mail it has InDifferentOrganization
See https://msdn.microsoft.com/en-us/library/microsoft.exchange.data.transport.recipientcategory%28v=exchg.150%29.aspx
Or we can evaluate the X-MS-Exchange-Organization-MessageDirectionality header field as mentioned here: https://social.msdn.microsoft.com/Forums/office/en-US/9387e62a-76d7-4340-b9cc-f87ffcfab8b1/how-to-detect-the-message-source-in-an-exchange-server-2013-transport-agent-for-getting-the-sending?forum=exchangesvrdevelopment&prof=required
Checking the presense of the message header "X-MS-Exchange-Organization-MessageDirectionality" solves it.
It's set to "Originating" for e.g. outgoing OWA message.
For incoming messages via SMTP it's not yet set in the EndOfData event.
And later on in the routing events it's set to "Incoming".```
Here we need to find out which values are set for all the different use cases how someone can use Exchange to send messages (e.g. Outlook, OWA, Thunderbird over SMTP, Relay/SmartHost)
@Pro: Just remove the right (access) to receive email from anonymous to your external connector for your authoritative domains (domains, you have configure in exchange).
It's the job of the agent to do that. Give a try to my solution and you will see that your example is managed.
# Don't receive from anonymous if it's an authoritative domain
Get-ReceiveConnector “My Internet ReceiveConnector” | Get-ADPermission -user “NT AUTHORITY\Anonymous Logon” | where {$_.ExtendedRights -like “ms-exch-smtp-accept-authoritative-domain-sender”} | Remove-ADPermission
@AlexLaroche That solution will not work for people using external email filtering services (Gapps, Exchange Online Protection etc) combined with an increasing amount of online services that send email from your authoritative domains.
So we need bluelist then. Something like this was proposed in https://github.com/Pro/dkim-exchange/pull/117
@ablanken : Your concern can be address in the follow ways : Create a account in your Exchange environnement and grant appropriate rights.
For external email filtering services (Gapps, Exchange Online Protection, etc)
- Create a account with right “ms-exch-smtp-accept-any-Recipient” in Exchange
Get-ReceiveConnector –Identity “My Internet ReceiveConnector” | Add-ADPermission -User “<Domain>\<Account>” -ExtendedRights “ms-exch-smtp-accept-any-Recipient”
If your really trust the sender, You could even bypass Exchange Anti-Spam system
Get-ReceiveConnector "My Internet ReceiveConnector" | Add-ADPermission -user "<Domain>\<Account>" -ExtendedRights "ms-Exch-Bypass-Anti-Spam"
For online services that send email from your authoritative domains
- Create a account for application that need to send a email to your domain (All users in your domain can send email to your receive connector)
Get-ReceiveConnector “My Internet ReceiveConnector” | Get-ADPermission -user “NT AUTHORITY\Authenticated Users” | where {$_.ExtendedRights -like “ms-exch-smtp-accept-authoritative-domain-sender”}
If you really need anonymous receive connector, for security reasons, create a new receive connector and please open it access only point to point (via your firewall).
Reference for special Exchange Rights : https://technet.microsoft.com/en-us/library/jj673053(v=exchg.150).aspx
Why not refactor this as a SmtpReceiveAgent instead of RoutingAgent.. since this applies to the message whenever its being sent out via SMTP is when this should be done, not when in routing. since a message can get routed multiple times its easy to get multiple signs, which I had problems with.
Also it's easy to tell if the message is internal -> external or not using a combination of rcptArgs.SmtpSession.IsExternalConnection (takes into account authorized proxies, as well as localhost, and other exchange servers in the cluster) and checking to see if the source domain is in the signing list. This would prevent external servers from sending inbound with faked source and getting signed.
This sounds reasonable, but I'm currently not up to date on the capabilities/differences between the RoutingAgent and SmtpRecieveAgent. Also currently I don't have time to investigate that further. If you want, you can check if it is possible to use the SmtpReceiveAgent and modify the Source to create a Pull Request.
I would like to raise awareness of this issue. Messages with spoofed sender addresses are still signed so bogus messages bearing a sender address from the authoritative domain cannot be filtered out. Unfortunately, removing the right "ms-exch-smtp-accept-authoritative-domain-sender" from the receive connector does not work as suggested because this right is only evaluated for HubTransport connectors. However, the default receive connector on port 25 is a FrontendTransport. See https://docs.microsoft.com/en-us/answers/questions/203616/ms-exch-smtp-accept-authoritative-domain-sender-de.html