delphij's Chaos

选择chaos这个词是因为~~实在很难找到一个更合适的词来形容这儿了……

31 Oct 2006

VERP邮件地址的一个安全问题

前一阵在为cn.freebsd.org的邮件列表做维护时发现,由于网易的邮件系统无法正确地(更具体地说,是以符合标准的方式)进行退信,导致一些无效地址仍然在不停地接收邮件,导致邮件系统的管理员必须手动处理这些退信产生的报告。后来在挖掘了mailman的文档之后,发现它支持djb的VERP退信。

相比处理符合标准的退信来说,VERP所需的编码量更少,并且对于不符合标准的退信也能够做很好的处理。从开销上说,由于VERP不需要parse整封邮件,因此也不会导致性能上的折损,甚至由于不需要进行任何解信操作,这种做法在性能上应该会优于标准的做法。

然而仔细思考一下,我们会发现VERP存在一个很严重的问题,即退信的可伪造性。并且,更令人悲观的是,这个问题其实并不仅仅是VERP的问题。[E]SMTP协议在设计时对于安全方面的考虑不多,最显著的问题就在于它的发件人是可以伪造的。在利用VERP进行发信时,这个问题也随之而来。

下列攻击是可行的,并且目前没有有效的解决方法:

  • 计算VERP退信地址
  • 向这个地址发送若干空白邮件

于是,从VERP中解码的邮件地址,便从邮件列表中删除了。

对于普通的邮件列表来说,这可能并不是一个问题,因为这类零和攻击(攻击和被攻击者均有损失)只有白痴会去做;然而,对于派发包含重要通知信息,特别是安全更新一类信息的邮件列表来说,这就非常可怕了。我现在想到的一种方法,是将一个salt序号,加上salt与原VERP地址的SHA值作为后缀编码到VERP地址中。接到退信时,验证salt序号是否过期,如果没过期则取出本地序号相同的salt,重新计算散列值比较。

不过,这种方法的计算复杂性要高于原始的VERP。我打算有时间的时候在mailman或者自己的邮件列表系统中加以实现。不过在这之前要问问,各位看官有没有更好的方法?