通常来说,TCP握手就表示通讯双方互相验证了IP地址。事实却并非如此,TCP握手欺骗是一种新型的攻击方式。
假设A是客户端,正在连接B:
A: Hi B, I'm A, send number 5.
B: Hi A, I'm B, 5, send number 3.
A: Hi B, I'm A, 3, send number 6. I'd like example.net.
B: Hi A, I'm B, 6, send number 4. Here comes the data: ...
在这之后,A与B将会互发数据。同时为了保证所有数据都能被收到,即通信的可靠性,数字会不断增加。在1981年设计TCP协议时,安全性没有被优先考虑。ARPANET给出了一个列表,他们需要一个协议来发送数据,并且不用担心数据重传错误、校验数据完整性、保持数据包序列等等,TCP解决了这些问题。这些数字被称为序列号(Seq)和确认号(Ack),它们会引发两个问题:
我们来演示一下利用者两个缺陷进行攻击,A发送数据给B:
A: Hi B, I'm C, send number 5.
B: Hi C, I'm B, 5, send number 3.
A: Hi B, I'm C, 1, send number 6. I'd like example.net.
B: Hi C, I'm B, that's incorrect. Close the connection please.
A: Hi B, I'm C, 2, send number 6. I'd like example.net.
B: Hi C, I'm B, that's incorrect. Close the connection please.
A: Hi B, I'm C, 3, send number 6. I'd like example.net.
B: Hi C, I'm B, 6, send number 4. Here comes the data: ...
上面的情形中B根本无从知道自己在响应一个伪装的IP地址,真正的C也根本不知道发生了什么。平均需要花费120GB网络流量就能创建一个欺骗连接,这取决于你的运气,不好的话可能需要200GB,但运气好时只需要72GB。许多拥有1gbps带宽的VPS非常便宜,如果你充分利用它,每次攻击平均只要17分钟左右。通常如果你想要注入一个有效载荷,例如发送一个命令,它需要被放在现有数据后面,这会增加攻击所需的流量。例如发送“GET / HTTP/1.0/n/n”平均需要152GB或者20分钟,但这会使得你的连接在对方的access logs显示为一个正常的连接。
由于TCP协议自身的原因,这种攻击很难解决。虽然可以拒绝大量的不正确的Ack,并可以以此为理由关闭连接,即便如此,还是会留下巨大的利用空间。如果要互相认证对方,那就需要额外的安全条件,例如使用TSL。即使证书没有被认证过,由于客户端需要接收额外的数据,任何加密的TSL会话都会认证,这样欺骗就无法进行。总之,不要使用基于IP地址的认证,不要相信IP地址白名单,当你需要安全性的时候使用安全协议认证。
感谢魏星对本文的审校。
给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ,@丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入InfoQ读者交流群 (已满),InfoQ读者交流群(#2) )。