Tag Archive: mail


Another well extended measure to add security to the SMTP protocol (when will we stop applying patches and move on to a new protocol?) is known as DKIM.

This stands for DomainKeys Identified Mail and as you can imagine, it’s based on some PKI concepts.

The general idea is fairly simple, the server signs every mail before sending it and publishes its public key through (drums…) a DNS record! You certainly didn’t expect this one, did you?

Let’s see an example. I’ll send me an email from Facebook which is one of the big DKIM adopters. Checking the SMTP headers we find the following:

DKIM-Signature: v=1; a=rsa-sha1; d=facebookmail.com; s=q1-2009b; c=relaxed/relaxed;
q=dns/txt; i=@facebookmail.com; t=1244588132;
h=From:Subject:Date:To:MIME-Version:Content-Type;
bh=JfuLVdMFj4tE3DQJ7E3AUmszqaY=;
b=d46czRF6YMvrFofJsHpQyBOnHqKbkfO7rnjtvr5POMTEq1mLtc04NQHxeJANwQpo
aBcfAqB5vedMP9zsL6MqPQ==;

I don’t know you, but that thing at the end looks like a bunch of Base64 encoded to me. Some of the important fields here are

  • v=1, no words needed.
  • a=rsa-sha1, stands for the algorithms used.
  • d=facebookmail.com, the domain.
  • s=q1-2009b, the selector, used to determine what DNS record to query.
  • c=relaxed/relaxed, means that the system will be tolerant to modifications made to the email in transit.
  • b=(chunk of Base64 encoding), the signature itself.

Let’s query the DNS for the public key. We know that the DNS record that hold this is of the form selector._domainkey.domain, in this particular case

carlos@pattern:~$ dig @dns05.sf2p.tfbnw.net q1-2009b._domainkey.facebookmail.com
txt

; <<>> DiG 9.5.0-P2 <<>> @dns05.sf2p.tfbnw.net q1-2009b._domainkey.facebookmail.
com txt
; (1 server found)
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48012
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;q1-2009b._domainkey.facebookmail.com. IN TXT

;; ANSWER SECTION:
q1-2009b._domainkey.facebookmail.com. 3600 IN TXT “k=rsa\; t=s\; p=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKrBYvYESXSgiYz

KNufh9WG8cktn2yrmdqGs9uz8VL6Mz44GuX8xJAQjpmPOb
e6p2vfTMWeztKEudwY6ei7UcZMCAwEAAQ==

;; AUTHORITY SECTION:
facebookmail.com.       172800  IN      NS      dns04.sf2p.tfbnw.net.
facebookmail.com.       172800  IN      NS      dns05.sf2p.tfbnw.net.

[follows not relevant info.]

Before doing anything I would like to get more info about this RSA key, so I’ll write a PEM container and name it pub.key

A detail worth to mention, that will save you a lot of time is that the specification states that every line should have exactly 64 chars, except the last one, which could be shorter.

—–BEGIN PUBLIC KEY—–
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKrBYvYESXSgiYzKNufh9WG8cktn2yrm
dqGs9uz8VL6Mz44GuX8xJAQjpmPObe6p2vfTMWeztKEudwY6ei7UcZMCAwEAAQ==
—–END PUBLIC KEY—–

With the help of Openssl we could check the validity of this key, as follows

carlos@pattern:~$ openssl rsa -pubin -in pub.key -text
Modulus (512 bit):
00:aa:c1:62:f6:04:49:74:a0:89:8c:ca:36:e7:e1:
f5:61:bc:72:4b:67:db:2a:e6:76:a1:ac:f6:ec:fc:
54:be:8c:cf:8e:06:b9:7f:31:24:04:23:a6:63:ce:
6d:ee:a9:da:f7:d3:31:67:b3:b4:a1:2e:77:06:3a:
7a:2e:d4:71:93
Exponent: 65537 (0×10001)
writing RSA key
—–BEGIN PUBLIC KEY—–
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKrBYvYESXSgiYzKNufh9WG8cktn2yrm
dqGs9uz8VL6Mz44GuX8xJAQjpmPObe6p2vfTMWeztKEudwY6ei7UcZMCAwEAAQ==
—–END PUBLIC KEY—–

So we are, in fact, dealing with a 512 bit RSA key.

What I would like to do now is decrypt the b field with the public key and compare the hashes in order to verify that I didn’t miss anything.

However there is still a little problem though. We don’t know exactly which part of the email has been included in the SHA-1 hash.

Wait a minute, who said panic? The answer resides of course in the DKIM-Signature header, specifically in the h parameter, which indicates which headers have been included in the hash process.

I tried to decrypt the signature using OpenSSL but I found it too unflexible, so I’ll do it manually. I still need to code some RSA decryption program (using OpenSSL libraries) to get the original hash and compare it to the SHA1 hash of the original message body and selected headers.

This will take me some time, so until then enjoy the reading ;)

Mail protection measures: SPF

Let’s face it. SMTP has been a mess for security since the beginning. But what is the state of the current efforts to secure this “not built with security in mind” service?

SPF (Sender Policy Framework)

As the name suggests, this method is thought to attack the problematic of sender address forgery.

The solution is based on DNS (great, another service designed without security in mind) and basicly consists on the organization establishing a policy that states which servers are able to forward email for this domain. This is performed through TXT records in the authoritative servers of the forementioned organization.

This way, when a server receives an email with a sender address belonging to this organization (in the MAIL FROM field), checks first if the IP address used in the HELO command is allowed to forward email for the domain. To do this check, it queries the following record from the domain’s DNS server:

carlos@pattern:~$ dig @208.67.222.222 nscglobal.com ns

; <<>> DiG 9.5.0-P2 <<>> @208.67.222.222 nscglobal.com ns
; (1 server found)
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26587
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;nscglobal.com.                 IN      NS

;; ANSWER SECTION:
nscglobal.com.          85371   IN      NS      a.ns.joker.com.
nscglobal.com.          85371   IN      NS      b.ns.joker.com.
nscglobal.com.          85371   IN      NS      c.ns.joker.com.

;; Query time: 49 msec
;; SERVER: 208.67.222.222#53(208.67.222.222)
;; WHEN: Mon Jul  6 21:36:06 2009
;; MSG SIZE  rcvd: 88

Now that we know the nameservers for this domain, let’s query them for the TXT records, one of them being the SPF record:

carlos@pattern:~$ dig @a.ns.joker.com nscglobal.com txt

; <<>> DiG 9.5.0-P2 <<>> @a.ns.joker.com nscglobal.com txt
; (1 server found)
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58587
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 3
;; WARNING: recursion requested but not available
carlos@pattern:~$ dig @a.ns.joker.com nscglobal.com txt

; <<>> DiG 9.5.0-P2 <<>> @a.ns.joker.com nscglobal.com txt
; (1 server found)
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43969
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 3
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;nscglobal.com.                 IN      TXT

;; ANSWER SECTION:
nscglobal.com.          86400   IN      TXT     “v=spf1 mx ip4:217.77.187.125 ip
4:195.217.168.151 ?all”

;; AUTHORITY SECTION:
nscglobal.com.          86400   IN      NS      a.ns.joker.com.
nscglobal.com.          86400   IN      NS      b.ns.joker.com.
nscglobal.com.          86400   IN      NS      c.ns.joker.com.

;; ADDITIONAL SECTION:
a.ns.joker.com.         7200    IN      A       207.44.185.10

[truncated for simplicity]

Let’s analyze the info contained in this text record,

nscglobal.com.          86400   IN      TXT     “v=spf1 mx ip4:217.77.187.125 ip4:195.217.168.151 ?all”

The SPF version used is 1 (v=spf1)

The MX records for this domain are allowed to forward email in behalf of it, obvious (mx).

Those two individual IP addresses (if not mask is specified /32 is used) are allowed as well.

And now the mystery record: ?all, this is different in the sense that it has attached a symbol at the beginning, in this case “?”.

Well, the truth is that all of them have one appended but the default is “+” and is not shown. The SPF record is, besides the version information, a list of so called mechanisms with modifiers attached. It’s similar actually to an ACL and is read sequentially as well.

Some of the most common mechanisms are all, ip4, ip6, a, mx, etc.

It’s clear that ip4, ip6 match ranges of IP addresses, while a, mx matches an A and MX record for this domain respectively. The meaning of all shouldn’t be a surprise either and why it appears always at the end… yes, it’s the default rule in an ACL and for this reason is one of the most important parts of a SPF record.

What about the modifiers? There are four of them:

“+” : Pass

“-” : Fail

“~” : SoftFail

“?” : Neutral

The action associated with each modifier is the following:

Result Explanation Intended action
Pass The SPF record designates the host to be allowed to send accept
Fail The SPF record has designated the host as NOT being allowed to send reject
SoftFail The SPF record has designated the host as NOT being allowed to send but is in transition accept but mark
Neutral The SPF record specifies explicitly that nothing can be said about validity accept
None The domain does not have an SPF record or the SPF record does not evaluate to a result accept

Notice that, in contrast with an ACL, unless specified, the default behaviour if a match is not found is to accept the email.

Finally we can read and interpret the SPF record for our company, with sad results…

Allow my MX’s, those two hosts and with the rest of the emails coming from IP addresses not belonging to the company, claiming to be from our company… We can’t say anything about the validity, so let them through! This is basicaly equivalent to not implementing a policy.

Most of the companies have a default rule like “-all” instead of “?all”, effectively dropping the spoofed emails.

As an example, the berliner-sparkasse.de SPF record:

carlos@pattern:~$ dig @ns.bankgesellschaft.de berliner-sparkasse.de txt

; <<>> DiG 9.5.0-P2 <<>> @ns.bankgesellschaft.de berliner-sparkasse.de txt
; (1 server found)
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7877
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;berliner-sparkasse.de.         IN      TXT

;; ANSWER SECTION:
berliner-sparkasse.de.  100     IN      TXT     “v=spf1 ip4:212.121.135.74 ip4:193.31.187.5 ip4:193.31.187.9 ip4:194.37.255.0/24 ip4:91.198.224.0/24 ip4:62.181.134.163 ip4:62.181.134.164 ip4:62.181.134.165 ip4:62.181.134.166 ip4:212.222.91.0/24 ip4:62.50.32.0/19 -all”

;; AUTHORITY SECTION:
berliner-sparkasse.de.  28800   IN      NS      sec2.dns.psinet.de.
berliner-sparkasse.de.  28800   IN      NS      sec1.dns.psinet.de.
berliner-sparkasse.de.  28800   IN      NS      sec3.dns.psinet.de.
berliner-sparkasse.de.  28800   IN      NS      ns.bankgesellschaft.de.

As you can see, the Berliner Sparkasse defines pretty clearly which networks are allowed to relay email for this domain and denies explicitly all the other incoming email.

Now what about the efficiency of this method? Well, its basis are the DNS entries so it has all the vulnerabilities inherent to this protocol. For a regular spammer it wouldn’t be practical to fake the DNS answers but for a very decided individual it could be easy to fake an email and the credibility would be respalded for the SPF mechanism itself.

Powered by WordPress | Theme: Motion by 85ideas.