dream的小站 Resource Source Research Search

【技术安全】邮件审查——SMTP协议TCP重置攻击

谈谈对于非http的邮件协议,GFW是如何阻断的

发现发件人在黑名单中,立即重置TCP链接

from scapy.all import *
send(IP(dst='1.2.3.4', ttl=9) / TCP(dport=25, flags='S', seq=0))
send(IP(dst='1.2.3.4', ttl=9) / TCP(dport=25, flags='A', seq=1))
send(IP(dst='1.2.3.4', ttl=9) / TCP(dport=25, flags='A', seq=1) / 'MAIL FROM: xiazai@upup.info\r\n')

看似普通的三个包其实暗藏玄机。首先,目标地址是1.2.3.4,这显然是我胡写的一个地址,而且ttl设置为9。所以这个包发出去就没有打算让最终的目标机器接到,而只是发给GFW看的。这个ttl值要大于你的机器到GFW的跳数,一般11是一个保险的值。

然后要触发GFW的响应,有以下几个缺一不可的条件

目标端口是25,我尝试了其他几个端口没有发现触发响应

第二个包虽然内容是空的,但是必须存在。而且必须是ACK。内容也可以不为空,GFW似乎不care内容是什么,只要有这个包就可以。

第三个包的seq必须为1,哪怕第二包有内容了,这个包的seq也必须为1。而且MAIL FROM: \r\n这个格式必须对,不能替换成FROM MAIL啥的。还有一个条件就是邮件地址必须上了黑名单。这里举的例子是一个翻墙软件的索取地址,所以上了黑名单。

观测到的响应是GFW发一个TCP RST包。而且每次都是一个,从来不多发。如果少了中间那个空的ACK,则是连做两次探测触发一个TCP RST。貌似GFW把两次探测认为是一个连接了。

发现收件人在黑名单中,立即重置TCP链接

from scapy.all import *
send(IP(dst='1.2.3.4', ttl=9) / TCP(dport=25, flags='S', seq=0))
send(IP(dst='1.2.3.4', ttl=9) / TCP(dport=25, flags='A', seq=1))
send(IP(dst='1.2.3.4', ttl=9) / TCP(dport=25, flags='A', seq=1) / 'RCPT TO: xiazai@upup.info\r\n')

这与上面的MAIL FROM的例子基本上是一样的。不同之处只有一点就是有的时候可以看到两个TCP RST的回包。

发现收件人在黑名单中,发回用户不存在的错误消息

from scapy.all import *
send(IP(dst='1.2.3.4', ttl=9) / TCP(dport=25, flags='S', seq=0))
send(IP(dst='1.2.3.4', ttl=9) / TCP(dport=25, flags='A', seq=1) / 'EHLO anything-here\nRCPT TO: xiazai@upup.info\n')

得到的错误消息是 “551 User not local; please try \r\n”。有的时候还会伴随有数个连续的TCP RST。同样因为包根本没有到对方的服务器,而且这个服务器压根就不存在,所以这个用户不存在的错误消息只能是GFW做出的响应。

触发的条件是

  1. 目标端口必须是25
  2. 第二个包的第一个命令必须是EHLO或者HELO,内容没有关系
  3. 第二个包的第二个命令必须是RCPT TO,而且邮件地址要在黑名单中。
  4. \r\n没有关系,\n也是可以触发的

这次触发的条件是一个合法的SMTP请求过程。而之前的触发过程根本就不是合法的SMTP请求。

而且另外一个特征是这样触发的TCP RST,会有三个重叠,ack递加的现象,与HTTP全文关键字的响应非常类似。我推测,两型的响应是两个不同的模块。单独对MAIL FROM和RCPT TO的封锁,与对HTTP关键字的封锁类似,属于看到就封型。

而后一种更智能的,还会回答错误消息的是能够真正理解SMTP协议的模块,可能还用于做邮件全文内容的关键字检测。属于深包中的深包检测了

添加新评论