Shadowsock重定向攻击学习与复现
Shadowsock重定向攻击学习与复现
前言
什么是Shadowsocks
也称小飞机,shadowsocks和shadowsocksR是两款软件,shadowsocksR是基于早期的shadowsocks开发的
Shadowsocks(简称SS)是一种基于Socks5代理方式的加密传输协议,也可以指实现这个协议的各种开发包。目前包使用Python、C、C++、C#、Go语言、Rust等编程语言开发,大部分主要实现(iOS平台的除外)采用Apache许可证、GPL、MIT许可证等多种自由软件许可协议开放源代码。Shadowsocks分为服务器端和客户端,在使用之前,需要先将服务器端程序部署到服务器上面,然后通过客户端连接并创建本地代理。
在中国大陆,本工具广泛用于突破防火长城(GFW),以浏览被封锁、遮蔽或干扰的内容。2015年8月22日,Shadowsocks原作者Clowwindy称受到了中国警方的压力,宣布停止维护此计划(项目)并移除其个人页面所存储的源代码[8][9]。
为了避免关键词过滤,网民会根据谐音将ShadowsocksR称为“酸酸乳”[注 1](SSR),将Shadowsocks称为“酸酸”(SS)。另外,因为Shadowsocks(R)的图标均为纸飞机,所以专门提供Shadowsocks(R)或类似服务(如V2Ray和TROJAN)的网站则就被称为了“机场”。
From wikipedia.org,Shadowsocks
Shadowsocks
ShadowsocksR
Clash中也支持Shadowsocks
Shadowsock重定向攻击利用条件
能抓取到shadowsocks使用者的报文(此条件较易达到,例如在交换机上使用端口克隆;在路由器上对接口抓包,利用tcpdump)
1
2
3#openwrt安装tcpdump
opkg install libpcap
opkg install tcpdumpshadowsocks使用者使用了shadowsocks-py, shadowsocoks-go, shadowsocoks-nodejs,并且加密方式为 stream 加密(aes-128-cfb、aes-256-cfb等)
攻击者需要知道加密方式
什么是Shadowsock重定向攻击
以下是个人理解,若发现有不正确之处欢迎提出,我将修正
概括
攻击者通过修改数据包中的接收者的地址,模拟正常用户发送数据后服务器将解密的数据发送到被修改的接收者的地址,
攻击者无需知晓ss服务器的密码
完整描述
攻击者首先抓取到了ss使用者的上网的数据报文,然后监听一个tcp地址和端口。
攻击者提取ss使用者的上网的数据报文其中的ss客户端接收的数据,
伪造修改数据中标识的发送者地址为攻击者监听的tcp地址和端口,将数据再次发送给ss服务器。
ss服务器会对这些数据进行解密,然后误以为攻击者监听的tcp地址和端口是实际用户的地址并解密之后发送过去,
攻击者在监听一个tcp socket中获取到了解密的数据,完成一次攻击。
正文
加密原理分析
AES CFB模式加密
以下是python3的加密程序
1 | import struct |
AES CFB模式解密
以下是python3的解密程序
1 | import struct |
加解密分析
基于以上的加解密流程,容易得知其中一个重点就是加解密过程中均存在XOR(异或)的过程,
并且解密密文的过程是以加密密文的形式再XOR得到明文,
加密过程XOR(密文分组1,AES(IV))得到密文1,XOR(明文分组2,AES(密文分组1))得到密文2……
解密过程XOR(IV,AES(密文分组1))得到明文1,XOR(密文分组1,AES(密文分组2))得到明文2……解密时要对下一组密文再进行一次加密。
1 | 1 xor 1=0 ... 0 xor0=0 ... 1 xor 0=1 ... 0 xor 1=1 |
以本文利用实验的AES-256-CFB 为例,首先这是一种流式加密,在加密时不会对密文进行上面流程中的分组,
而是不断使用 XOR(明文,AES(密文))来处理,也就是说:
1 | XOR_KEY = AES(IV) |
这意味着如果我们能知道部分密文和对应明文,可以伪造密文,关系如下
1 | XOR_KEY = 密文 XOR 明文 |
ss客户端接收的数据的结构
ss客户端接收从服务端返回的数据的结构如下:
header是0x01(1 byte) + IP(4 byte) + port(2 byte)
的形式
1 | iv(16 byte) | aes( header(7 byte) | data ) |
伪造的操作
知道上述知识,我们就可以开始修改向ss服务器发送的数据了。
可知进行http请求时,返回的结果可能有HTTP/1.1
,和抓取到的ss返回密文,就拿到了一对明文密文对,就可以算出XOR_KEY
我们可以替换抓取到的加密数据中的客户端地址为一个我们所伪造的地址,然后就可以在上面监听数据了,
ss解密数据后会将数据发往我们监听的地址
1 | #抓取的客户端接收数据,recv_iv是iv, recv_data是aes( header(7 byte) | data ) |
复现过程
抓取数据报文的工具
可以使用wireshark或tcpdump进行数据报文抓取
wireshark
tcpdump
安装tcpdump
1 | sudo apt install tcpdump |
从eth0接口抓取所有数据并保存为dump.pcap
1 | tcpdump -i eth0 -w dump.pcap |
抓取数据报文
启动shadowscks代理-服务端
(服务端最好在另外一台机器启动,为了不混淆后面的分析)
安装shadowsocks-python版
1 | pip install shadowsocks |
以下配置需设置为监听端口,加密模式和密码
1 | { |
启动shadowsocks-python服务端, 假设上述配置文件保存在/etc/ss/ssserver.config
1 | ssserver -c /etc/ss/ssserver.config |
启动shadowscks代理-客户端(命令行版)
安装shadowsocks-python版
1 | pip install shadowsocks |
shadowscks代理-客户端启动后会在本地起一个socks5服务器,
客户端使用浏览器进行上网、玩游戏等只需要通过这个本地的socks5服务器即可,
此时需要记住这个socks5服务器端口(local_port),配置文件如下
1 | { |
启动shadowsocks-python客户端, 假设上述配置文件保存在/etc/ss/ss.config
1 | sslocal -c /etc/ss/ss.config |
启动shadowscks代理-客户端(GUI版)
打开, 直接设置即可
设置完成后选中设置的代理服务器
代理模式设为全局
开始抓包
首先记得启动抓包软件的监听
模拟访问(使用curl)
使用curl发送数据(走shadowscks代理)
1 | curl --socks5-hostname socks5服务器地址(一般为localhost):socks5服务器端口 http://aaa.lxscloud.top/test.html |
1 | curl --socks5-hostname localhost:1080 http://aaa.lxscloud.top/test.html |
模拟访问(使用浏览器)
访问一个http网站即可,例如
1 | http://aaa.lxscloud.top/test.html |
查看抓取的数据包
使用wireshark打开抓取的pcap文件
抓取到的加密数据的解析
起一个tcp监听以接收重定向的数据,这里端口设置为8081
1 | nc -lvp 8081 |
使用POC(Python3程序)对抓到的数据向ss服务端进行重放,需要scapy用于解析pcap
1 | pip3 install scapy |
修改目标主机以接收对ss服务器被重定向攻击后解析的数据
(POC程序修改自ss-redirect-vuln-exp,原程序在win10、python3.8、Scapy2.5.0跑不起来)
1 | from scapy.packet import Raw |
运行结果
攻击结果
在监听的8081端口收到消息
对比浏览器数据,可知95%数据都被拿到了
此时服务端存在报错,
经测试好像数据量太大服务端就不发送数据了
如何避免攻击
- 弃用shadowsocks,换v2ray或Trojan
- shadowsocks-py, shadowsocoks-go, shadowsocoks-nodejs存在漏洞,换用shadowsocks-libev, go-shadowsocks2 以及使用AEAD加密
End!
此种攻击方式似乎还能解密https,本文未进行尝试
本次实验参考自:
- https://github.com/edwardz246003/shadowsocks
- https://github.com/LeadroyaL/ss-redirect-vuln-exp
- https://www.leadroyal.cn/p/1036/
谢谢!
EOF