shadowsocks-org
shadowsocks-org copied to clipboard
利用防重放机制自动对 Shadowsocks、VMess 等未知流量代理进行“隐蔽式拒绝服务攻击”
由于 https://github.com/shadowsocks/shadowsocks-org/issues/183 ,我在研究“对服务端与客户端的逐字节重放”,并且取得了一些成果,此时又开了一下脑洞:
~~如果布隆过滤器被人恶意打满呢?不过可操作性不强,还有太多未知变量。~~
接着就想到了如题:众所周知,某中间人一直在对未知流量进行重放,导致现在大多数实现都有防重放机制。
而利用服务端的防重放,中间人不需要破坏连接,只需提前发送未知流量的前 32 个字节(或更多),即可使这些代理实质性失效。
不需要封锁任何 IP 或端口,精准阻断未知流量类代理。 某种程度上还是无解的,允许重放又会存在问题。
这个机制简单可行,好消息是,它尚未被部署,坏消息是,一旦部署会很棘手。
其实只会阻断这类协议:未知流量、0-RTT、有重放过滤器,~~听起来是不是很熟悉?而且并没有封你,是你自己封了自己。~~
——谁杀了我,而我又杀了谁?
——是我杀了我?
“因噎废食”式攻击
墙变身为延迟复读机,你发什么他就发什么,你向梯子服务器建立一个连接他也建立一个连接。不同的是,他抢在你发的内容发出去之前就把你发的内容发出去了,而这个延迟是加给你的。
那么,当一个 IV 通过了后续的 AEAD 解密有效性检验并被加入反重放过滤器中时,来自客户端的、到达较晚的 IV 反而会触发重放检测,让客户端的整个连接变成无限读,直接实质上瘫痪代理。
这个由 rprx 提出的攻击的原理非常简单,部署起来可以说技术难度很小,虽然会有很大概率误伤正常服务,但不排除有在极端时期被墙针对性利用的可能。
如果在有实质有效数据转发后再将相应数据放进反重放过滤器,能否缓解该问题?
如果在有实质有效数据转发后再将相应数据放进反重放过滤器,能否缓解该问题?
能用是能用了,但如果里面是个无状态的服务,就很可能给对面回了一份一模一样的包,就把自己给卖了……
确实棘手,,
@NutterChen @DuckSoft
正常的服务通常有握手鉴权机制,并且因此没有重放过滤器,即使某中间人无法识别给这么操作一波,基本上不会受影响。
而这些代理是不能有握手鉴权机制的,否则公开后会成为强特征。所以这是一个死局,还可以按比例干扰,非常恶心。
对了,防重放机制不一定都无限读,~~不然这也是强特征。~~
有意思,间歇性阻断就VANS了。 不过意义不大吧,直接换TLS或者WS又可以避免了。
能否把客户端本身的ip也加入协议中作为一个特征?如果只是简单的重放的话ip肯定会变动,校验失败的直接丢掉?
~~结论是不是tls真香~~
这确实是个很棘手的问题,可能需要移除过滤器并且重新设计协议才能彻底解决现在遇到的问题。
基本上我会赞成先移除过滤器,再考虑下一步协议要怎么改。 至少现在AEAD算法下第三方就算重放包也只能得到一个看不懂的回复(尽管可以通过包长来初步判断,但是毕竟那是不精确的)。
@deximy 能否把客户端本身的ip也加入协议中作为一个特征?如果只是简单的重放的话ip肯定会变动,校验失败的直接丢掉?
客户端本机是很大概率是没办法直接知道自身的外网IP的,所以做IP校验是不可行的。
@wevsty 客户端本机是很大概率是没办法直接知道自身的外网IP的,所以做IP校验是不可行的。
可以通过访问某个外网特定的获取IP地址的接口来实现?
@wevsty 客户端本机是很大概率是没办法直接知道自身的外网IP的,所以做IP校验是不可行的。
可以通过访问某个外网特定的获取IP地址的接口来实现?
这个是不现实的,外部接口如果设在国外GFW可以直接墙,设在国内可以直接找你麻烦。另外外部接口的做法无法应对多出口会变IP这种情况(比如某些运营商的透传或者小区黑宽带)。
@deximy 能否把客户端本身的ip也加入协议中作为一个特征?如果只是简单的重放的话ip肯定会变动,校验失败的直接丢掉?
没用,GFW可以合法地伪造来源IP。
事实上伪造来源IP从来都不是一件困难的事,你自己就可以轻松做到。 伪造来源IP,利现有UDP服务进行反射型DDoS攻击,也早就被大规模应用了。所以一些面向终端用户的ISP部署了BCP38、RPF. 之类的协议以过滤掉伪造来源IP的数据包。
但GFW自身就是核心路由节点,所以它可以合法地伪造所有经过该路由节点的来源IP。如果回程路由,也经过相同节点的话,GFW甚至可以使用该IP建立合法的TCP连接。
可以用 Xray-core 的 TPROXY + sniffing + Freedom 改改代码来模拟出这种攻击。
Hi rprx,
Great job discovering this attack!
Blow are the description of the adversary, the proof of concept and our comments on this attack.
Adversary
This attack requires an in-path adversary to:
- temporarily block the first packet sent by a legitimate client;
- establish a TCP connection with the suspected server;
- send a replay of the first 32 bytes or the complete payload;
- and then release the blocked legitimate packet.
The attack is clever because the blocking will be connection-based, which potentially causes less collateral damage comparing to port-based or IP-based blocking. It can thus be especially useful when the GFW cannot accurately determine whether the server is for circumvention or not.
Proof of concept
Let's get a traffic capture of the first packet sent from legitimate client to server. Note that it can be any Shadowsocks implementation and any encryption method.
ss-server -s 127.0.0.1 -p 8388 -m aes-256-gcm -k "mypassword"
ss-local -s 127.0.0.1 -p 8388 -m aes-256-gcm -k "mypassword" -l 1080
curl -x socks5h://127.0.0.1:1080 -v http://example.com
We then save the captured hex stream of the first legitimate packet to a file called payload:
echo "b0cee48154f678d86bb11ef35c4a069fedd6c7748ceca018702f104a6f52b22b9119ac97fb74c9de333a57fedcd71c604672e1a875f93ec46ae9fa1526459721638a7f3d042e96d34cab26ea4f61a9fe86b4efdc6b1f41edac458802b284bc339b7432f128256b3301b7e80460a2a0e5630b494cbd31a8532d8420c8e792be449f76100d862c2e60e12bc9d20fc706a6cc0bd522f785b6c3aadd1b5f24c2cf22b08cfeddc21918d28730ef800c48a6b2546d405562de1f11d74e5946e2a9" > payload
We prepare a salt file which contains only the salt of the captured payload. Note that 32-byte is the length of the corresponding salt construction.
head -c 64 payload > salt
Now, we start the server again using:
ss-server -s 0.0.0.0 -p 8388 -m aes-256-gcm -k "mypassword"
First we send the salt and close the connection:
xxd -r -p salt | nc -vn 127.0.0.1 8388
As expected, Shadowsocks-rust server will complain, but no worry, our salt has been remembered:
ERROR failed to decode Address, may be wrong method or key, from client 127.0.0.1:51930, error: timed out
Now, we simulate the delayed legitimated connection:
xxd -r -p payload | nc -vn 127.0.0.1 8388
The server will not respond to the delayed legitimate client because it detects repeated salt:
ERROR failed to decode Address, may be wrong method or key, from client 127.0.0.1:51932, error: detected repeated iv/salt
Affected Shadowsocks implementations
Using the method above, we tested Shadowsocks-rust v1.8.23 and Shadowsocks-libev v3.3.3 on February 1, 2021. While apparently all Shadowsocks implementations with nonce-based replay filter will suffer from the replay of a complete legitimate payload, exclusively sending the salt is sufficient to block Shadowsocks-rust v1.8.23 connections.
A simple salt replay will not block Shadowsocks-libev and Outline's connection because these two implementations will only remember the salts if the following length tag and payload tag are authenticated. Note that we did not test Outline ourselves, but we were told by Outline developer @fortuna that Outline server would authenticate before remembering the salt back to October 2020.
Comments
Below, we argue that additional effort is required for the GFW to deploy this seemingly easy attack. This is because this attack requires in-path capability, while evidence suggests that the GFW traffic analysis system has been designed to be on-path. We believe similar rationale applies to the other newly discovered vulnerability.
The difference between an in-path and on-path system is clearly introduced by Wang et al. in section 2.1:
An "on-path" censorship system wiretaps routers of the ISPs controlled by the censor, makes copies of the packets on the fly and performs analysis in parallel with ongoing traffic. In contrast, an "in-path" censorship system places devices as part of a route, analyzes the traffic and then passes the same to the next hop. The capabilities of an "on-path" system include reading packets and injecting new packets, while an "in-path" system can also discard and/or modify packets. For an "on-path" system, processing time is not critical and thus, it can do more sophisticated analysis; for an "in-path" system, it is critical not to perform heavy analysis that will introduce packet delays. Large-scale censorship systems like the GFW usually deploy the "on-path" design in order to ensure extremely high throughput.
In this proposed attack, the adversary has to buffer and delay the legitimate packet for at least a large amount of time: time to compute payload entropy + time to establish TCP connection with suspected server + time to send the legitimate payload. If the censor had implemented the Shadowsocks traffic analysis system exclusively in-path, even non-circumvention traffic would have suffered from significant delay. Different from a simply keyword matching (which takes little time and thus can be implemented in-path like what the GFW has been using for ESNI censorship), Figure 8 and Figure 9 by Alice et al. shows that the GFW needs to compute the payload length and entropy which takes much more time. In fact, potentially because the in-path implementation will cause significant delay, we have not yet observed the censor to take this approach in practice.
That being said, we conjecture that the censor would use a hybrid approach to implement such attacks. The censor may first conduct on-path traffic analysis, and then capture and buffer only a few legitimate connection using in-path devices based on IP-port pair.
In fact, if such a hybrid approach is implemented, the censor can identify Shadowsocks servers with many new attacks by blocking and/or modifying legitimate connections. For example, although we have not tested it against other protocol, it seems to be rare for a server that respond to a certain payload only for the first time, but not any other time.
Finally, we realized that Shadowsocks community are proposing a potential upgrade to the Shadowsocks protocol. We thus encourage Shadowsocks community to read this post by us. You may find it helpful because that post contains our thoughts on how to make a more probe-resistant circumvention service based on our findings of the GFW. For example, the attack above could be mitigated as suggested in the post:
Shadowsocks servers to remember the nonces of all authenticated connections forever, or until the master password is changed.
感谢 @gfw-report 进行详尽的测试,我的补充如下:
- 若主要针对现有的 Shadowsocks 协议,则 50 bytes 足以包含一个有效的 length 加密块,我推测这应该会影响 Outline server。
- 我认为攻击者无需给原连接增加显著的延迟,因为只需 快一步 即可,即攻击者的 IP Packet 始终具有更高的发送优先级。
- 这种方式对 VMess 等协议也是 通杀的,所以攻击者实施前仅需评估附带伤害,它应该是微不足道的,目前需要进一步验证。
- 若主要针对现有的 Shadowsocks 协议,则 50 bytes 足以包含一个有效的 length 加密块,我推测这应该会影响 Outline server。
It appears that, at least for Shadowsocks-libev v3.3.5, it requires both the length tag and the payload tag to be properly authenticated before the replay filter remembers a nonce. Thus a 50-byte truncation may not be sufficient.
We conduct the following test:
We prepare a salt_len_lentag.bin file which contains a 32-byte salt, a 2-byte length field and a 16-byte length tag.
xxd -r -p payload | head -c 50 > salt_len_lentag.bin
Now, we start the server again using:
ss-server -s 0.0.0.0 -p 8388 -m aes-256-gcm -k "mypassword"
We send the salt, length field and length tag; and then close the connection:
nc -vn 127.0.0.1 8388 < salt_len_lentag.bin
Now, we simulate the delayed legitimated connection:
xxd -r -p payload | nc -vn 127.0.0.1 8388
It turned out that the server would still respond to the delayed legitimate client.
- 我认为攻击者无需给原连接增加显著的延迟,因为只需 快一步 即可,即攻击者的 IP Packet 始终具有更高的发送优先级。
We agreed that the delay could possibly be short. As shown in Figure 7, the minimal observed delay of a replay was 0.28s. This means the censor just needs to hold the traffic for around 0.28 seconds in the best case.
- 这种方式对 VMess 等协议也是 通杀的,所以攻击者实施前仅需评估附带伤害,它应该是微不足道的,目前需要进一步验证。
We agreed that it requires a probing experiment to the real world network like what Frolov et al. did in Section 3.B.
@gfw-report
- 是的,此前我看过 ss-libev 的代码。所以我推测 50 bytes 时会受到影响的是 Outline server(因为它是单端口多用户)
- 不需要
0.28s,我的意思是两个连接应该是 并行的,而不是阻塞的,这样更具实用性
@fortuna I'm contacting you via Keybase
如果在有实质有效数据转发后再将相应数据放进反重放过滤器,能否缓解该问题?
能用是能用了,但如果里面是个无状态的服务,就很可能给对面回了一份一模一样的包,就把自己给卖了……
如果server對每個連接都也生成一個新的IV(可能的話再加以長度干擾參數),應該可以避免回包一模一樣吧?
@NutterChen @DuckSoft
正常的服务通常有握手鉴权机制,并且因此没有重放过滤器,即使某中间人无法识别给这么操作一波,基本上不会受影响。
而这些代理是不能有握手鉴权机制的,否则公开后会成为强特征。所以这是一个死局,还可以按比例干扰,非常恶心。
如果將握手鑑權與Payload結合呢?當然我一直覺得完整鑑權的意義不是很大。重放只對第一個包有效,server也很容易察覺重放,改變對重放的處理方案(不應該直接取消,應用程式server不應該收到兩次包)以及解決樓上的問題(或許ECC前向安全原理可以做到相關機制?)就能解決很大部分的問題。 相比之下,我有點在意重放攻擊與未重放攻擊下行為對比統計是否可以帶來特徵引發非常時期更暴力的封鎖,以及0-RTT的TLS1.3如果承載VMess,是否也可以使用類似的方案統計判定。
而利用服务端的防重放,中间人不需要破坏连接,只需提前发送未知流量的前 32 个字节(或更多),即可使这些代理实质性失效。
@rprx If GFW is bothered enough to launch such attack, why doesn't it just blacklist the server IP? What assumptions do you hold about GFW for this attack to be realistic?
而利用服务端的防重放,中间人不需要破坏连接,只需提前发送未知流量的前 32 个字节(或更多),即可使这些代理实质性失效。
@rprx If GFW is bothered enough to launch such attack, why doesn't it just blacklist the server IP? What assumptions do you hold about GFW for this attack to be realistic?
It is difficult for GFW to determine whether a weakly-characterized encrypted connection carries the Shadowsocks service. Of course, if GFW knows that a server provides Shadowsocks, it will block that server.
@QChWnd You're repeating me.
Let me rephrase it: in what scenario would GFW choose to launch this hypothetical attack instead of just simply banning the suspected server IP address or dropping uncategorized traffic altogether?
@QChWnd 如果server對每個連接都也生成一個新的IV(可能的話再加以長度干擾參數),應該可以避免回包一模一樣吧?
目前 Server 端回复已经是每个 Session 独立生成一个 IV (Salt) 的了(也就是Client和Server之间使用的收发IV是不一样的)。 我理解一模一样是指包的长度方面?
@riobard @rprx If GFW is bothered enough to launch such attack, why doesn't it just blacklist the server IP? What assumptions do you hold about GFW for this attack to be realistic?
I'm not sure if GFW can establish TCP connections by spoofing the IPs of other users in China. While some say this is possible, I have not seen any examples.
But if GFW can do this, then I'm afraid it will be difficult to block suspicious IPs. Because blocking such IPs will likely affect normal users.
@QChWnd You're repeating me.
Let me rephrase it: in what scenario would GFW choose to launch this hypothetical attack instead of just simply banning the suspected server IP address or dropping uncategorized traffic altogether?
The current misjudgment rate of GFW does not seem to be high, perhaps it does not want to bring misjudgments. For proxy servers like Shadowsocks, TLS is of course the most convenient solution.
I'm not sure if GFW can establish TCP connections by spoofing the IPs of other users in China. While some say this is possible, I have not seen any examples. But if GFW can do this, then I'm afraid it will be difficult to block suspicious IPs. Because blocking such IPs will likely affect normal users.
That's a completely different issue. See the quote above by @gfw-report about on-path vs in-path systems. For performance and reliability reasons it's relatively safe to assume GFW is on-path, so it has limited capabilities to establish TCP streams on behalf of real users.