陳 曼,談 程,吉慶兵
(中國電子科技集團公司第三十研究所,四川 成都 610041)
Shadowsocks 和ShadowsocksR 常被用于突破防火墻長城(Great Firewall,GFW),以瀏覽被封鎖、遮蔽或干擾的內容[1]。
Shadowsocks(簡稱SS)是一種基于Socks5 代理方式的加密傳輸協議,也可以指實現這個協議的各種開發包。Shadowsocks 分為服務器端和客戶端,使用前需要先將服務器端程序部署到服務器上,然后通過客戶端連接并創建本地代理。ShadowsocksR(簡稱SSR)在Shadowsocks 的基礎上增加了一些數據混淆方式,修復了部分安全問題,并可以提高QoS 優先級。
與TLS 等協議不同,Shadowsocks 的最初設計的目的只是繞過GFW,而不是提供密碼學意義的安全,所以Shadowsocks 自行設計的加密協議對雙方的身份驗證僅限于預共享密鑰,無完全前向保密,也未曾有安全專家公開分析或評估協議及其實現。
本文分析Shadowsocks 和ShadowsocksR 產生的流量的報文格式和密碼算法,并探討用戶數據在兩種代理軟件保護下的機密性問題。
Shadowsocks(R)服務組件包括運行在本地電腦上的SS 客戶端和運行在遠端服務器上的SS 服務端。攻擊者能夠獲得的流量通常是從SS 客戶端發送至SS 服務器端的加密流量,而非本地電腦的Socks5 代理發送至SS 客戶端的流量。因此,這里分析從SS 客戶端發送至SS 服務器端的加密流量的報文格式。
圖1 是Shadowsocks 客戶端配置界面。從該界面可以看出,Shadowsocks 使用時需要用戶配置的部分包括服務器IP、服務器端口、密碼以及加密等部分。配置完成后,本機SS 客戶端與服務器IP 上的服務器端口建立連接,傳送通過密碼和加密處理過的應用數據。

圖1 SS 客戶端配置界面
SS 客戶端與服務器端之間傳送TCP 流或UDP報文。本文重點關注TCP 流,對UDP 報文格式不作介紹。TCP 流的最前面是隨機數,后續字節是密文。隨機數的長度與使用的加密算法有關,用作不同模式下密碼算法的初始向量或其他密碼參數。密文是用戶數據經過加密得到的。SS 客戶端轉發用戶數據至SS 服務器前,會在用戶數據前加入用戶訪問的地址,地址也是加密傳輸的。SS 客戶端發往服務器端的TCP 流和反向TCP 流格式分別如圖2 和圖3 所示。

圖2 SS 客戶端發往服務器端的TCP 流

圖3 SS 服務器端發往客戶端的TCP 流
TARGET ADDRESS 表示用戶要訪問的地址,使用Socks5 協議的地址表示方法,即TARGET ADDRESS 由類型、主機名和端口3 個字段標識。
Shadowsocks 加密選項的選取不同,用戶數據加密后的格式也不相同。當前,Shadowsocks 支持aes-128-ctr、chacha20-ietf 等流密碼算法和aes-192-gcm、chacha20-ietf-poly1305 等AEAD 密碼算法。對于流密碼算法,加密前后數據長度相同;對于AEAD 密碼算法,明文會變成如圖4 所示的密文。

圖4 AEAD 加密算法的密文格式
Shadowsocks 選用的加密算法不同,隨機數的長度也不相同。aes-128-ctr 等ctr 結尾的流密碼對應的隨機數長度為16 Byte;除bf-cfb 為8 Byte 外,其他cfb 結尾的流密碼如aes-128-cfb、camellia-256-cfb 等,隨機數長度為16 Byte;chacha20-ietf隨機數長度為16 Byte;AEAD 密碼算法包括chacha 20-ietf-ploy1305、aes-128-gcm、aes-192-gcm 和aes-256-gcm,其隨機數長度與密鑰長度相等。
圖5 是ShadowsocksR 客戶端配置界面。相比于Shadowsocks 客戶端配置界面,這里多出了協議、協議參數、混淆和混淆參數4 個配置項。通過源代碼分析可知,加密、協議和混淆是3個相對獨立的過程。首先,ShadowsocksR 先使用協議和協議參數對用戶數據進行封裝(部分協議會對用戶數據進行加密),使用戶數據滿足協議的格式;ShadowsocksR 對滿足協議格式的數據進行加密,加密方式與Shadowsocks的加密方式相同;ShadowsocksR 使用混淆和混淆參數對加密后的數據進行封裝,使加密后的數據滿足混淆的格式。

圖5 SSR 客戶端配置界面
對Shadowsocks 源碼分析可知,Shadowsocks 中使用的密碼算法包括兩類,分別是密鑰生成算法和不同加密選項使用的加(解)密算法。
Shadowsocks 配置加密選項時,實質上是同時選擇了基礎密碼算法和加密模式。加密選項基于TCP 流中的隨機數及密鑰生成算法產生的主密鑰來加密數據。不同加密選項使用隨機數和主密鑰的方式不同,本文僅以幾個加密選項為例說明。
Shadowsocks 密鑰生成算法基于預共享密鑰,即Shadowsocks 配置界面的密碼來生成主密鑰。加密選項確定的情況下,主密鑰的長度確定。當前Shadowsocks 支持的密鑰長度為16 Byte、24 Byte 和32 Byte。令pwd 表示預共享密鑰,master key 表示Shadowsocks 加密選項使用的主密鑰,輸入pwd、master key 長度,通過最多兩輪MD5 算法得到輸出master key。
CFB 模式的先決要素包括基礎密碼算法、密鑰、所支持的輸入/輸出長度以及所支持的標簽長度[2];輸入包括IV、明文和偏移參數s。Shadowsocks 使用aes-192-cfb 加密時,基礎密碼算法使用aes-192;密鑰長度24 Byte,取值為密鑰生成算法的輸出值master key;IV 長度為16 Byte,取值為TCP 流的16 Byte 隨機數rand;s 取值為128。
GCM模式的先決要素包括基礎密碼算法、密鑰、所支持的輸入/輸出長度以及所支持的標簽長度[3];輸入包括IV、明文和附加認證數據A。Shadowsocks使用aes-256-gcm 加密時,基礎密碼算法使用aes-256;IV 長 度 為12 Byte,取 值 為0;A 長 度 為0 Byte;密鑰K 長度為32 Byte,由密鑰生成算法的輸出值master key 以及TCP 流的32 Byte 隨機數rand,通過3 輪基于SHA-1 哈希函數的HMAC 算法產生。
Shadowsocks 使用過時的哈希函數生成主密鑰和會話密鑰,且主密鑰生成過程中未加入鹽值。通過口令猜測攻擊,攻擊者可以得到用戶配置,解密后獲取用戶數據。
Shadowsocks 使用過時的哈希函數用于密鑰生成。Shadowsocks 基于MD5 算法生成主密鑰,進一步使用MD5 算法、基于SHA-1 的HAMC 算法等從主密鑰導出會話密鑰。由于密碼學界對MD5 算法和SHA1 算法的一系列破解方法的提出[4-5],應用程序和密碼庫等已逐步取消對MD5 和SHA-1 算法的支持。中國和美國在2012 年分別制定哈希函數標準,稱為SM3 和SHA-3。
Shadowsocks 主密鑰生成僅與pwd 和master key長度有關。由于沒有加入鹽值,攻擊者可快速構建主密鑰庫,加快攻擊的速度。
密鑰生成算法輸入pwd、master key 長度得到輸出master key。猜測master key 和加密選項,任意攻擊者解密數據流得到用戶數據,通過驗證用戶數據是否滿足特定規則或AEAD 的標簽是否正確,攻擊者可以判定猜測的master key 和加密選項是否正確。獲取正確的master key 和加密選項后,攻擊者可解密用戶發送的任意流量,嚴重威脅用戶數據的機密性。
猜測得到正確參數的困難性即是猜測得到正確加密選項的困難性和猜測出用戶密碼的困難性。Shadowsocks 支持的加密選項個數是固定的,其隨機性較小,猜測得到正確加密選項的概率較大。而受易用性、可記憶的密碼數量等限制,用戶設置的Shadowsocks 密碼通常是非隨機的,這就允許通過口令猜測的方法驗證猜測正確性。對批量用戶進行攻擊時,攻擊者通過構建預共享密鑰庫的方式增加pwd 命中的概率,縮短算法運行時間。
密鑰生成算法的輸入僅包含pwd 和密鑰長度。Shadowsocks 支持的密鑰長度有16 Byte、24 Byte 和32 Byte。不同長度的密鑰是在上一長度密鑰上拼接,也就是說,從32 Byte 密鑰中可以直接讀取出同一pwd 生成的16 Byte 密鑰和24 Byte 密鑰。因此,攻擊者可能將存儲預共享密鑰庫轉化存儲32 Byte 密鑰庫,通過時空折中[6]實現參數獲取加速。
此外,對于流密碼算法,其他參數相同情況下,cfb 模式和ctr 模式解密得到的第一字節完全相同。遍歷加密enc 時,可將cfb 和ctr 看作同一種,減小遍歷次數實現參數獲取加速。
通過3.2 節,攻擊者得到了Shadowsocks 的全部配置信息,即得到四元組(服務器IP,服務器端口,密碼,加密)或四元組(服務器IP,服務器端口,密鑰,加密)。獲取這些參數后,可方便地進行流量解密。由于流密碼算法和AEAD 密碼算法的報文格式不同,流量解密流程也不相同。流密碼算法按照圖3 的方式從TCP 流中取密文進行解密。AEAD 密碼算法按照圖4的方式從TCP流中取密文進行解密。
ShadowsocksR 的參數獲取方法與Shadowsocks參數獲取方法類似。混淆和混淆參數不涉及加解密步驟,按照混淆的封裝格式直接解封裝即可剔除其影響。由于協議和協議參數的影響,TCP 流解密后的明文特征被隨機化,無法通過明文特征判定參數是否正確。然而,由于每種協議都用了特定的協議格式,可以通過驗證明文是否滿足協議格式的方法確定密碼、加密的參數正確性,同時確定協議的參數正確性。最后,根據協議類型和通過密碼、加密解密得到的明文,攻擊者可以進一步猜測并確定協議參數。
獲取所有參數后,通過讀取混淆和混淆參數去除混淆封裝、讀取密碼和加密得到明文、讀取協議和協議參數提取明文或進一步解密,攻擊者可實現SSR 流量的解密。
Shadowsocks 和ShadowsocksR 作為國內常用的網絡代理軟件,生成的流量的機密性僅依賴于配置界面的參數設置。攻擊者通過捕獲網絡流量和遍歷參數的方法可獲取用戶參數,一旦獲取用戶參數,攻擊者就可以監聽所有用戶數據,嚴重威脅數據機密性。由于攻擊者使用被動攻擊方法,用戶對于這種攻擊行為完全無感知。為保障用戶數據機密性,建議用戶增加Shadowsocks 和ShasowdocksR 配置參數的隨機性。Shadowsocks 和ShasowdocksR 配置中,加密、協議和混淆的參數個數固定,自由度較低,建議用戶增加密碼、協議參數的隨機性。此外,建議Shadowsocks 和ShadowsocksR 開發者使用SM3、SHA-3 替代現有的哈希算法,并且在主密鑰生成過程中加入鹽值。