使用了架设在自己服务器上的Seafile一段时间,本菜对于其宣传的“端对端加密,数据在客户端解密”这个特性产生了好奇。很想了解一下网络传输、加密的过程是如何运作的。不多说,我们马上配置好Android上的抓包环境,用fiddler看看网络传输的内容吧。
系统 : Windows 7、nexus 5
程序 : Seafile 2.2 for Android
程序下载地址 : 710K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2V1M7X3g2S2L8h3y4J5j5h3y4C8k6i4u0Q4x3X3g2G2L8X3I4A6L8X3g2Q4x3V1k6V1i4K6u0r3z5e0x3#2y4K6u0T1k6X3g2V1z5o6p5J5y4r3f1%4z5e0S2W2j5h3u0Q4x3V1k6X3K9h3I4W2M7#2)9J5c8W2)9K6c8Y4m8Q4x3@1c8Q4x3V1k6o6M7X3q4U0K9#2)9#2k6V1#2W2i4K6u0r3j5$3!0E0i4K6u0W2M7$3g2S2k6X3W2D9k6g2)9J5k6i4y4W2j5h3c8J5L8$3W2V1x3W2)9#2k6U0R3K6i4K6u0W2j5i4m8C8
要求 : 分析逻辑
使用工具 : fiddler、apktool、AndroidKiller、Android Studio、 smalidea插件
确认端对端加密设置启用后,打开设置好的加密资料库secret,输入密码:

此时捕获到了这样几个包(关键位置已打马赛克):

这里post密码,服务器认可。

返回了资料库的一些信息,比较值得关注的有加密类型、magic、random_key。

接下来请求根目录内容,Response以json形式展现了资料库根目录内容。
此时,我们请求一个文件,看看传输来的数据如何。



获得服务器生成的下载的链接,然后得到一段密文。这里文件的大小是120字节,而传输过来的文件大小是128字节。
再随机拍张照片上传,此时抓到的文件数据和本地的很不相同

综上所述,我们可以做出如下猜测。
1.服务器对于加密资料库提供了端对端加密的方式,即文件在本地解密,即使有人攻击了传输链条中任意一环,也无法直接获得明文消息。
2.加密资料库以“端加密方式”开放时,会生成随机消息用于加密。
3.加密方式是通用的公开算法,且有可能是cbc模式。
我们使用最新的apktool做为反编译工具,发现提示反编译成功。那么,直接设置我们的apktool的路径作为Android Killer的默认反编译器。我们直接全局搜索“加密”:
接着全局搜索enc_title,发现出现很多xml文件,再仔细看看,其实更多是重复的多语种的string资源文件。经过筛选,发现\res\xml\settings.xml的这一行很可疑:
全局搜索“client_encrypt_switch_key”,发现SettingsManager.class有两个函数较为可疑,我们将其smali文件转成Java代码查看:
isEncryptEnabled明显是判断“端对端”加密方式是否打开的函数,想必要调查用户选择的加密方式的手法也就是调用它了,全局搜索“isEncryptEnabled”试试。
搜索结果有两个是\data路径下的SeafRepoEncrypt、SeafRepo两个类文件。但项目内引用SeafRepoEncrypt类的次数较少。我们来看看SeafRepoEncrypt的定义:
搜索其调用,还是有两个较为可疑的引用,seadroid2\ui\dialog下SetPasswordTask、PasswordDialog类。
其中,PasswordDialog类的onTaskSuccess函数使用 用户输入的密码、random_key生成了password:
然后调用了this.dataManager.setRepoPasswordSet:
saveEncKey函数向数据库插入一条记录:
再来看看生成password的Crypto代码:
其中,seafileDecrypt的定义
好了~
至此,我们可以提出假设:
在输入密码进入加密资料库时,会利用random_key、用户输入的密码生成一个最终password,这个password将作为aes_cbc加盐算法的key被存储。而在下载/上传文件时,必然调用加解密函数,存储的password也必然被查询。
我们在Android Studio中安装smalidea插件、载入反编译的smali项目。连接Nexus 5后,对于Crypto中的重点函数布下断点,开始动态调试。我们输入资料库密码后确认,服务器发来消息:


我们在看看此时断点的情况:

用password、enc_type、random_key构成参数,开始构造最终key:

构造key、iv。继续跟

发现加盐了

最终生成一组密码对。
当我们在资料库中下载一个文件时,传回的文件流如图所示:

而程序此时断在了解密函数:

解密函数的密钥对与上面生成的相匹配。

等到程序返回,就会将解出的明文写入文件。
再来观察一下细节,加解密相关的函数很简单朴素:
而构造key函数却很值得玩味:
以口令生成key_iv对,解密random_key,用其生成此次通信的key_iv。
而构造key、iv的函数都是利用PKCS5S2ParametersGenerator 这个类将传入的数据+盐生成一个值:
PKCS5S2ParametersGenerator定义:
盐值:
我们通过抓包分析、静态分析提出了关于seafile端对端加密方式的假设,最终以动态分析的方式确认了我们的想法。根据官网的介绍:
可以推论,一次加密资料库传输是这样发展的:
接着用 ture key_iv 加解密文件,客户端服务器间传输文件都是加密后的密文。试想,排除控制了使用者终端这种极端情况,如果攻击者可以侦听https传输的内容,但没有获取最开始传输的口令,那么就无法解析传输的内容。
[培训]科锐逆向工程师培训第53期2025年7月8日开班!
最后于 2019-2-2 10:17
被kanxue编辑
,原因: