ShadowSocks协议的弱点分析和改进 #38

Closed
breakwa11 opened this Issue Aug 28, 2015 · 327 comments

Projects

None yet
@breakwa11
Owner

本文内容比较偏向于技术,可能有点难看懂 :(

原ShadowSocks协议的TCP连接部分,使用非常简单的协议,加密前是这样子的:
地址类型(1byte)|地址(不定长)|端口(2byte)
其中,地址类型有三个可能取值:1,3,4,分别对应IPv4,Remote DNS,IPv6
地址的长度就按这个地址类型取值来决定,后面这些不详细介绍了,不是关键的东西。

而加密的时候,会根据不同的加密算法,在前面添加一些随机字节,再进行加密,以使得即使发送相同的数据,加密的结果也不会相同。但是,同一个加密算法下,前面添加的随机字节的长度是固定的,而最常用的加密算法只有rc4-md5和aes系列(aes-128-cf8和aes-256-cfb等等),而非常的不巧,这些加密算法在使用的时候前面均添加16字节,于是前文所说的表示地址类型的那个字节的位置是完全固定的(在第17字节上)。

服务端为了判断数据是否有效,判断的依据就是表示地址类型的那个字节,看它是不是在那三个可能取值,如果不是,立即断开连接,如果是,就尝试解析后面的地址和端口进行连接。

基本的原理介绍完了,以下介绍如何进行主动探测。
因为SS判断数据的合法性,仅仅依据表示地址类型的那个字节,与此同时,根据信息论,对加密后的数据解密的时候,同一个位置上的数据如果穷举全部256个编码,那么能正好一一对应解密后的全部256个原码,这与密码长度还是用什么加密算法完全无关。那么,可以通过暴力尝试全部256种可能,找出服务器是否有三种情况下没有立即关闭连接,从而成功判断出这个端口开放的是SS服务。成功判断出这是SS服务器为了什么呢?聪明的你应该明白,在这之后你的IP或者你的服务器IP其中一方会落入黑名单。
PS.因为chacha20填充的长度是8字节,和其它加密用的长度并不一样,于是你会发现用chacha20的往往比其它加密算法稳定,只是因为这个长度较少被用于探测。

关键的问题就是,只需要穷举256种可能,成本太低了,太不安全了。也许clowwindy也意识到这个问题,他在issue中提出到考虑让服务端发现连接的数据不正确的时候,把数据重定向到一个正常的http网站,让其行为看起来比较一致从而不好分辨。但是这个修改还没有完成,为什么clowwindy会被请喝茶?因为如果不阻止,那么加入这个特性后会让ss封锁起来困难很多,所以请喝茶,阻止更新,然后才方便对其实施大规模封杀(毕竟按照新的特性重新写探测代码很麻烦不是)。在我知道clowwindy被请喝茶那天,我已经明白根本不是因为ss不好封杀,而是阻止更新然后去封杀,这个弱点已经被掌握并正在被运用,大规模封杀那天会到来得很快。

但是,那个改进依然不安全,还是只要穷举256种可能,看一看是不是有253种情况是http/https协议就行了,所以我没有考虑这么做(不过我想得还是粗糙,这点其实是猜的,有误请指出)。如果是多用户服务器,就更简单了,直接端口扫描,看看开放的接口是不是大部分都是http(甚至全都指向同一地方)就行了,总之这种做法特征明显。

我感觉上,这个如果不从协议上去解决,还是很难避免被封杀,于是在原来的SS协议头,添加了一个包装,在这里复制一下这个包装的结构说明:
标志版本号(1byte)|首包总长度(2byte)|随机填充长度(1byte)|随机填充数据|原ss首数据包|CRC32(4byte)
起关键作用的,就是末尾的CRC32,前面的数据包不管你如何去猜测,有了CRC32作为整个数据包的校验,穷举成本提升到至少256的5次方,即需要尝试10^12次,或1T次,产生的数据量将达到几十T,这样子去暴力破解还不如直接DDOS的成本低。另外,为啥CRC32放最末尾?一是为了方便校验,二是根据加密的特性,前面的数据只要改了一个,就会导致后面的数据完全不一样,这样只要前面的数据一动,后面所有的值就都错了,让CRC32校验充分发挥作用。
另外还有一个关键的地方就是随机填充不定长度的数据。现在其实除了新的Windows C#版客户端,其它平台基本没有把握手包和第一个数据包连起来发送,这样会导致SS客户端发送的第一个数据包的长度,在很多情况下是固定的,从而成为被检测的依据。就算实现了连同第一个数据包一起发送,但某些协议的连接并不会立即产生第一个数据包,而是先等待服务端的回应(比如 SSH),于是依然存在定长的问题(会精确等于16+1+4+2=23字节,只要统计发现你的IP经常产生23字节的TCP首包便可封杀)。为方便其它平台以最少的代码实现,直接在协议头部加入这个随机填充长度,以弥补ss在加密时总是产生定长数据包的问题。

这个解决方案能极大增加主动探测的难度以及首包长度检测的难度(非首包长度目前没有混淆,尽管还是可以通过非首包长度进行猜测,但毕竟需要的计算资源较大,这样调整后的SS还是能存活较长的时间的),但不想对SS协议做太大的改动从而造成各平台实现的修改困难(在Python或C#上增加支持这个协议才10行代码不到),SS之所以能实现如此多的平台,正是因为其协议简单,容易实现,所以我决定使用比较简单的协议来解决以上问题。

如果以上协议你还发现存在弱点,请留言告诉我,大家一起讨论——by Breakwa11

@Xuchenhao

然而你的加密写的极差无比,人品也是

@BroncoTc

@Xuchenhao 不要人身攻击!!

@shuangzhijinghua

只要打出那样一句话就已经暴露自己了
不用过多辩解,无需去讨好每个人,总会有人对你不满意,不爽的block即可。大不了发abuse如果你觉得值的话。

直接回复邮件看来不是一个好习惯,还是上来改了。

@XhstormR

@Xuchenhao 然而你看也看不懂,写也不会写,小朋友。

@zhenyihan

不会写的小朋友,喝喝茶

@xxnet
xxnet commented Aug 29, 2015

非常不错的分析和策略选择。

协议没有发现问题,补充一点想法:
第一,服务端不要去兼容老的协议,兼容了就失去其保护作用了。
只能采用另外分支或者在配置中设置开关。
为了方便维护,设置开关也许是不错的选择。

第二,在发现异常连接时,记录发起方的ip,最好能够记录到日志文件中,后续可以分析。

另外,请不要人身攻击。

2015-08-29 7:28 GMT+08:00 PowerOlive notifications@github.com:

不会写的小朋友,喝喝茶


Reply to this email directly or view it on GitHub
#38 (comment)
.

@polong
polong commented Aug 29, 2015

果然触碰到一些人的利益了。

@aOJzQT
aOJzQT commented Aug 29, 2015

在敏感时期连一个有技术的妹子都敢于挑大梁,勇气何等珍贵!那些海量的共匪狗,五毛狗利益被威胁,所以跳出来乱咬,滚去给你刁包主子跪舔吧

@renyidong

为什么你不能先Google一下ecb和cbc呢?
https://en.m.wikipedia.org/wiki/Block_cipher_mode_of_operation

@breakwa11
Owner

@renyidong 因为我不知道,现在粗略看了一下,就是描述对数据流的加密所使用的加密方式,不知道是否是我原文哪里说错了?请指教

@renyidong

@breakwa11 虽然我觉得对一个合格的程序员来说,这点英文水平至少应该有,可再怎么说你也可以点一下左侧的中文。
https://zh.m.wikipedia.org/wiki/块密码的工作模式
中文wiki虽然内容比英文少很多,不过也很足够说明问题了。

感谢你(再)发明了轮子,成功的解决了一个不存在的漏洞。
既然你要接手这个项目,为什么你连ae256-cfb中的cfb是什么意思都懒得Google一下?

@breakwa11
Owner

@renyidong 这个问题其实对于流加密来说(不管你如何处理)均有此问题,和cfb还是ofb无关,具体是实现上的问题

@flowfire

检测到这种协议就直接丢包。。。。是一个可行的方案

@xxnet
xxnet commented Aug 29, 2015

@breakwa11
前面提到的这种探测,能不能自己重现?有没有做过实验验证?
加密数据在解密时,会不会有自校验?

我也没有深入研究加密算法的实现,但大家是热心付出,很多时候时候都是在学习,希望能够在互相尊重的基础上探讨。
yidong 是做过加密相关算法的,能否解释清楚?

在 2015年8月29日 下午12:15,breakwa11 notifications@github.com写道:

@renyidong https://github.com/renyidong
这个问题其实对于流加密来说(不管你如何处理)均有此问题,和cfb还是ofb无关,具体是实现上的问题


Reply to this email directly or view it on GitHub
#38 (comment)
.

@breakwa11
Owner

我还没有严格验证过,昨天写得很匆忙,今晚验证一下

@renyidong

@breakwa11 哎呦,脸打的这么响,都肿了,还不承认啊。我就问了,你这样歧视古今中外的密码学家的智商,也不怕折寿?

1976年,IBM发明了密码分组链接(CBC,Cipher-block chaining)模式。在CBC模式中,每个平文块先与前一个密文块进行异或后,再进行加密。在这种方法中,每个密文块都依赖于它前面的所有平文块。同时,为了保证每条消息的唯一性,在第一个块中需要使用初始化向量。

就这一段,cbc是为了解决什么问题,初始向量什么作用,说的清清楚楚。流式加密只有ecb才有这个问题。因为ecb块与块之间独立加密。

而非常的不巧,这些加密算法在使用的时候前面均添加16字节

呵呵,这不是不巧,而是完全正确的用法。16byte=256bit,就是一个块长度的初始向量。

我看此issue极其宝贵,可使广大程序员免受拔牙之苦。

如果你还要接着嘴硬:talk is cheap,show me the code。Wireshark抓包记录秀出来。

@xiao201261

以ctrl+s

@breakwa11
Owner

cbc根本没有解决我在文章中所说的问题,文章中本来就考虑到了。所以其实我还是不知道你想说啥,能再说清楚一些么

@renyidong

@breakwa11 你就接着满地打滚装傻好了。有高中水平的数学,认真看完以上内容,早就懂怎么回事了。该说的都说了。再往下,纯粹就是智力测验了。

@breaking-gfw

@renyidong
剛剛看了一下https://en.m.wikipedia.org/wiki/Initialization_vector
我對密碼學並不了解。要看一看了

@breaking-gfw

@renyidong
理論上拔牙之苦我以前也有經歷過,哈哈,真是慘痛的教訓,只怪以前無知

@breakwa11
Owner

目前并没有发现你的说明与本文有些什么关系,文中本来就考虑到后面加密数据依赖上文的情况,但对于此攻击没有任何防御能力,如果没有有力的说明,那么我会完全无视你说的内容。至于说到严格证明,文章由于写得匆忙,还没有加上具体的加解密和攻击示例,会在晚上慢慢补上

@breaking-gfw

@breakwa11
shadowsocks源碼我沒有具體看過,要去扒一下才能驗證了.

@renyidong

说了吧,从这往下都是智力测验的内容。不是我当别人弱智。只要智商正常的人,看完中文维基多少该懂。反之,modus tollens。
不懂没关系,可以学。人傻没关系,可以多努力。然而你叫不醒装睡的人。
@breakwa11 again, talk is cheap, show me the code. 我除了开头结尾各两句情绪化语言,中间全是干货。

不妨最后再给你个机会,我楼上所有发言,有个问题完全没提及,然而却能使你提出的攻击从理论上可行。
当然,即使你能指出来,也只能证明你认真读了维基,而且是在本issue开始之后。因为你先前提出的解决方法,是完全错误的。此外,即使该攻击理论上可行,实际上也是没有意义的。原因现在先保留。无论你是否能说对,我都会公布问题所在,以及解决办法,供真心想改进ss的人参考。

@aOJzQT
aOJzQT commented Aug 29, 2015

@renyidong 讨论问题就说问题,说什么打脸,打滚的有个卵用。别人一妹子程序媛也是边做变学习,懂得多的多指教,懂的少的虚心点。套用温影帝常掰的:知无不言,言无不尽。
再套个你的,talk is cheap, show us the code,你倒是写个参考实现出来阿,you can you up, no can no bb. github上牛人一抓一大堆,装啥聊斋,一天天的闹心

@breakwa11
Owner

我发现我每个帖子都有一个特别高姿态的人,还每次都不一样的id,为啥之前的人不跟过来呢,好奇怪

@xiao201261

围观撕逼

@TearDownGFW

@breakwa11 因为我们都知道您的水军很厉害,也明白了一个道理,永远不要试图叫醒装睡的人

ilc22xe5vcm7 kqjv 9iv4

@xiao201261

有一些头像都没有的

@renyidong

@aOJzQT 唉呦,水军来啦?
我说了,无论对错,我都会将我发现的问题和解决办法一并奉上。code当然有,但我也不想有人马后炮出来说:“其实早就知道了”云云。台面上摆明白,大家看清楚。

懂得少的是该虚心点,然而某人虚心了么?
懂得多的是该多指教,我先贴链接,又指出读哪一段,最后直接节选关键,这不叫指教什么叫指教?我耐不耐心,明眼人一看就懂,你搅什么浑水?

GitHub上牛人多,水军更多。

@breakwa11 什么时候正面回答了我的问题,再来叫我。除此之外,一律无视。

@Xuchenhao

I think I am not a communist.And I am the admin of long-live-shadowsocks.So donnot act like a snob.You are a dog but I am notPick up your 'friends'.
I just told a truth.Your code is fool! :D

@mokeyjay

前来膜拜SSR

@renyidong

@XhstormR no ad hominem. This would be violation of GitHub ToS. I know that she knows nothing about cryptography, and so does everyone who is conscious. But direct ad hominem is another story.

@aOJzQT
aOJzQT commented Aug 29, 2015

@renyidong 你既然想解决问题就别和大家打嘴仗,撕逼,一个男的跟女的撕什么,还是在github上,还来劲了。你管我水不水军,这是重点?关键是你的建议和code,你可是夸了口了,别到时候操到一半痿了。

就算 @breakwa11 技术欠缺,代码“烂”,起码别人在尝试,你几个大神倒是fork过去提pull request阿,要不干脆直接参与不就好了。可别来什么怕被查水表、我很忙,不肖云云的托词。

我本不想参与"撕逼",这里给所有人致歉,都是共匪沦陷区的墙友,何苦相互为难。

@polong
polong commented Aug 29, 2015

跟贱人瞎掰,你们没毛病吧

@breaking-gfw

@renyidong 这和性别无关把...

@breaking-gfw

@renyidong
抱歉刚刚at错了。刚刚扫了一下,你说的确实没有错。

@TearDownGFW

@polong 每天上班在那坐一天,多没意思,看这个 repo 放松心情啊

@breaking-gfw

@breakwa11
老实说作为一个严谨的程序员,你不能说这句“不过我想得还是粗糙,这点其实是猜的,有误请指出”,或者诸如“据可靠消息”之类的。望注意

@dianso
dianso commented Aug 29, 2015

骂人的小学生连高中都没上就辍学了,还是好好上学吧,连高中都读不上,骂人可是强项。

@XhstormR

@renyidong 也是醉了,你要真想SS,就贡献代码;而不是在这里玩嘴皮子,勾心斗角,或者装个只会talk的大神;我就纳闷了,到底是谁是talk is cheap, show me the code,难道不是你吗?要我说,你还是去当狗仔队记者比较好,不要在这里浪费大家时间。

你忘了开Github这个网站的目的了?就是为开源代码,集众人力量,改进代码,然后Push;而不是让你看到代码漏洞,就在那里嘚瑟;国外开源库都要有你这样的人,开源社区早见鬼了。

看到这些冷嘲热讽的人,真令人恶心。

@soaper
soaper commented Aug 29, 2015

笑看装x还不贡献代码,却满脸牛x样子的“文学家”。

@akw28888

話說那種新註冊然後自己的帳戶裡根本沒有項目或者只是fork了SS的項目的...簡直和在FB上面成天罵人的無臉帳號一個樣啊(

@falseen
falseen commented Aug 29, 2015

建议大家停止争吵,虽然争吵可以暴露出一些问题,但相比由此带来的种种不好的影响而言,此举仍然是得不偿失。虽然大家意见不合,但这并不是太大的问题。就像clowwindy说的那样:“The license problem is rather a small problem, compared to other problems we face now.”

相比我们现在所面临的问题,这些小问题算得了什么?我们安安静静的在这讨论技术不好吗?为什么非要扯那些有的没的?为什么非要针锋相对?就算是有人的言辞和态度让人感到不适,也没必要这样斤斤计较吧?冷静下来想一想,这样真的对吗?事实就是你认为的那样吗?
希望大家不要一开始就抱着鄙夷或怀疑的态度来对待每个人,这样很容易造成误解。

@TearDownGFW

@falseen 自己去 clowwindy 的 twitter 看看,到底说的是什么

为什么不能安安静静讨论技术?因为 repo 主根本没有技术,屡次空穴来风的故意说原版 SS 有缺陷,有 XX 漏洞,比如这个 issue 就是,然而他改写协议缺陷更多,漏洞更多,还不能说,一说他的话不对,一说他写的代码不好,里面就会有好几个,甚至几十个小号来骂你。这是不能讨论技术的最主要的原因,大家应该也看到了,某人小号回复的时候换错了号,然后又自己删了。

为什么要扯那些别的?因为 repo 主一直在不停地扯别的,他要写协议就写吧,还要来说 SS 原版的协议不安全,有问题,renyidong 过来指出了 repo 主文章中的说错的地方,然而 repo 主根本不懂是什么意思,假装看懂了一样的,回复了一堆牛马不相及的东西,最后发现有问题,明白了一点的时候,又开始故意装傻。

为什么要针锋相对?为什么要计较?上面两段已经说了,repo 主不懂装懂,写一些有问题的东西骗小白,这就算了,竟然还开小号或者叫水军来骂人,请问你是来写翻墙的还是来建立帝国的?

“事实就是你认为的那样吗?”你难道没有看到吗?

是我们真的不支持 SS 吗?我们难道真的会去跪舔土工吗?历史上跪舔土工的,最后哪个人不是死在了土工手里?

@YouRepelMe

非常同意 @TearDownGFW 的观点。
我们是想让不明“真相”的多数人看到:Repo主并没有成熟的技术、不懂装懂、装疯卖傻、用这种软件的意义来博取人们的同情,造成误解,导致出现这么多的撕逼。
@breakwa11 你开了马甲小号来给自己洗地,随后删除,你这样做是把我们当傻子看么?

我们的目的都一样,是为了更好的网络环境,希望大家意识到了这点后,冷静思考。

@YouRepelMe

@wszf5560
别喷了, http://we.poppur.com/thread-1446352-1-1.html 先给自己洗洗地吧

@shuangzhijinghua

咦 现在流行查家底了?

YouRepelMe notifications@github.com于2015年8月29日周六 下午6:15写道:

@wszf5560 https://github.com/wszf5560
别喷了, http://we.poppur.com/thread-1446352-1-1.html 先给自己洗洗地吧


Reply to this email directly or view it on GitHub
#38 (comment)
.

@XhstormR

@TearDownGFW
哪来这么多小号,你看我是小号吗?

到底是谁在扯些别的,不是你吗?工信部的朋友,还说是挂代理钓鱼,你真的没事干嘛吗?

你说repo主不懂装懂,那你倒是给个说法啊?就扯小号水军什么的,你以为这里是微博啊,哪来这么多小号,5毛你给?

你不待见这个repo或者repo主,就请你unwatch吧,别来浪费口舌贬低了。Github是来写代码的,其他的事跑GOOGLE Group去,真是污染眼球。

@YouRepelMe

@shuangzhijinghua 没有恶意,我只是随手百度了一下看到的。大家都要冷静一些嘛。

@XhstormR

@TearDownGFW @YouRepelMe 这是给你洗地的小号吗?

@shuangzhijinghua

@YouRepelMe
YouRepelMe
Joined on 29 Aug 2015

只是随手点进了你的个人资料而已。

@polong
polong commented Aug 29, 2015

这里奇葩人真多,包括那个许宸皓,就是本贴第一回复,http://tieba.baidu.com/p/3718260428
好笑死了,看戏都可乐。

@polong
polong commented Aug 29, 2015

@YouRepelMe 别人卖个东西出争执有什么好洗地的,倒是你,小鲜肉,今天刚注册的新货,穿太多马甲小心把憋着。

@falseen
falseen commented Aug 29, 2015

@wszf5560 @TearDownGFW
你们说的很有道理,问题确实是出在了“某些人”的身上。他们就像旧时的“红卫兵”,如果没有他们,争吵是很难发生的。但从另一个角度考虑,他们的行为也是可以理解的,只是走错了地方。
技术上的争吵是很正常的,没有争吵就没有进步。但上升到人身攻击,性质就变了。真希望那些不懂github是什么地方的人转移阵地,不要污染了这里的环境。

@falseen
falseen commented Aug 29, 2015

@wszf5560 这样说确实没错,这个时候不管是谁站出来都是值得鼓励的。如果站在这个角度来看TearDownGFW和其他几个人的观点的话,那他们的行为确实是值得批判一番的。我之前就是站在这个角度来看的,但通过TearDownGFW后面的回复我才发现事情没有我想的那么简单,总结起来就是:“冰冻三尺非一日之寒”。矛盾是逐渐累积的,想要化解自然也需要一段时日。

能像你这样理性的指出错误的人太少了,如果人人都像你这样那该多好。

另外我不站在任何一方,我只站在ss的一方。而且我也不认为breakwall的行为全是对的,但既然clowwindy都公开支持她了,我也就试着去接受她一下,看看情况如何。以上。

@Xuchenhao

少拿小号来洗地,拿真名上Github Fork Shadowsocks,我不是你们想惹就惹得起的。
作者你还真不要脸,当心精分啊。

@polong
polong commented Aug 29, 2015

@Xuchenhao 得了吧,你都敢拿真名去做缺德事了,还怕拿真名来这骂人嘛,你连脸都不要了你还有什么可怕的,你没听过一句话:人至贱则无敌。不是怕惹得起你的问题,而是惹有毛线用,你别太看得起自己。
另外,你难不成觉得我是作者的小号,如果不是,那还好,如果是,除了你的思想也是奇葩之外,你实在太看得起我了,我没作者的好技术,我更没作者的好脾气。此刻,我是多么希望我有作者的技术,我也能为这场斗争出点真正的力,而不是只是来这里费舌。

@falseen
falseen commented Aug 29, 2015

@Xuchenhao @polong @wszf5560
以上@到和没@到的各位,这样的争吵是没有任何意义的,因为大家所站的角度和所掌握的信息不一样,所以争来争去也争不出什么结果来。这就像古代打仗,利用的就是信息的不对称。虽然这里可能并没有谁利用谁,但矛盾确实是由信息的不对称而逐渐升级的。

如果各位一定要为了一个破事争个你死我活、争到天荒地老,那我希望你们能站在ss的角度去争吵,而不是站在某个人的角度。这样即便是争得面红耳赤、争到头破血流那也是有意义的!!

@breaking-gfw

因为早就从讨论degrade到人身攻击了

@aOJzQT
aOJzQT commented Aug 29, 2015

grassmudhorse

都散了吧,真撕个没完啦,来一发

@polong
polong commented Aug 29, 2015

@falseen 哎,本来我的想法和你一样,但是实在看不过去,作者曾经因为违反开源协议被骂也就罢了,这回都开源了,按正常是人的思维,你若有能耐,作者的思路有什么问题,大可认真指出,可是它们是不是真有能耐不知道,舌头跟舔过屎似的,把嘴弄臭倒挺有能耐。
我只是祝愿它们是五毛吧,至少五毛它们为主而活为主说话,至少它们嘴还臭得还有原因,如果它们不是五毛,它们才真正的可悲。
好了算了,我也不扯皮了。

@ARwMq9b6

小白悄悄路过,纯支持。感谢有你。

@xuefliang

测试了以下,FORCE_NEW_PROTOCOL=True 没有路由器和手机端 的支持?

@bigoktesk

没看懂上面 @renyidong 说的问题重点是在哪里, @breakwa11 说的是墙可以主动检测,使用的方法是利用服务器对于"地址类型"这个字节不同值的反应,你说的似乎不是在反驳 @breakwa11 的观点?

不过对于 @breakwa11 的说法我也有疑问,是不是把"看它是不是在那三个可能取值,如果不是,立即断开连接"改成不断开连接就行了?因为主动检测没办法知道密码,所以这时候即使发出请求,也是不会得到服务端的回应的,是不?

我这也是小号,有点疑问的是,在这里不用小号的应该都是对自己信心满满不怕土共的,是不?

@renyidong

@bigoktesk cbc、cfb前面的字节会影响后面的结果,所以她说的256->256的对应关系不成立。也就是说地址类型位明文确实只有256个取值,密文根本不是

@k112358
k112358 commented Aug 29, 2015

有话好好说

@renyidong

@bigoktesk 其实你说的办法是可选的一种解决办法。不reset而是先返回一些垃圾数据。

@aofall
aofall commented Aug 29, 2015

一句吐槽变成撕逼就算了
撕逼还能扯到政治 ,还能搞批斗,也是醉了。repo主急需提高粉丝的质量啊

@falseen
falseen commented Aug 29, 2015

@renyidong
bigoktesk说的方法正是clowwindy离开之前准备着手去做的,具体你翻下原项目的issue。而且breakwall也提到了这个事。

我觉得你的说法有一定的道理,至于她为什么不承认,我也有点想不通,且看她如何反驳吧。但不管她会作何反应,我都希望你能把你的想法说出来。毕竟这里并不止她一个人,至少我看了你发的东西之后是获益良多的。

@breaking-gfw

"于是前文所说的表示地址类型的那个字节的位置是完全固定的", 其实作者被@renyidong提醒的地方是在这里。

@breaking-gfw

具体的话,看完维基自行做个实验就明白了。(aes-256-cfb,然后尝试穷举某个byte,看看解密那边什么反应)

@Lyoko-Jeremie

嗯...其实就是说需要实践检验一下字节的位置是不是完全固定的......
如果不是就说明并不存在这个漏洞....

@phpbestlang

只说技术,如果有之前讨论到但眼花没看到的内容,请补充

@renyidong 在加密这一块上,的确是你的理解有问题,协议中的这个弱点是真实存在的
你提到了块密码的工作模式,那应该是对密码学有一定理解的,那你应该知道AES不管工作在什么模式下,密文和明文的位置都是一一对应的,修改某个位置的密文,即对应修改了某个位置的明文(根据加密模式的不同,可能影响到后面其他密文块的解密,也可能影响不到,但在这里这个性质并不重要),如果预先知道了明文的模式,虽然无法解密还原出内容,但可以修改密文中的特定字节,起到修改解密后的明文的效果。在这里解密后的明文是多少只有天知道,但一共只有一个字节,所以穷举一下就行了,一共256种可能,这就是 @breakwa11 的意思。

Talk is cheap, show me the code.

举个例子,现在有一个协议包,共7个字节

0x01, 0x08, 0x08, 0x08, 0x08, 0x00, 0x50

对照socks5协议,很明显这是一个IPv4包(第一个字节是0x01),目的地是8.8.8.880端口

被shadowsocks加密了以后(密码abc,加密方式aes-256-cfb),数据包就变成了这样

0xbb, 0x59, 0x1c, 0x4a, 0xb9, 0x0a, 0x91, 0xdc, 0x07, 0xef, 0x72, 0x05, 0x90, 0x42, 0xca, 0x0d, 0x4c, 0x3b, 0x87, 0x8e, 0xca, 0xab, 0x32

前16个字节,从0xbb0x0d,都是iv,根据issue中提到的弱点和之前的总结,只需要修改0x4c,即真正密文中的第一个字节,就可要起到修改明文中的第一个字节的效果。

那就把0x4c修改成0x4d吧,解密以后的结果是

0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x50

的确只有第一个字节被改掉了,根据breakwa11的理论,不难推出其他情况,其中合法的是

0x4e => 0x03 (Domain Name)
0x49 => 0x04 (IPv6)

其他的转换情况也一并附在这里,可以数一下,解密后的结果是不存在重复的,可以说是一一对应的

0x00 => 0x4d, 0x01 => 0x4c, 0x02 => 0x4f, 0x03 => 0x4e, 0x04 => 0x49, 0x05 => 0x48
0x06 => 0x4b, 0x07 => 0x4a, 0x08 => 0x45, 0x09 => 0x44, 0x0a => 0x47, 0x0b => 0x46
0x0c => 0x41, 0x0d => 0x40, 0x0e => 0x43, 0x0f => 0x42, 0x10 => 0x5d, 0x11 => 0x5c
0x12 => 0x5f, 0x13 => 0x5e, 0x14 => 0x59, 0x15 => 0x58, 0x16 => 0x5b, 0x17 => 0x5a
0x18 => 0x55, 0x19 => 0x54, 0x1a => 0x57, 0x1b => 0x56, 0x1c => 0x51, 0x1d => 0x50
0x1e => 0x53, 0x1f => 0x52, 0x20 => 0x6d, 0x21 => 0x6c, 0x22 => 0x6f, 0x23 => 0x6e
0x24 => 0x69, 0x25 => 0x68, 0x26 => 0x6b, 0x27 => 0x6a, 0x28 => 0x65, 0x29 => 0x64
0x2a => 0x67, 0x2b => 0x66, 0x2c => 0x61, 0x2d => 0x60, 0x2e => 0x63, 0x2f => 0x62
0x30 => 0x7d, 0x31 => 0x7c, 0x32 => 0x7f, 0x33 => 0x7e, 0x34 => 0x79, 0x35 => 0x78
0x36 => 0x7b, 0x37 => 0x7a, 0x38 => 0x75, 0x39 => 0x74, 0x3a => 0x77, 0x3b => 0x76
0x3c => 0x71, 0x3d => 0x70, 0x3e => 0x73, 0x3f => 0x72, 0x40 => 0x0d, 0x41 => 0x0c
0x42 => 0x0f, 0x43 => 0x0e, 0x44 => 0x09, 0x45 => 0x08, 0x46 => 0x0b, 0x47 => 0x0a
0x48 => 0x05, 0x4a => 0x07, 0x4b => 0x06, 0x4d => 0x00, 0x4f => 0x02, 0x50 => 0x1d
0x51 => 0x1c, 0x52 => 0x1f, 0x53 => 0x1e, 0x54 => 0x19, 0x55 => 0x18, 0x56 => 0x1b
0x57 => 0x1a, 0x58 => 0x15, 0x59 => 0x14, 0x5a => 0x17, 0x5b => 0x16, 0x5c => 0x11
0x5d => 0x10, 0x5e => 0x13, 0x5f => 0x12, 0x60 => 0x2d, 0x61 => 0x2c, 0x62 => 0x2f
0x63 => 0x2e, 0x64 => 0x29, 0x65 => 0x28, 0x66 => 0x2b, 0x67 => 0x2a, 0x68 => 0x25
0x69 => 0x24, 0x6a => 0x27, 0x6b => 0x26, 0x6c => 0x21, 0x6d => 0x20, 0x6e => 0x23
0x6f => 0x22, 0x70 => 0x3d, 0x71 => 0x3c, 0x72 => 0x3f, 0x73 => 0x3e, 0x74 => 0x39
0x75 => 0x38, 0x76 => 0x3b, 0x77 => 0x3a, 0x78 => 0x35, 0x79 => 0x34, 0x7a => 0x37
0x7b => 0x36, 0x7c => 0x31, 0x7d => 0x30, 0x7e => 0x33, 0x7f => 0x32, 0x80 => 0xcd
0x81 => 0xcc, 0x82 => 0xcf, 0x83 => 0xce, 0x84 => 0xc9, 0x85 => 0xc8, 0x86 => 0xcb
0x87 => 0xca, 0x88 => 0xc5, 0x89 => 0xc4, 0x8a => 0xc7, 0x8b => 0xc6, 0x8c => 0xc1
0x8d => 0xc0, 0x8e => 0xc3, 0x8f => 0xc2, 0x90 => 0xdd, 0x91 => 0xdc, 0x92 => 0xdf
0x93 => 0xde, 0x94 => 0xd9, 0x95 => 0xd8, 0x96 => 0xdb, 0x97 => 0xda, 0x98 => 0xd5
0x99 => 0xd4, 0x9a => 0xd7, 0x9b => 0xd6, 0x9c => 0xd1, 0x9d => 0xd0, 0x9e => 0xd3
0x9f => 0xd2, 0xa0 => 0xed, 0xa1 => 0xec, 0xa2 => 0xef, 0xa3 => 0xee, 0xa4 => 0xe9
0xa5 => 0xe8, 0xa6 => 0xeb, 0xa7 => 0xea, 0xa8 => 0xe5, 0xa9 => 0xe4, 0xaa => 0xe7
0xab => 0xe6, 0xac => 0xe1, 0xad => 0xe0, 0xae => 0xe3, 0xaf => 0xe2, 0xb0 => 0xfd
0xb1 => 0xfc, 0xb2 => 0xff, 0xb3 => 0xfe, 0xb4 => 0xf9, 0xb5 => 0xf8, 0xb6 => 0xfb
0xb7 => 0xfa, 0xb8 => 0xf5, 0xb9 => 0xf4, 0xba => 0xf7, 0xbb => 0xf6, 0xbc => 0xf1
0xbd => 0xf0, 0xbe => 0xf3, 0xbf => 0xf2, 0xc0 => 0x8d, 0xc1 => 0x8c, 0xc2 => 0x8f
0xc3 => 0x8e, 0xc4 => 0x89, 0xc5 => 0x88, 0xc6 => 0x8b, 0xc7 => 0x8a, 0xc8 => 0x85
0xc9 => 0x84, 0xca => 0x87, 0xcb => 0x86, 0xcc => 0x81, 0xcd => 0x80, 0xce => 0x83
0xcf => 0x82, 0xd0 => 0x9d, 0xd1 => 0x9c, 0xd2 => 0x9f, 0xd3 => 0x9e, 0xd4 => 0x99
0xd5 => 0x98, 0xd6 => 0x9b, 0xd7 => 0x9a, 0xd8 => 0x95, 0xd9 => 0x94, 0xda => 0x97
0xdb => 0x96, 0xdc => 0x91, 0xdd => 0x90, 0xde => 0x93, 0xdf => 0x92, 0xe0 => 0xad
0xe1 => 0xac, 0xe2 => 0xaf, 0xe3 => 0xae, 0xe4 => 0xa9, 0xe5 => 0xa8, 0xe6 => 0xab
0xe7 => 0xaa, 0xe8 => 0xa5, 0xe9 => 0xa4, 0xea => 0xa7, 0xeb => 0xa6, 0xec => 0xa1
0xed => 0xa0, 0xee => 0xa3, 0xef => 0xa2, 0xf0 => 0xbd, 0xf1 => 0xbc, 0xf2 => 0xbf
0xf3 => 0xbe, 0xf4 => 0xb9, 0xf5 => 0xb8, 0xf6 => 0xbb, 0xf7 => 0xba, 0xf8 => 0xb5
0xf9 => 0xb4, 0xfa => 0xb7, 0xfb => 0xb6, 0xfc => 0xb1, 0xfd => 0xb0, 0xfe => 0xb3
0xff => 0xb2
@renyidong

@phpbestlang 看来我对AES的工作方式理解确实不对。我之前的理解是AES加密是以块为单位,是块到块的映射关系。因为有ShiftRows和MixColumns两步,所以修改一个bit的明文就会导致超过一个bit的密文改变,反之亦然。我会再做验证。

不过其实这依然不属于协议的问题,而是实现中没有考虑恶意客户端重用IV导致的。所以除了验证失败时返回随机内容,还有两点可做:

  1. 对最近的IV进行统计,如果发现IV频繁重用,则说明该客户端是恶意的。
  2. 对验证失败的次数进行统计
    两者都可以用一个IP为key的dict实现,开销不会太大。我想到的只有这么多,欢迎交流。
@renyidong

@phpbestlang 我之前的想法是,要穷举明文的1个byte,需要穷举整个密文块,现在看来并不是这样。

@lwm529
lwm529 commented Aug 30, 2015

小白路过…围观撕逼…

@breaking-gfw

@phpbestlang 我发现我也是没有考虑到这点。

@sutun2008

博主加油啊,一定要隐藏好自己,千万别再被喝茶

@ruleroller

继续路过,建议楼主不理会那些人身攻击的、冷嘲热讽的帖子。时间很宝贵的,不要回复没有意义的人,那些人如果真的想帮助你,可以明确指出不足,甚至提供改进代码,当然,他们绝不可能那么做的,因为他们生活在阴暗里,你越理他们,他们越来劲的,而你的时间却被浪费掉了。

加油。

@bigoktesk

@falseen 原项目的issue都看不到了吧?

@TearDownGFW

@phpbestlang 我不懂算法,但是我刚刚跑了 SS 的代码测试了,不要嘴上说,一定要实践

我觉得你可能没有注意到的是,SS 在每条连接的加密和解密过程中都是使用的同一个 encryptor 或者 decryptor 实例,并不是每次都初始化新的。

我们循环 0,255 之间数的 binary,前 16 位是 iv ,所以替换第 31-32 位的 hex 数据进行解密

首先是每次都初始化不同的解密器

Starting test ...
METHOD:aes-256-cfb
Plan Data: 5468697320697320746573742064617461
Real 31-32 bytes: 01
Tesing: 00
4281ed35cde1bbee006a1f57edfb04d761
Tesing: 01
5468697320697320746573742064617461
Tesing: 02
70a5d23fd751871b72a9e50b4be274f961
.......
Tesing: fd
9441b08a9a8c950a4696a57be5abf47461
Tesing: fe
55d7d9375a1cb0b3c2f811055290811361

我们可以看到,除了没有修改过的 “01” 位,只要修改了整个加密包中的任何一个字节为任何数据,解密出来的东西全部都是乱码,与原文没有任何关系,所以你的问题不成立

我们再按照实际的 SS 代码试一下

Starting test ...
METHOD:aes-256-cfb
Plan Data: 5468697320697320746573742064617461
Real 31-32 bytes: 04
Tesing: 00
5d5bf38b32acae600cf488274fc2892961 // 第一次尝试,不是 04 ,解密失败
Tesing: 01
ERROR: Decrypt failed
Tesing: 02
ERROR: Decrypt failed 

实际的 SS 代码,如果实行你所说的 IV 重放攻击,会直接对后续的一切数据包解密失败,只要第一次不正确,就算真正的提交了正确的猜测,也会解密失败。

不要搞理论,实践出真知。

所有代码均来自被删前大概 10 天的 git 备份

如果哪里有问题,请指出

@pluto6496

所以说这个问题是存在还是不存在?😵

@TearDownGFW

@pluto6496 我相信你看了上面所有的讨论,以及 breakwa11 回复的话,应该会明白

这个 issue,算是智商测验吧。

@phpbestlang

@pluto6496
breakwa11之前固然有很多地方在吹牛,对,我指的就是多路TCP这种不靠谱的“黑科技”,但在这个问题上,我认为这个弱点是真实存在的

@TearDownGFW
我也是跑shadowsocks代码测试的,并且贴出了所有的参数和测试结果,都是可以复现的
你可以把那段加密后的数据以密码abc,加密方式aes-256-cfb做解密,看看是不是我给的明文
再换一下第17个字节,看看是不是就变动了一个字节

您给出的结果,呃,说实话我没看明白,这不是握手包,也没有其他信息,可以给出详细的测试代码吗

另外,根据你说的

我觉得你可能没有注意到的是,SS 在每条连接的加密和解密过程中都是使用的同一个 encryptor 或者 decryptor 实例,并不是每次都初始化新的。

这句话,我觉得你可能没能理解这个弱点是如何利用的

@Yifei0727

搬运过来一个关于CFB工作模式的说明参见http://www.cnblogs.com/happyhippy/archive/2006/12/23/601353.html
优点:
1.隐藏了明文模式;
2.分组密码转化为流模式;
3.可以及时加密传送小于分组的数据;
缺点:
1.不利于并行计算;
2.误差传送:一个明文单元损坏影响多个单元;
3.唯一的IV;
@breakwa11 AES本质是块加密的,没有错
我也用openssl做了下测试,openssl在输入密码后,会产生随机盐值,在加密后会将这个盐值写在密文消息的头部
密码也用 abc
d是明文消息 e是加密后的消息体
$openssl aes-256-cfb -p -in d -out e
enter aes-256-cfb encryption password:
Verifying - enter aes-256-cfb encryption password:
salt=C71FC8D631013D49
key=EE5BA56E4C74F4108320E558A8FEB1BA652334D37940AC028938A047A9B971CE
iv =96EAB019C7B859D9AFD7D7D46AD4BB19
加密后:
$ hexdump -C e
00000000 53 61 6c 74 65 64 5f 5f c7 1f c8 d6 31 01 3d 49 |Salted__....1.=I|
00000010 b7 21 d9 5a 21 a5 63 |.!.Z!.c|
00000017
修改第17字节为任意值:
$ hexdump -C e1
00000000 53 61 6c 74 65 64 5f 5f c7 1f c8 d6 31 01 3d 49 |Salted__....1.=I|
00000010 30 21 d9 5a 21 a5 63 |0!.Z!.c|
00000017
解密修改后的密文
$ openssl aes-256-cfb -d -p -in e1 -out d2
enter aes-256-cfb decryption password:
salt=C71FC8D631013D49
key=EE5BA56E4C74F4108320E558A8FEB1BA652334D37940AC028938A047A9B971CE
iv =96EAB019C7B859D9AFD7D7D46AD4BB19
查看解密后的结果
$ hexdump -C d2
00000000 86 08 08 08 08 00 50 |......P|
00000007
的确发现第一字节值改变了,而后续值仍对的。
但是如果将cfb 8bit模式更改为cfb 1bit模式,就会影响了。
$ openssl aes-256-cfb1 -p -in d -out f
enter aes-256-cfb1 encryption password:
Verifying - enter aes-256-cfb1 encryption password:
salt=66321315CAAE5D96
key=690B35D3A8FBD10BDDFC3F62E248194FDD11A83E0DFCA6BDA2CD89AE5B975BE4
iv =68FC77DD023AEEBAFF5E5A13E7404B22
$ hexdump -C f
00000000 53 61 6c 74 65 64 5f 5f 66 32 13 15 ca ae 5d 96 |Salted__f2....].|
00000010 c7 7d a7 f8 75 15 fc |.}..u..|
00000017

将密文f 修改
$ hexdump -C f1
00000000 53 61 6c 74 65 64 5f 5f 66 32 13 15 ca ae 5d 96 |Salted__f2....].|
00000010 30 7d a7 f8 75 15 fc |0}..u..|
00000017
解密
$ openssl aes-256-cfb1 -d -p -in f1 -out df
enter aes-256-cfb1 decryption password:
salt=66321315CAAE5D96
key=690B35D3A8FBD10BDDFC3F62E248194FDD11A83E0DFCA6BDA2CD89AE5B975BE4
iv =68FC77DD023AEEBAFF5E5A13E7404B22

结果:
$ hexdump -C df
00000000 c5 ba 45 07 7f 98 48 |..E...H|
00000007

至于说ss本身是怎么加密传输的,那你们接着争吵吧,我不关心,--我对客户端证书式认证传输感兴趣--。

@bigoktesk

我的搬瓦工上的ss的log:

2015-08-29 16:23:47 ERROR    can not parse header when handling connection from 198.35.46.6:34252
2015-08-29 16:23:47 WARNING  unsupported addrtype 222, maybe wrong password
2015-08-29 16:23:47 ERROR    can not parse header when handling connection from 198.35.46.6:34253
2015-08-29 17:23:47 WARNING  unsupported addrtype 44, maybe wrong password
2015-08-29 17:23:47 ERROR    can not parse header when handling connection from 198.35.46.6:55072
2015-08-29 17:23:47 WARNING  unsupported addrtype 222, maybe wrong password
2015-08-29 17:23:47 ERROR    can not parse header when handling connection from 198.35.46.6:55073
2015-08-29 18:23:48 WARNING  unsupported addrtype 44, maybe wrong password
2015-08-29 18:23:48 ERROR    can not parse header when handling connection from 198.35.46.6:46499
2015-08-29 18:23:48 WARNING  unsupported addrtype 222, maybe wrong password
2015-08-29 18:23:48 ERROR    can not parse header when handling connection from 198.35.46.6:46500
2015-08-29 19:23:49 WARNING  unsupported addrtype 44, maybe wrong password
2015-08-29 19:23:49 ERROR    can not parse header when handling connection from 198.35.46.6:43293
2015-08-29 19:23:49 WARNING  unsupported addrtype 222, maybe wrong password
2015-08-29 19:23:49 ERROR    can not parse header when handling connection from 198.35.46.6:43294
2015-08-29 20:23:48 WARNING  unsupported addrtype 44, maybe wrong password
2015-08-29 20:23:48 ERROR    can not parse header when handling connection from 198.35.46.6:59003
2015-08-29 20:23:48 WARNING  unsupported addrtype 222, maybe wrong password
2015-08-29 20:23:48 ERROR    can not parse header when handling connection from 198.35.46.6:59004
2015-08-29 21:23:48 WARNING  unsupported addrtype 44, maybe wrong password
2015-08-29 21:23:48 ERROR    can not parse header when handling connection from 198.35.46.6:57282
2015-08-29 21:23:48 WARNING  unsupported addrtype 222, maybe wrong password
2015-08-29 21:23:48 ERROR    can not parse header when handling connection from 198.35.46.6:57283
2015-08-29 22:23:49 WARNING  unsupported addrtype 44, maybe wrong password
2015-08-29 22:23:49 ERROR    can not parse header when handling connection from 198.35.46.6:32812
2015-08-29 22:23:49 WARNING  unsupported addrtype 222, maybe wrong password
2015-08-29 22:23:49 ERROR    can not parse header when handling connection from 198.35.46.6:32813
2015-08-29 23:23:49 WARNING  unsupported addrtype 44, maybe wrong password
2015-08-29 23:23:49 ERROR    can not parse header when handling connection from 198.35.46.6:47019
2015-08-29 23:23:49 WARNING  unsupported addrtype 222, maybe wrong password
2015-08-29 23:23:49 ERROR    can not parse header when handling connection from 198.35.46.6:47020
2015-08-30 00:23:50 WARNING  unsupported addrtype 44, maybe wrong password
2015-08-30 00:23:50 ERROR    can not parse header when handling connection from 198.35.46.6:57978
2015-08-30 00:23:50 WARNING  unsupported addrtype 222, maybe wrong password

是不是 @breakwa11 说的主动检测呢?

@coolchenK

@renyidong 看到最后,你自己被打脸了。真是笑死我了对了,以我的注册时间和发言记录,大概就是你口中的水军吧。.~

@phpbestlang

@yifei0727
aes-256-cfb1的工作模式意味着单个block大小为1bit,而非常见的128bit,在这种情况下,单个位的误差会传播影响到后续的所有块。即使在这种情况下,由于shadowsocks只校验第一位,所以特征还是在的。

@bigoktesk 不是,原因已经在log里了,自己想一想

@TearDownGFW
我忽然明白了您的意思,但IV重放不是这么做的,每重放一次需要断开连接重新连接的

@QLrGWTXz

楼主 给你想个特别简单的办法 不增加额外的信息量又能达到目的。

把17字节开始的“1.2.3类型名” 设置为随机值即可… 随机值由C/S协商好

比如说 服务器和客户端之间除了协商密码类型和密码,还要协商代表“地址类型”的随机赋值。 比如我可以设置为ABC,而不是123.

具体实现起来为了简便和安全,可以这么实现:

地址类型从1字节扩展到16字节(或者更长),3个代表“地址类型”的字符串,由服务器和客户端自动从用户密码中采取,做到不重复且随机即可。

比如说要求用户密码不少于15位,服务器自动将密码前15位分成3组,每组通过HASH等手段变换为16位无规律字符,作为地址类型的标识。

这就使得地址类型也变为“PSK”协商了。

@breaking-gfw

@phpbestlang
按这样下去,数据包的crc32值是可以有的

@breaking-gfw

@QLrGWTXz
密码15位......晕

@breaking-gfw

@QLrGWTXz
把密码hash掉再取3组又如何?而不是限制长度。

@clowwindy

我就贴个链接,什么也不说,不算“参与维护”吧。
https://github.com/shadowsocks/shadowsocks/wiki/Ban-Brute-Force-Crackers

@Yifei0727

@phpbestlang 又看了下,这种模式AES算法加密的不是明文数据,而是用于计算保护数据的密钥!
就是说利用算法、 IV、密钥产生一个用于与明文数据XOR计算的“密钥”,然后XOR后就是密文!这也就解释了为什么密文结果和明文结果一样长,而不是16字节块大小整数倍了。
那么接下来我看了了下这里 https://github.com/openssl/openssl/blob/6218a1f57e7e25a6b9a798f00cf5f0e56a02ff31/crypto/modes/cfb128.c 最后两个函数

发现,如果是8bit模式,按字节模式加密,1bit模式,按位加密,也就是说同样一段数据,是原来的8次调用,性能影响太大!
只是为什么1bit模式下会影响后续字节,我还得继续看

@phpbestlang

@yifei0727
其实是用key加密iv而已再对明文做xor而已
正常情况block大小是128bit,8和1刻意缩小的,的确会影响性能
影响后续字节的原因是因为模式的不同,OFB就不会有这个问题,具体的好好想一下

@renyidong
AES只是保证重复的明文不会被加密为同样的密文,但位置还是一样的
用dict过滤对抗重放攻击并不现实,Eve完全可以等到几天以后再做这些事,而此时你的dict不是被清空,就是已经撑爆了内存

@clowwindy
Take care

@falseen
falseen commented Aug 30, 2015

@clowwindy 但是这样也会有误伤的吧?注意隐藏自己.....

@phpbestlang

@falseen
不会有误伤,除非下次IP被分配到和之前攻击者一样的IP,但这概率并不高

@falseen
falseen commented Aug 30, 2015

@phpbestlang 我的意思是如果不小心输错了密码…这种情况应该很常见。想要避免误伤的话就只能修改客户端了(如果密码错误就停止发包,等待用户重新输入密码)。

@aOJzQT
aOJzQT commented Aug 30, 2015

运行下面的脚本,封掉试图暴力破密码的共匪骇客的IP
来一发,@clowwindy 老大 可以删楼了

Shadowsocks 2.6.2+ output the IPs that try to brute force crack your password.

You can use utils/autoban.py to ban them.

python autoban.py < /var/log/shadowsocks.log

Use -c to specify with how many failure times it should be considered as an attack. Default is 3.

To continue watching for the log file:

nohup tail -F /var/log/shadowsocks.log | python autoban.py >log 2>log &

Use with caution. Avoid to ban yourself.
#!/usr/bin/python
# -*- coding: utf-8 -*-

# Copyright (c) 2015 clowwindy
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from __future__ import absolute_import, division, print_function, \
    with_statement

import os
import sys
import argparse

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='See README')
    parser.add_argument('-c', '--count', default=3, type=int,
                        help='with how many failure times it should be '
                             'considered as an attack')
    config = parser.parse_args()
    ips = {}
    banned = set()
    for line in sys.stdin:
        if 'can not parse header when' in line:
            ip = line.split()[-1].split(':')[0]
            if ip not in ips:
                ips[ip] = 1
                print(ip)
                sys.stdout.flush()
            else:
                ips[ip] += 1
            if ip not in banned and ips[ip] >= config.count:
                banned.add(ip)
                cmd = 'iptables -A INPUT -s %s -j DROP' % ip
                print(cmd, file=sys.stderr)
                sys.stderr.flush()
                os.system(cmd)

autoban.py

@luxin88
luxin88 commented Nov 20, 2015

@bigoktesk 俺英文不好,但是你说的这个,伪造ip后如何获取到返回数据,这个对于运营商级别来说太简单了,不管是发出的还是返回的数据包,都要经过人家的设备,只要匹配一下dst和src,然后把这段数据复制下来就可以了,比较类似中间人攻击

@luxin88
luxin88 commented Nov 20, 2015

@breakwa11 日志怎么看到,shadowsocks-libev 2.3.1 没有找到/var/log/shadowsocks.log文件

@fovecifer

http://crad.ict.ac.cn/CN/abstract/abstract3031.shtml
匿名通信系统不可观测性度量方法

@luxin88
luxin88 commented Dec 1, 2015

FUCK FBX
不知道是不是真对ss的。。

@lixin9311 lixin9311 referenced this issue in shadowsocks/shadowsocks-libev Dec 3, 2015
Closed

Question and Suggestion about One-Time Auth #468

@garymaxallen

Could anybody tell me where I can find Shadowssocks OS X client source code and iOS 9 client source code? I want to continue the development.

@snnn
snnn commented Dec 13, 2015

@breakwa11 说的是对的。这是cfb设计上的缺陷。

“Bit errors in the incoming cipher block (bytes in this context) will cause bit error at the same bit positions in the first plain text block。”

source: http://www.pvv.ntnu.no/~asgaut/crypto/thesis/node16.html

其实解决办法很简单,随便换个其它的模式就行了。

@snnn
snnn commented Dec 13, 2015

再有一个解决办法,就是在头部填16个字节的随机填充。没有任何作用,就是随机填一点bytes而已。

再有,@breakwa11,既然你都提到了CRC,为何不用hmac?

@caicaicai

怎么感觉楼上像是个产品经理在跟程序员要代码。。。。人家又没有卖license给你。。。。。想稳定。。。自己学编程。。或者雇个程序员

@8884361
8884361 commented Dec 14, 2015

同上

從我的 Windows Phone 寄出


寄件者: 蔡忠振mailto:notifications@github.com
寄件日期: ‎2015/‎12/‎14 13:10
收件者: breakwa11/shadowsocks-rssmailto:shadowsocks-rss@noreply.github.com
副本: 8884361mailto:lianweijian@live.hk
主旨: Re: [shadowsocks-rss] ShadowSocks协议的弱点分析和改进 (#38)

怎么感觉楼上像是个产品经理在跟程序员要代码。。。。人家又没有卖license给你。。。。。想稳定。。。自己学编程。。或者雇个程序员


Reply to this email directly or view it on GitHub:
#38 (comment)

@8884361
8884361 commented Dec 14, 2015

然而你就沒看到已經有對應的插件出來試圖解決問題?GXFXW又沒有文檔,你只能試圖猜測行為尋找對應方法。

  • 從我的Sony Xperia™智能手機發送

---- Nemo提到 ----

@breakwa11,怎么还在讨论,什么时候讨论完毕,什么时候出来东西啊,让我们一直担心服务器不知道那天就完蛋了


Reply to this email directly or view it on GitHub:
#38 (comment)

@8884361
8884361 commented Dec 14, 2015

不支持SS-R的高級功能就是。而且這是iOS的代碼,並不能在OS X上用。所以,這只是代碼而已。

  • 從我的Sony Xperia™智能手機發送

---- akw28888提到 ----

@garymaxallen https://github.com/shadowsocks/shadowsocks-iOS/releases
There are "OSX" source code


Reply to this email directly or view it on GitHub:
#38 (comment)

@superfls

小白路过,不明觉厉,只是觉得这本来是一件好事,有人开了头,大家各尽其才,各显神通就好, 你可以有你的风度,但这是大家的选择。
Stay hungry. Stay foolish,

@liyue80
liyue80 commented Jan 31, 2016

本人大学时密码学是选修课,所以没修过,说得不对就请忽略吧。
楼主文中提到,“有三种情况下没有立即关闭连接”,某WALL如果能以此判断SS服务器的话,SS服务器就当收到错误的包时,随便回一些随机的包回去,某WALL会不会认为这是一个未知的协议呢。

@Yifei0727

我一直认为静默模式不更好?

liyue80 notifications@github.com于2016年2月1日周一 02:16写道:

本人大学时密码学是选修课,所以没修过,说得不对就请忽略吧。

楼主文中提到,“有三种情况下没有立即关闭连接”,某WALL如果能以此判断SS服务器的话,SS服务器就当收到错误的包时,随便回一些随机的包回去,某WALL会不会认为这是一个未知的协议呢。


Reply to this email directly or view it on GitHub
#38 (comment)
.

@testcaoy7

A thought:
先使用Rivest发明的 all or nothing transform对原始协议数据包进行搅混
然后再对搅混的数据包进行加密,更妙的是只需加密数据包的一小部分即可,剩余的数据依赖于加密的数据部分,如果不截获全部数据就无法解密和分析
Botan里有这个算法

@cool5
cool5 commented Mar 5, 2016

teredo服务可以临时性的提供给本机一个IPv6地址。虽然这个v6是包在v4内的,但是SS协议包在ipv6之后,拆包检测的特征是否会有变化呢?如果搭建一些teredo服务在SS服务端和客户端之间?

@jang-u
jang-u commented Mar 6, 2016

作者跟五毛掰的后果就是被精确定位
被强迫不更新
社会经验等于零

@cool5
cool5 commented Mar 6, 2016

@jang-u 作者出什么情况了?楼上知道内情了?

@dosgo
dosgo commented Mar 10, 2016

@jang-u 可怜啊,一个妹子程序员,更新。。竟然让你们气跑了。。不过原因不止这个吧

@outgofw
outgofw commented Mar 14, 2016

你们吵得毫无道理……包括@renyidong ,一开始我以为你说的是对的,直到后来发现是ss的缺陷而非cfb 的缺陷。你关于aes的理解也毫无问题。@phpbestlang,你的测试问题在于数据不够长。建议超过32字节,再进行测试。理论上结果应该是每16字节中的第一字节出问题。

大概考虑了一下,结论应该是无法做到绝对安全,在限制添加信息较少的范围内,包括lz的协议。可以通过改变256到1字节再重放来试探偏移地址。crc可以穷举。不过这样一来,如果用crc32,每次判定的成本是256^6。另crc范围可以减少,目前我能想到的是前32字节crc,不知道有没有漏洞?

@lersh
lersh commented Mar 16, 2016

作者的ssr非常好,解决了我的燃眉之急。我不知道指责作者重新发明轮子和代码质量差的人是什么心态。反正在ss不能用后,ssr让我重新连上了fb和tw。你们不动手不肯贡献代码为什么还要来指责一个肯脚踏实地的妹子?

@breakwa11 breakwa11 closed this Apr 18, 2016
@dawei101

虽然关掉了,但表示楼主很棒。思考很深入,我们需要你。加油

@zagfai
zagfai commented Jul 27, 2016 edited

总算看完争论了

ss ota看上去已经解决问题

如果包的字节数非常少 是不是还是存在被穷举的风险?

@andy520
andy520 commented Jul 27, 2016

其实功夫网现在是睁一只眼闭一只眼,毕竟人家中科院院士都出来说话了,墙如果堵死了会影响学术资料的获取

2016年7月27日 23:00,"Zagfai" notifications@github.com写道:

如果包的字节数非常少 是不是还是存在被穷举的风险?


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#38 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AMQ2rMiUaXWN7bPrtV_s8VsvpTKlKhMwks5qZ3KcgaJpZM4F0NPQ
.

@PowerOlive

@andy520 very correct

@PowerOlive

@breakwa11
Thanks.

@Void-Malkuth

"But why don't GFW ban your SS ip directly?" @bigoktesk
I believe that is because it can easily cause your ss server reject yourself while not harming normal internet traffic,as long as you enabled your autoban. It can do this trick on some suspectsed hosts.

@Qingluan

@phpbestlang @renyidong 作为一个学密码的。。我得先说下, 你提到的 一个密文 对应明文 ,或者明文对应 密文是不存在的。。。除非这玩意根本就没实现AES, 或者只在古典密码里面。。。而现代密码的 不管是流密码, 或者分组加密,都有一个很重要的一步,混淆。这个特性的具体效果就是,让明密空间不再简单对应(任何对明文的一点更改,会导致整个密文改变)
https://en.wikipedia.org/wiki/Confusion_and_diffusion#Analysis_of_AES
screenshot

@breakwa11 @renyidong 但是像 @breakwa11 所说的。如果IV填充不当确实是可以探测出代理的特征的
后续我会附上测试的

@zagfai
zagfai commented Aug 26, 2016

@Qingluan 不是, 由于这个东西使用了流加密,导致了每一个字节是一个分块,没有了混淆效果。
我觉得比较靠谱的方法是直接block填充。用padding。每一次发送数据直接128bit。这样旧没问题了

@breakwa11
Owner

@Qingluan 来来来,来写,我非常想知道你是如何理解的,反正我的主动探测代码已经从去年就写好了,到现在都还能正常使用,正确检出SS服务端

@Qingluan

首先我看了下,加密部分的代码(只针对 aes-256 ) 这个部分直接使用openssl,
screenshot
它用了EVP_CipherInit_ex , 所以不会出现每次都重置初始化,也就是说cfb模式只有第一包最有可能被监测出来,@zagfai 这个是直接调用openssl的aes,cfb只是分组加密的方式类似流加密的 反馈寄存器的方式而已 ,它对每一个块都会padding的啊
screenshot

其次 我对ss的tcp部分的连续10000个 tcphdr->len > 0 的报文进行了随机性监测,结果如下
kde.pdf
kde -fig
前 40 个bit 的分布,能很清楚的看到,几乎能均匀地分布到0-255, 也就是说每一bit的 都是很均匀的,随机性很好。

然后对所有报文的进行 每一位进行期望计算,这个看上去简单粗暴
mean
每一位的均值,最小的也没有低于120,最高的没高过132

我反而很好奇你的探测是如何捕捉到特征数据的
@breakwa11

@Qingluan

最后附上 kde 前40bit payload 的分布图
screenshot

@Qingluan

@phpbestlang 对于你说的那种情况,我没遇到过,你确定用的aes-cfb-256 模式是调用了openssl的还是个人实现的流密钥 冒充aes?

@breakwa11
Owner

其实你把前面的所有人的回复都看过了么。。。前面不是有人已经解释很清楚了么。。。我这个不学密码学的都知道你这逻辑推理哪里出了问题。。。最后这个统计更是毫无说服力。。。。

@Qingluan
Qingluan commented Aug 29, 2016 edited

有问题的地方你明说出来 。
前面的评论我看了。
你们一直在说流密钥 流密钥 ,这个根本就没有用流密钥加密,aes-cfb-256的块填充没有问题。

说我有问题的,请具体指出,哪里, 证据, 数据,结果,分析,
而不是单纯的说我有问题。别乱逼逼
其次,说我统计没有说服力的,我已经写明这个统计的来源 ,统计数据,和结果,以此来证明一点,ss本身的数据在前 40 bie都很随机,没法拿到特征。并不需要说服什么 。

我在最后已经注明,你说你能检测出ss的数据,请拿出数据,和证据附上来讨论

@breakwa11

@breakwa11
Owner
breakwa11 commented Aug 29, 2016 edited

我只能说你是一个好人,只想着从正常的角度去看问题,而且你没有理解cfb的具体代码实现是怎么做的,从你所说的

cfb只是分组加密的方式类似流加密的 反馈寄存器的方式而已 ,它对每一个块都会padding的啊

就知道,你其实根本不知道标准的cfb实现是怎么样的,谁告诉你会padding的?这又不是cbc
cfb根本就是流加密,cfb模式就是让块密码变成流密码,变成流密码自然就存在所有流密码相同的通病
更严重的是,你一直在说的是加密的方向怎么怎么样,但明明本issue说的是解密方向如果恶意构造数据会怎么怎么样,你完全就理解错了好了么?

@Qingluan
Qingluan commented Aug 29, 2016 edited

@breakwa11 谁告诉你使用分组加密的时候不需要padding的, padding不是指 cfb模式的时候padding, 而是对于block pading,否则没法加密, 有兴趣你自己看下分组加密经典的gird的流程说明就明白
这里我简单放了个des的轮函数流程,aes camillia 3des ,等一系列的分组加密 都遵循这个网格结构,而

正是这种网格结构使得 其必须 !!! padding

screenshot
这一点上 你再扯也没用。

再来说cfb,这个确实是很标准的流密钥模式,但是它不是把分组加密变成流密码

所谓的cfb是对如何应用分组密码的中的块的模式, 对于一个块而言,同样运用标准的分组加密

cbc 模式和 cfb模式的的表达式分别是
cbc : C[i] = aes( P[i] xor C[i-1]) ; C[0] = iv
screenshot

cfb : C[i] = aes(C[i-1]) xor P[i] ; C[0] = iv
screenshot

其操作几乎是一样的(这是wiki上的原话
screenshot
),只在加密顺序有差别。

谁告诉你会padding的?这又不是cbc
cfb根本就是流加密

你不懂麻烦你看懂后在说,别腰疼

后面我来说解密的部分

@breakwa11

@Qingluan

screenshot
P[i] = aes(C[i]) xor P[i+1] # 这里便成 i+1 其他和加密是一摸一样的
这一点使得 每一个块的混淆性都会扩散到全部
这是aes - cfb的解谜过程

对于一个块的解密,它同样遵循
AES的标准
https://en.wikipedia.org/wiki/Advanced_Encryption_Standard#High-level_description_of_the_algorithm

先不说一共进行多轮的 线性和非线性的变换
单轮的变幻中 就能保证起混淆性
screenshot

而这个S-box 几乎让所有的线性对应关系 gameover 真是对抗“差分攻击” (differential cryptanalysis)(你说的恶意构造只是插分攻击中的简化版,有兴趣你自己看吧。我就不放链接了。这个我也没学懂,但是知道流程和原理)
screenshot

。最后结论就是, 你所说的恶意构造密文来影响特定明文情况是不存在的,哪怕对单个块
screenshot

aes-256-cfb 单独一块都是

32字节

32字节

32字节

重要的事说三遍,

不是 1字节 @zagfai @breakwa11

所以我很好奇, @breakwa11 , 你是怎么通过恶意构造密文提取到特征的,还是说你提取到的是tcp 活着ip的特征,这一点上我并没有嘲讽,是真的好奇

@breakwa11
Owner

看来你还是不懂具体的cfb的实现方式,我还是给你重复一下,cfb的实现不需要padding,更不是一字节还是多少的加密单位,而是完全的流加密,你可以按位来处理,亦可按字节来处理,具体实现你看OpenSSL的实现就好了啊,这个和AES压根就没有关系,这是所有的cfb/ofb/流加密的共同问题
我真的不想对每个人都去科普cfb实现啊
另外我一年前写过的攻击代码你真的看都不看?这弱点早已经被我做成成品了

@chinawrj

@breakwa11 有的人更喜欢相信自己理解的那个理论。其实我想 @Qingluan 可以换个角度:如何解释 @breakwa11 的主动探测脚本是有效的。

@maxchendt

哎呀,一周年了!不容易。
搜索OTA (One-time authentication,shortened as OTA) 读着读着连接到这里来了。
请问 ss 起了 OTA,breakwa11 的程序还能侦测出来吗,还是我的问题本来就是两个不同的概念扯在一起?

@breakwa11
Owner
breakwa11 commented Aug 29, 2016 edited

@maxchendt 这针对的是原协议,非OTA协议
补充:目前对OTA没有可靠的办法探测出来,但有办法阻断

@Qingluan

是啊一周年了。。。不容易啊
@chinawrj 我也是这么想的
@breakwa11 我倒是想看啊。。没找到。麻烦给个链接。这种有趣的东西 就该多讨论

我重申一遍我的态度,我没有想攻击谁 ,我对repo 主非常敬佩的,对于此gist非常赞成,也不想引起骂战之类的,如果觉得我对repo有冒犯之处,我道歉。

但是对于那些冷嘲热讽,没有干货还发着段子的家伙 比如@stdstx 这样的,我只有

MDZZ , 熊孩子一遍玩去

回归正题, @breakwa11 我知道你说的是啥意思,可能是我表达有问题吧。你想表达的是下面这个吧(语文差,就不自己解释了)
screenshot

你的办法是,尝试让地址位置的数据能够穷举 255个,然后只要找出对应3个就能探测吧。我还是用代码描述

count = 0
for bit in range(255):
     nwe_header = change_addr_bit(bit, old_header) #只更改地址位
        code = send(data)  # data 包含了新的头
        if failed:
           count += 1
if count == 3:
    gfw.do_some(this_server)

这是我对你描述的理解,你看下有错么
没错的话我接着往下说

这个方法有一个前提吧,
就是要能计算出 对于单个 bit 的全部 密文空间 (就是你说的 0-255 )我的统计,就是为了测试能不能非常快的穷举这个空间,结果是混乱的数据依旧能够 映射到均匀的密文空间。

screenshot

你的办法就是要更改这个明文的第一个字节对吧,( 0-255)

然而AES 没法做到 你改 1bit 还能构造出一个合法的密文,

除非 服务器,只管 这1bit,其他数据解密对不对都不管。

其次,
screenshot

iv 是随机的,对于一段时间的连接需要捕获到第一次的包,第一次之后这个唯一能拿到的密钥就失效了

最后一点,我也不想重复了。 aes-256 的最小粒度 真的是32字节,cfb只是模式,它没法改变最本质的加密流程。
所以我真的很想看下你的代码啊。。。

最后,我看了你的改进方法,假设你说的都成立,我的一个最高效的改进的思路是,借鉴防御扫描器的思路,把正确的包收下,错误的包,不管是探测还是网络错误的包,drop掉就行,不用立刻断掉连接,也不给反馈,这样对于探测就能大大让其没法判断。当然这样对于网络的稳定性没法保证了,如果这点也要兼顾,那就引入类似ipsec的会话机制吧

@breakwa11
Owner

#50 自己看,不想科普,你可以对你自己的ss服务器或别的啥服务器测测看,你根本没懂CFB

@breakwa11
Owner

另外想问个无关的问题,你是密码学博士?

@dosgo
dosgo commented Aug 29, 2016

同问

@Qingluan

不是,群环域伤的证明,我最多看懂,不会证明。
只是我导师很屌,要求很高,所以我会这个,也知道点怎么分析密码算法的优缺点。所以不用和我争这个,除非你去把美密那群人打死。
别一直说我没懂没懂cfb的。。。我懂这个。你只是盯着cfb不用padding ,我一直在强调我知道你在说啥,麻烦你看下我发的东西好么。。。这一点上我也不想和你扯了。。
screenshot
代码还没看,先测了。。。结果如上,回家后我会去看遍代码的。

还有最后,能别带着偏见好么

@breakwa11
Owner

那你真不知道要翻转CFB模式下的解密原文的某些位,只要xor对应的值就行了么。。。。你自己写两段代码解密一下就知道了啊,说这一堆东西,还是错的,你自己说的内容和你截图的内容都是矛盾的

@breakwa11
Owner

另外我不清楚你那个运行结果里,那个IP端口跑的是哪个分支哪个版本的服务端,最近新加的IV检测我只测试过ss-libev/python这两版本,如果是其它版本,由于实现的不同,你可能需要从历史代码里翻旧版本

@Qingluan

哎,我知道啊。
screenshot

iv 你能在第一次拿到

这个
screenshot
你怎么拿到,你别告诉我你 要 255 ^255 ,
构造了第一个 [0-255] [...]这个后面的你不管?

我服务器端就是python的 ss

screenshot

@Qingluan
Qingluan commented Aug 29, 2016 edited

screenshot

我附上了 ip , 端口 , 和运行着 python 版本 sss的证明

@breakwa11
Owner

我刚刚在VPS用旧版本的代码攻击了一下你给的地址,结果检测出是SS
你可以使用这个版本的代码测试

https://gist.github.com/breakwa11/73c1a2a5c8a3dfa5bac7/c7ffac2a3492a1c85fbc9766ffc34378d772fd88

因为原SS的python实现的问题(就是个实现错误),导致新版本反而没检测出来

@breakwa11
Owner
[root@host-meow shadowsocks]# python att.py 
0%
5%
10%
15%
20%
25%
30%
35%
40%
44%
49%
54%
59%
64%
69%
74%
79%
83%
88%
93%
98%
Waiting response
Double check
45.62.100.165:3007 is a Shadowsocks server
@Qingluan

嗯,成功了,👏 。我回去研究下代码。厉害的妹纸

@breakwa11
Owner

你只要搞清楚,如果iv长度是16,你加密明文为
01 02 03 04 05 06 07 08
加密后,如果我想把解密后的01变成03,很简单,只要对密文的第17字节 xor 2就得到想要的结果
因为CFB是流密码,自然获得了流密码的特性,和AES是多大的块来做的加密完全没有关系

@Qingluan

这个我明白。
我知道我误解了什么,我一直理解以为服务器会完整的检测整个密文内容
看了你的代码,发现,它只要一位的。。。我去。。。。这个检测也太简单粗暴了吧。。。。

@Qingluan

再次为你👏。厉害,有时间我也改改这个ss吧。

@breakwa11
Owner

你可以先看看我的最新协议实现,你有tg或twitter吗

@Qingluan

Mroy_F , 有机会多交流吧

@chinawrj

@Qingluan 同学,我们有空多交流啊。我不是搞密码学的,但是工作中涉及到。图解密码学那本书看了很多次,科普用的。但是我觉得看了那本书就知道这里讲的是什么内容了。

@Qingluan

Mroy @breakwa11 twitter

@tony1016

把块密码工作原理又翻了一遍,确实,出了ECB,其它的CBC,CFB,OFB,CTR等,最终都是和某个可被更改的值做xor出来的明文,确实都会被探测。ECB不是,但是又因为其统计性而不安全。看来确实只能从协议上入手了

@phpbestlang
phpbestlang commented Aug 30, 2016 edited

@Qingluan 来晚了,汗颜,看来你已经认识到了自己的错误
只说两点

  1. 这不是对AES的攻击,这是基于服务器的行为进行的攻击,另外你所谓的“完整检测整个密文的内容”在没有OTA的情况下不可能实现
  2. 你其实不理解加密的本质,也不理解块密码的工作原理。AES在这里实际上是作为PRNG存在的,意图通过XOR伪随机数来擦除明文的概率分布偏差,你辛辛苦苦画的那些图恰好证明了你至少不会正确使用AES
@Qingluan

@phpbestlang
你说我不懂就不懂吧。 虽然我用着我自己设计实现并通过测试的密码算法。。。

完整检测密文内容是完全可以做的,并且你一直在用。一种混合了对称算法混合非对称的方案

@breakwa11
Owner

通过什么测试的密码算法。。。

@Qingluan

伪随机 01平衡 周期测试没做,前面的两个过了懒得下去了。。。

@Qingluan

感兴趣你可以研究下
screenshot

结构这样的,实现的时候我加了点料,最后用一种脑洞大开的方式伪实现了一次性加密。。同key,同p,每次都可能是不同的密文

@phpbestlang
phpbestlang commented Aug 30, 2016 edited

@Qingluan

完整检测密文内容是完全可以做的,并且你一直在用。一种混合了对称算法混合非对称的方案

愿闻其详

另外您这个图太魔幻了,作为一个不学密码也不敢自己设计密码的看不懂,有没有像上面贴的DES那样比较正规的流程图可以看一下?

@Qingluan

你银行的那个hub 就是一个非常标准的。
大致这样,具体细节记得不是很清楚,你可以查下
1,公私交换
2,payload=公钥加密分组的密钥 + 分组加密的密文 + hmac (这个就是验证完整性的,加密的hash)
3 发送后,就不用我解释怎么解密了吧

@Qingluan
Qingluan commented Aug 30, 2016 edited

上面的流程图,没有标准的图,大致解释下吧 。从左到右 ,
初始化序列
screenshot

padding
分组
screenshot

带记忆的 反馈线性变换
screenshot

后面是非线性的部分,用了分组的s-box做非线性变换 背包作为数学难题。
大致就是这样。。。
我github上有一个c的实现。。代码现在看来很烂。还混合了camillia的破代码。不过也不想改了。。。看的眼睛疼,你愿意看我也贴出来

https://github.com/MLCIS/I_Camellia

最后,嗯这个算法,我取名 aptx4869 。。。
虽然效果和 aptx4869 正好相反

@phpbestlang

@phpbestlang

@Qingluan
我还以为你在说用对称非对称混合做完整性检测。。。那不还是靠HMAC做完整性验证啊。SS的OTA实现实质就是HMAC。我说这个是因为你说服务器竟然没有完整检测整个内容,但实际上没有OTA的帮助是做不到的。

算法太复杂,等我看明白了再来请教。

@Qingluan

@phpbestlang 嗯,是我理解错了

@zagfai
zagfai commented Aug 31, 2016

@breakwa11 OTA为啥能够截断?能分享下原理吗?

其实我觉得OTA是复杂了,只要密文中有足够的身份识别信息,
外界就没办法知道是什么原因服务器会关掉连接。

@breakwa11
Owner

@zagfai 不想说

@zagfai
zagfai commented Sep 2, 2016

@breakwa11 靠响应时间统计吧?

@breakwa11
Owner

@zagfai 不,比检测原版还容易的方法单独把OTA全部阻断,其它流量正常的手段而已

@dosgo
dosgo commented Sep 23, 2016

ss正式被封了?我用不了了

@BillLeecn

看完了上面的全部内容,我自己复述一遍,就是:流密码以及 CFB/OFB 模式的一个 block 内会有 ENCRYPT(Plaintext XOR x) = ENCRYPT(Plaintext) XOR x 的逐位对应关系,以及 ssserver 使用一个 bit 来决定做校验,共同造成了这个问题。

如果使用 CBC 模式,是不是可以解决这个问题呢?

另外 OTA 应该也已经解决了这个问题吧?难道还造成了新的问题呢?

@oloukou
oloukou commented Sep 24, 2016

@BillLeecn 如果上文phpbestlang提到的AES一一对应的确存在——不是学这个的没这个水平来判断——那么CBC模式也没用,顶多是不在第17字节罢了。
结合作者blog,对OTA的攻击方式其实挺容易想到了,虽然在我看来对墙的目标是杀敌八百自损一万。值得注意的是作者指出了「有OTA功能但没开」的服务器的高风险,看措辞应该是实现相关的(我没验证),赞一下作者的耐心。
回到攻击脚本上,现在的动态检测iv后再针对性构造,从节省总时间的路子上应该是对的(虽然对个别实现动态检测有毛病),但依然完全依赖第17字节这个预先分析出来的magic number,对没有IV协商这一步的更不安全的协议RC4反而只能抓瞎。总体来看我还是怀疑有没有可能把判断所有SS配置的脚本在可接受时间内跑完的可能——上文提到的两个版本合起来仍然无法搞定。但总体上看SSR通过增加层次(加密、验证、混淆vsSS只有加密)来指数级提高难度的思路是正确的,这让写出类似思路的统一攻击脚本难度大大上升。

@breakwa11
Owner

@oloukou cbc有用,但目前没法用。
rc4现在所有分支都不支持
现在因为攻击难度的下降,之前的攻击代码可以不用那样写了,而且可以准确很多。防探测的协议我还在设计并测试中,应该不久后会放出来

@oloukou
oloukou commented Sep 26, 2016

@breakwa11 呃……那能解释下「cbc根本没有解决我在文章中所说的问题,文章中本来就考虑到了」这句话的正确理解方式么?谢谢

@breakwa11
Owner

@oloukou 因为SS不使用CBC啊,SS的设计使得只能用流式加密,既然没法用,就没法用于去解决

@MilitaryRiotLab

我想提出新思路,
SilentKnock ( http://www.cs.umn.edu/~hopper/silentknock_esorics.pdf ) 不知道能否阻止主動探偵?

  • Knocking is stealthy: as in SilentKnock, the secret to open the port is part of the TCP SYN packet's SQN, so there is not a single extra packet on the wire (one Knock instead of KnockKnock). Thus, using Knock is indistinguishable on the network from a standard TCP handshake. Furthermore, as there is only one packet, there is no window of opportunity for an attacker to use, as would be the case if a first packet enables the server.
  • Our Knock optionally does not merely enable opening the connection, but also can be used to protect the first N bytes of the TCP payload. Thus, given a sane protocol being run above TCP (one begins with a key exchange), an active attacker cannot simply take over the TCP connection after the handshake without also being locked into sending the same TCP payload. Thus, if the client begins by sending his public key and then continues to send data that must be authenticated with that key, even an active man-in-the-middle adversary cannot hijack the connection.

取自 Ref1 https://gnunet.org/knock
Ref2 http://www.degruyter.com/downloadpdf/j/popets.2016.2016.issue-4/popets-2016-0028/popets-2016-0028.xml

PS 我是小白,請不要罵我

@BillLeecn

@shamkoonyu 工程上不太可行,操作系统的 TCP/IP 协议栈一般不支持设定 SQN.

@MilitaryRiotLab

如果用普通的port knocker是否有用?

@linkerlin

我自己用Java的Quasar重写了一个ShadowSocks的服务器端。
为的就是抹去所有的协议在时间序列上的特征。

@breakwa11
Owner

@linkerlin 你的repo是哪个,给我看看?

@linkerlin
linkerlin commented Sep 27, 2016 edited

针对探测 3/256 判断是SS的方法,我做一个改动,我把所有不认识的地址视为 ADDR_TYPE_IPV4

if(addressType!=SSHeader.ADDR_TYPE_IPV4 && addressType!=SSHeader.ADDR_TYPE_HOST && addressType!=SSHeader.ADDR_TYPE_IPV6) { log.warn("被探测了!!!,我们伪装下。"); addressType = SSHeader.ADDR_TYPE_IPV4;// 避免被探测 }

@breakwa11
Owner

@linkerlin 你觉得这会有用么?如果你的实现推广了,我再给你写个主动探测脚本,我最近是没空管这个了

@breakwa11
Owner

@linkerlin 你开源了再说,不开源还要花我一下午去猜测你的实现,这时间我消耗不起

@noel-zhang

从头看到尾,前面那些人身攻击看得我抓耳挠腮。
直到@Qingluan 的出现,有一些真实的技术探讨。到29th/Aug 达成共识后一切变得坦然了。
@breakwa11 加油,目前国内许多VPN 都已经被屏蔽。就靠你们了,我是做IC 的,最近也会接触一些加密的东西。不管是IT 还是IC,渴望自由之人,都只能行走在暗影的保护之下。

@yuanl yuanl referenced this issue in jlund/streisand Nov 7, 2016
Merged

add shadowsock OTA, enable fast_open #400

@502647092
  • 新萌围观大佬们
@Mygod Mygod referenced this issue in shadowsocks/shadowsocks-org Jan 12, 2017
Closed

Refine doc for OTA #29

@elespec
elespec commented Jan 13, 2017

我一直都不愿意承认这是一个妹子..可这确实是一个妹子...

@wnxkiwi
wnxkiwi commented Jan 13, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment