Revision history and IPFS entry, back to latest
flyawaytheazure
IPFS What is this

Content Hash

用链式代理织成的绞索--利用RC4-MD5等流加密以及链式代理可瘫痪ss/r服务端

flyawaytheazure
·
·

一些背景(可能包括作者的私货)

  • 尽管开发者们一再告诫流加密,尤其是代理提供商(即机场)最喜欢使用的rc4-md5为代表的流加密存在的 严重 安全隐患,且并不如直觉“此类‘简单’的加密方法可以更节省资源提高速度“,在支持aes硬件加速的设备上,其表现并不如更安全更现代的aes-gcm系列加密方法,在不支持aes硬件加速的设备上也有chacha20-ietf-poly1305。敲响警钟也好,一遍一遍的耐心解释也好。计算机科学,数学,密码学的晓之以情动之以理也好,换来的似乎总是不理解,还有“自说自话自作主张”之类的评价。
  • 去年重定向攻击解密shadowsocks流密码的大新闻历历在目,却似乎只能证明大多数工具的使用者“集体记忆”远不如防火长城和站在它背后的技术团队,审查者日新月异而这边似乎有点情怀过头甚至“抱残守缺”。
  • 这次流加密的漏洞则起源于链式代理以及RC4加密本身的脆弱性。

实验

在实现攻击的源代码公开后,我与这个项目的开发者之一(也是Qv2ray的开发者之一)对代码进行了测试。

流程也并不复杂。

我一开始打算拉取源代码进行编译。

  • 拉取源代码(需要安装git)
git clone https://github.com/Qv2ray/rc4md5cry
  • 然后就是本地构建
  • 这里我发现很大一个坑,如果使用rustup提供的rust工具链,构建可以成功,但是构建出的二进制文件攻击并不能达到效果,我无论是在Debian9的vps上还是本地的macOS上都是如此。
  • 而使用pacman包管理器安装的rust工具链却可以(不知道brew安装的怎么样),尽管两者的rustc和cargo版本明明一样,真是搞不懂rust。
  • cd 到文件 rc4md5cry 下运行 cargo build命令就会在target下生成可执行文件。
  • 赋予执行权限,运行
./rc4md5cry --address shadowsocks服务端IP:服务端端口 
\ --password shadowsocks的密码 
\ --rounds 一个大于1024的整数值 
  • 总之最后因为我这里编译出的二进制文件出了状况,最后使用了GitHub actions编译的二进制文件,无论是mac端还是Linux端,攻击都能成功。
  • 攻击成功的表现
  • 服务端会输出 “ Too Many Open Files” ,然后是 “Connection timed out" 。此时不同于传统拒绝服务攻击,服务端cpu,内存,带宽等资源不一定被剧烈消耗,但ss/r服务会被瘫痪。
  • 效果很是震撼,百试百灵
  • 下面几张图是受到攻击的使用RC4-MD5加密方式的ss服务端日志
服务端崩溃


不涉及技术细节,具体实现,代码和理论的简要原理说明

由于作者非专业人士,以下原理基于自己的理解,可能有不准确甚至错误,欢迎指出和改正,同时感谢开发者对原理的耐心讲解。

  • 攻击的原理大概涉及:一个脆弱过时的流密码,一条代理链和代理链制造的一个回环。
  • 一个脆弱的流密码
  • 比如RC4-MD5,客户端和服务端会使用一个key进行通讯,而由于RC4的简单和脆弱,短时间内提前根据服务端客户端预先共享的shadowsocks的密码计算出未来通信使用的key会更加容易,这也是攻击的前提条件。
  • 其实并非仅限于RC4-MD5,理论上任何非协商算法(即key完全由客户端产生,服务端不介入密码产生)由于其本身的特点都具备被攻击的条件,只是预先算出之后通信使用的key消耗的时间,资源的问题而已。
  • 一条代理链,一个回环。
  • 这个思路大概最先起源于对不加密的网页代理( HTTP 代理)的研究正常的代理行为是客户端告知服务端(假设为 A )查询目标网站的数据,则数据流向为
我(客户端)-> 服务端(A) ->目标网站
  • 而正常的链式代理则使用两个或更多的代理服务器(A,B,C等),数据流向为
我(客户端)-> 服务端(A) -> 服务端(B) ->目标网站
  • 那如果利(滥)用(用)这个特性,可以做什么呢?
  • 以极低的成本,在不耗尽服务端cpu,内存或带宽资源的情况下,瘫痪shadowsocks/r服务
  • 要做的仅仅是让这条代理链变成一个环就好。即
我(客户端)-> 服务端(A) -> 服务端(A) -> 服务端端(A) -> 服务端(A) ->...—>服务端瘫痪
  • 而A 向外的每一个连接对应一个 fd (即文件描述符),而这个fd是有限的,可以通过 ulimit -n 获得,只要rounds后整数超过该上限,代理服务就会瘫痪。而因为攻击的rounds可以无限提高,因此调高上限不能解决问题。
  • 那如果禁止本地向本地回环发送数据呢?
  • 实际上这个解决方式并不能解决实际问题,只需在代理链上增加另一个服务端
我(客户端)-> 服务端(A) -> 服务端(B) -> 服务端(A) -> 服务端端(B) ->...—>服务端双双瘫痪
  • 一片雪花就这样沿着周而复始的代理链制造了雪崩。

这会有什么影响呢?

  • 对于个人用户而言,我想大多数人没有使用 RC4-MD5 裸奔的余裕吧。
  • 然而机场不知道是不是因为“RC4-Md5 作为弱加密更节省资源”之类的非科学的错觉,尽管开发者一再澄清事实(如上文),普遍使用且坚持使用该类加密。
  • 到了开发者们一致决定在软件包中移除流加密后,不理解更是上升到了攻击,尽管我真的不明白,为何要对付出时间精力智力劳动而不取分文的开发者这样高高在上。
  • 就算机场有对防火长城视若等闲的余裕,友商的网络攻击大概不能不理会吧,而由于这个工具的出现,以极低的成本瘫痪服务端从未如此简单,且目前没有缓解方案,一定要说的话,那就是拥抱AEAD加密,拥抱SSL/TLS

缓解方法(一己之见,自然含有大量私货)

  • 尽量使用更加先进的以SSL/TLS来进行伪装和确保传输安全的代理协议,ss/r确实堪称很多翻墙爱好者的情怀所在,然而终归时代在变化,高墙在成长,终究只有日新月异才能把握自由的分量。
时代变了


  • 很多人钟情于 shadowsocks/R 也是因为其简单轻量化的部署,比起需要搭建伪装站点,申请证书和修改相对复杂的配置文件的v2ray,trojan等,确实简单易行的多。如此便不难理解了。
  • 尽量使用自建代理,不过这就提出了更高的要求:“Linux、基础网络知识及 NGINX TLS 配置经验”等等。

再来一点碎碎念!

  • 因为构建问题昨天折腾了相当久,推荐直接使用GitHub Actions 提供的二进制文件。(需要登录GitHub账号)


二进制文件在这里


  • 能想出来这些攻击方式,确实相当佩服开发者们的创造力,将其实现,又需要行动力和代码水平,仰慕。(我啥时候才能到这种水平啊)
  • 也很高兴和感谢他们对我有过很多帮助和指导,他们也更是我自我进步自我改变的信标和鼓舞。
  • 也许以后会写搭建加密代理的教程。


CC BY-NC-ND 2.0