前言
前一阵子360的Zhiniang Peng在Github上披露了先前发现的一种针对Shadowsocks大部分版本有效的攻击方式,不清楚与先前几次传闻的Shadowsocks不安全、被监控之类的新闻是否对应。在浏览完说明文件后,因为对密码学和网络协议不是很了解,导致在原文省略一些说明的情况下没有理解原理,后来通过另一篇博客的进一步的解释才终于初步了解了整个过程。由于原文缺乏了一些说明,而另一篇博客其实偏重于对复现的代码细节的讲解,故于本文记录自己阅读后对两篇文章重点的提炼,给类似我这样刚刚入门的人一定的参考。
Github原文:https://github.com/edwardz246…
参考的博客:https://www.leadroyal.cn/?p=1036
背景知识简述
Shadowsocks的工作流程
简单示意:client <—> ss-local <–[encrypted]–> ss-remote <—> target
这里的client便是浏览器、游戏客户端等涉及网络访问的程序,ss-local是运行于电脑本地的Shadowsocks服务,ss-remote是远程代理服务器,target则是client的通讯目标。对于client而言ss-local就像一个SOCK5服务器,client将数据传输给ss-local,ss-local加密后传输给ss-remote,ss-remote解密后再传输给真正的通信目标target。
流加密 (Stream Ciphers)
当时大部分Shadowsocks的版本使用的是非AEAD式的流加密,涉及多种算法及变种(原文以aes-256-cfb为例),这里仅对完全不了解的读者做一个简单描述,对具体细节感兴趣的可以去搜索或是查询相关书籍。
所谓流加密,即将原始数据按固定长度切片后,对每一个分片使用密钥进行加密操作,其中不少变种算法中对每一个分片的加密还需要使用到前一分片的(部分)密文。简单来说,其中是一个事先设定的随机值即所谓Input Vector (IV)。此类加密方法仅能提供数据的保密性,而不能提供完整性与真实性的保证。
Shadowsocks数据包结构
Request结构:[input vector][target address][payload]
Response结构:[input vector][payload]
target address结构:[1-byte type][variable-length host][2-byte port]
其中地址的type值0x01、0x03、0x04分别对应4-byte IPv4、domain name和16-byte IPv6三种类型,大部分情况中处理的都是IPv4类型的地址,这也是这种攻击主要针对的对象。
攻击方案
攻击假设
这里假设被攻击的电脑是不安全的,攻击者有办法获取ss-local与ss-remote之间通讯的所有数据包。当然通常情况下这些数据包已经经过了本地加密,虽然被攻击电脑不安全但是攻击者还是没有办法破解,只能看到大量“无意义“的乱码。
攻击思路
攻击者截获加密数据包后,试图篡改target address的值后再转发给原ss-remote,让ss-remote完成解密后将明文发送给攻击者控制的服务器。
攻击流程
攻击者已经获取了ss-local发送与ss-remote返回的数据包,接着要做的便是在不知道密钥的前提下替换掉target address。下面将以原文中的AES-256-CFB为例解释整个过程(原文附带的Github代码应该仅为思路参考,个人在比对分析后打算暂时采信参考博客中的说法)(CFB示意图来自https://www.cnblogs.com/yanzi…)。
攻击的核心依据便是http的response包大部分情况下是以”HTTP/1.”为开头(可以通过伪造的包尝试建立连接来验证),那么当攻击者知道这一分片的明文与密文后便可以推算出与这一分片进行异或运算的密钥,但无法进一步逆推得到原始加密用的key来解密数据包中所有的信息。注意到response包的前7位,假如看成request包则恰好对应IPv4类型的7-byte target address,故攻击者利用得到的切片密钥与预设的恶意服务器地址异或运算,塞入数据包并作为request发送给ss-remote,便可以在服务器收到解密后的原始response数据。
另外那篇参考博客中还提供了了面向指定域名的针对request攻击的思路,感兴趣的可以去看一下。
解决方案
原文中有提及,不要使用shadowsocks-py、shadowsocks-go、go-shadowsocks2以及shadowsocks-nodejs,使用shadowsocks-libev版本并仅使用AEAD的加密方式。AEAD方式中,C/S双方单独维护了一个对称密钥用于签名来保证数据的完整性防止篡改。
评论 在此处输入想要评论的文本。