DKIM邮件协议的部署和管理情况研究
介绍
这是一篇来自USENIX Security 2022的论文,题目是《A Large-scale and Longitudinal Measurement Study of DKIM Deployment》,该论文做的是关于DKIM邮件协议的部署和管理情况的研究。
三种电子邮件身份认证协议
由于简单邮件协议(SMTP)缺少身份验证机制,IETF提出了三种电子邮件身份协议:
- 发件人策略框架(SPF):一种以IP地址认证电子邮件发件人身份的技术,接收邮件方会首先检查域名的SPF记录,来确定发件人的IP地址是否被包含在SPF记录里面,如果有,则认为是正确的邮件,否则会认为伪造的邮件并退回。
- 域密钥识别邮件(DKIM):通过消息加密认证的方式对邮件发送域名进行验证,邮件发送方发送邮件时,利用本域私钥加密邮件生成DKIM签名,将DKIM签名及其相关信息插入邮件头。邮件接收方接收邮件时,通过DNS查询获得公钥,验证邮件DKIM签名的有效性。从而确认在邮件发送的过程中,防止邮件被恶意篡改,保证邮件内容的完整性。
- 基于域的消息身份验证、报告和一致性(DMARC):是一种基于现有的SPF和DKIM协议的可扩展电子邮件认证协议,邮件收发双方建立了邮件反馈机制,便于邮件发送方和邮件接收方共同对域名的管理进行完善和监督。
论文贡献
- 对DKIM的部署和管理进行了首次大规模纵向测量研究,发现Alexa前100万个域中有28.1%启用了DKIM保护,其中2.9%管理不当。
- 发现DKIM密钥管理和DKIM签名问题在现实世界中非常普遍。
- 向受影响的电子邮件提供商报告漏洞,并提供在线DKIM测试工具,以提高DKIM部署的安全性。
背景
DKIM签名头和DKIM记录
DKIM签名头和DKIM DNS记录由多个标记=值对表示的不同信息元素组成。
DKIM签名头
DKIM签名头是DKIM签名不包括"b="标签的部分。DKIM签名在电子邮件中的示例如下。
DKIM-Signature:v=1;a=rsa-sha256;
c=relaxed/relaxed;s=s1;d=a.com;h=From:
To:Subject;l=200;bh=vFvy46eesudgj4s....;
b=IHEFQ+7rcisqsRBSEdd83....
| 参数 | 意义 |
|---|---|
| a | 用于生成DKIM签名的算法 |
| c | 消息规范化算法。默认值为“simple/simple”。simple不允许修改,relaxed允许常见修改 |
| s | 选择器,这是DKIM签名中的一个属性,允许在同一个域下使用多个密钥。电子邮件接收者使用此标记通过查询s1._domainkey.a.com获得公钥。 |
| d | 签名者的域 |
| h | h表示受签名保护的标头列表。必须包括“发件人”标题。 |
| l | 指示签名覆盖的电子邮件正文的字节数。 |
| bh | 由“l=”标记限制的消息规范化正文部分的哈希 |
| b | 整个电子邮件的实际数字签名,包括电子邮件正文和电子邮件标题。 |
DKIM记录
在DNS服务器上发布的DKIM记录示例如下。
v=DKIM1;k=rsa;h=sha256;
p=MIGfMA0GCSqGs......
| 参数 | 意义 |
|---|---|
| k | 密钥类型。默认类型为“rsa” |
| p | 公钥。空值表示公钥已被吊销。该标记值由“k=”标记定义,然后在base64中进行编码。 |
| h | 可接受的散列算法。此标记是可选的,默认允许所有算法(例如SHA-1和SHA-256)。 |
DKIM工作流程
DKIM工作的流程主要有三部分:
- 域名所有者首先生成一对密钥,并通过DNS TXT记录公布公钥(即DKIM记录),其格式为selector._domainkey.example.com。举个例子,如果a.com的所有者将s1设置为selector,DKIM记录就通过s1._domainkey.a.com的TXT记录来设置。
- 发送服务计算三个哈希值:邮件正文的哈希值(body-hash),选定的邮件标题的哈希值(h-headers),以及整个邮件的哈希值(data-hash)。其中,data-hash由body-hash、h-headers和DKIMS签名头组成(不包括"b="标签的值)。然后,电子邮件服务将签名data-hash,并将结果作为 "b="标签的值。最后,电子邮件服务将在头块中插入DKIM签名,并将电子邮件发送给收件人。
- 接收服务从发件人的DNS服务器检索公钥,以验证收到邮件时的DKIM签名。

测量思想
数据收集
- 被动DNS数据集:当收到带有DKIM签名的电子邮件时,支持DKIM的电子邮件服务器会检查公钥以验证DKIM签名。因此,DKIM记录可以被记录在接收邮件服务器所使用的DNS服务器中。这里面包含了大量域名的DKIM部署状态,同时记录了DKIM部署状态随时间的变化。通过匹配DNS TXT记录中selector._domainkey.example.com的domainkey来筛选其中的DKIM记录。
- 邮箱服务器记录:通过解析Coremail提供的记录中的邮件头,在DKIM签名中获得domains和selectors的相关信息,利用这些信息可以在DNS记录中进一步分析DKIM的部署情况。
数据处理
- 被动DNS数据的数据清理:
1.按域名聚合被动DNS记录,表示为5元组(请求的域名、DKIM记录内容、第一个请求时间戳、最后一个请求时间戳记和请求时间),如果域名的DKIM记录相同,通过扩展时间戳和请求时间来合并5元组记录。如果DKIM记录发生变化,我们将其视为两个不同的5元组记录。
2.开发语法分析器来过滤出违反标准的DKIM纪录。记录电子邮件服务器日志的重复数据消除
- 记录电子邮件服务器日志的重复数据消除
测量时只关注域名和DKIM签名的多样性,而不是电子邮件的数量。因此根据"d="tag(domain)和"s="tag(selector)来消除DKIM签名的重复性。
- 对Alexa前100万域名的主动扫描
1.进行主动扫描的前提是需要知道selector,因此先基于被动数据集统计出常见的10个selector。
2.使用这些selector来查找Alexa顶级域名的相应DKIM公钥记录
数据分析
测量的方面包括:
-
DKIM的采用率
- 对Alexa中排名前一百万的域名的数据进行了分析
- 对常规的邮箱提供商的DKIM使用情况进行了分析
- 统计DKIM的部署率,并和类似的SPF和DMARC进行了比较 DKIM记录的语法分析
- 标签不合法
- 异常的p字段
- 多个DKIM记录对应一个selector
- 不支持RSA-SHA256 DKIM的密钥管理问题
- 长期使用同一密钥
- 共享密钥
- 弱密钥 DKIM签名的安全性问题
- 弱签名
- 不安全的l=标签
- 过时的哈希算法
测量思路总结
测量方法主要从被动DNS数据集和主动扫描相结合出发。首先先分析DNS数据集和邮件服务器日志中提取相应的DKIM记录和DKIM签名头。对被动数据集中的DKIM记录进行数据清理,对邮件服务器日志中的DKIM签名进行重复数据删除。然后通过分析总结前10个selector,并用这些selector进行主动扫描Alexa Top 1M域获得DKIM公钥记录。利用这些信息从DKIM的采用率,DKIM记录的语法分析,DKIM密钥管理问题和DKIM的签名安全角度进行出发进行分析。

代码复现
由于没有被动的DNS数据集,代码复现的是主动扫描的过程,先将selector写入selector.txt中,将Aleax Top 1M写入Aleax Top 1M.txt中,用GO语言进行复现。
package main
import (
"bufio"
"fmt"
"io"
"net"
"os"
"strings"
)
func main() {
var count_obtain, count_not_obtain int = 0, 0
filepath := "E:/goproject/src/gocode/paperproject/DKIM/selector.txt"
file, err := os.OpenFile(filepath, os.O_RDWR, 0666)
if err != nil {
fmt.Println("Open selector file error!", err)
return
}
defer file.Close()
buf := bufio.NewReader(file)
for {
line, err := buf.ReadString('\n')
line = strings.TrimSpace(line)
filepath2 := "E:/goproject/src/gocode/paperproject/DKIM/Alexa Top 1M.txt"
file2, err2 := os.OpenFile(filepath2, os.O_RDWR, 0666)
if err2 != nil {
fmt.Println("Open Alexa file error!", err2)
return
}
defer file2.Close()
buf2 := bufio.NewReader(file2)
for {
line2, err3 := buf2.ReadString('\n')
line2 = strings.TrimSpace(line2)
txtrecords, _ := net.LookupTXT(line + "._domainkey." + line2)
for _, txt := range txtrecords {
fmt.Println(line2 + " " + txt)
count_obtain++
}
if err3 == nil {
count_not_obtain++
}
if err3 != nil {
if err3 == io.EOF {
break
} else {
fmt.Println("Read Aleax file error!", err3)
return
}
}
}
if err != nil {
if err == io.EOF {
break
} else {
fmt.Println("Read selector file error!", err)
return
}
}
}
fmt.Println("支持DKIM的有", count_obtain)
fmt.Println("不支持DKIM的有", count_not_obtain)
}

该论文详细介绍了DKIM邮件协议的背景、工作流程、部署情况和管理问题。研究发现,28.1%的Alexa前100万个域启用了DKIM,但2.9%存在管理不当。论文通过大规模数据收集和分析,揭示了DKIM密钥管理和签名的常见问题,并提供了在线测试工具以提升安全性。

2547

被折叠的 条评论
为什么被折叠?



