导语:CryptKeeper的代码纰漏因外部调用工具环境变化触发,导致用户输入的加密密码被字符串"p"所取代。
1 事件起因
2017年1月31日,Softpedia网站发布了一篇名为《Cryptkeeper Linux Encryption App Fails at Job, Has One Letter Skeleton Key – "P"》的文章,其中提及,CryptKeeper应用在Debian 9中存在一个BUG,会使得用户为加密文件夹设定的密码被替换为单个字符“p”,从而使字符“p”作为解密由其加密的文件夹的通用密码。
文章引用了Kirill Tkhai于2017年1月26日在debian社区(bugs.debian.org)提交的Bug信息。安天CERT为验证此消息的准确性,对所涉及模块的源代码进行了分析。
2 事件验证及分析
CryptKeeper是一款工作在Linux平台的加密文件夹管理软件,具有安装、卸载encfs文件夹和更改文件夹密码、创建新加密文件夹的功能,可与默认文件管理器集成使用。CryptKeeper使用GTK库编写,底层对encfs模块进行了封装,使用AES-192/256算法对文件进行加密。
产生问题的代码位于cryptkeeper/src/encfs_wrapper.cpp,在该代码中,作者使用了encfs的-S(Stdinpass)参数,从标准输入读取用户输入的密码。
在旧版本的encfs中,会给出两个选项,让用户手动选择一个加密的模式:
CryptKeeper根据旧版本encfs的设定,在代码中硬编码了"pn"选项,来模拟键盘输入,以选择paranoia模式(具有更高的加密强度)。以模拟键盘输入的方式实现加密模式选择,显然是不够严谨的,这就为后来的“通用密码事件”埋下了隐患。不过,由于encfs并没有提供其它的调用接口,CryptKeeper也没有更好的选择。
而本次事件中涉及的Debian9,仍处于测试版(unstable)阶段,使用了较新的encfs(1.9.1-3版)。新版本的encfs在-S参数的解析过程中不再读取模式,而是使用预配置的标准模式,并直接从输入中读取密码:
在源代码中也可以看到对应的流程,其中useStdin这个布尔变量在参数为-S的时候被设置,通过fgets读取用户输入的密码。
导致CryptKeeper出现该问题的encfs相关代码,为2016年9月由encfs作者于提交。
在encfs的新版本中,对于模式的指定如下:
而在旧版本中,模式的指定使用了不同的代码:
在新旧版本中,对于同一个Config_Prompt模式,是否指定useStdin(-S),行为是不一致的。在新版本中,如果指定了-S并且模式为Config_Prompt的话,会使用标准模式。
因此,CryptKeeper中硬编码的"pn"值被encfs直接看作密码,而实际应使用的密码被抛弃。由于-S模式关闭了输入回显,这个BUG并不容易发现。
而当用户重新加载时,输入原有密码,就会得到如下的"密码错误"提示:
3 事件影响
该事件的影响范围有限,因为:
1、 CryptKeeper的使用人数较少,作者甚至一度停止了维护; 2、 该Bug目前只出现在使用了encfs最新版本(1.9.1-3)的系统上,而此版本并未被很多发行版所采用; 3、 在事件发生后,CryptKeeper作者已从Debian 9的官方源中移除了自己的软件,并将在修复后重新上传该软件。
不过,对于CryptKeeper的用户来说,该事件的影响却是恶性的。一方面,不知情的用户在解除挂载后,将无法再次访问自己的加密文档;另一方面,用户数据在攻击者面前毫无加密强度可言,隐私数据可以被轻松解密获取。
4 关于CryptKeeper作者
CryptKeeper的作者Tom Morton预留邮箱为[email protected],而blueyonder.co.uk域名的注册单位为维珍媒体(Virgin Media)。目前, blueyonder.co.uk和virginmedia.com均指向同一页面。Virgin Media是一家英国公司,为企业和消费者提供固定和移动电话、电视、宽带互联网服务。
作者于1995年在英国布里斯托大学(University of Bristol)获得政治学学士学位,专们研究美国政治、国际关系、政治理论和撒切尔主义。作者在维珍媒体担任执行规划总监(Executive Planning Director)期间,在github启动了CryptKeeper项目,代码最早提交时间为2007年7月12日。目前作者在美国R/GA公司任高级副总裁(SVP Strategy)。
5 总结
通过上述分析可以看出,这个自2007年起就一直以硬编码形式存在于CryptKeeper源代码中字符“p”,之所以在2016年成为可以破解加密数据的“通用密码”,是因为其调用的encfs修改了一个参数(-S)的执行逻辑。
由于此事件给用户造成的后果是明显可感知的——用户使用所设定密码无法解密数据——我们可以初步定性这是一个Bug,而暂不倾向于认为这是一个由开发者(包括 CryptKeeper的开发者和encfs的开发者)预制的后门,也暂没有迹象表明这是一次由攻击者入侵开发环境造成的代码污染。
这个案例再度说明了系统安全的复杂性——特别是系统安全和数据安全“连接部”的脆弱性。对于围绕开源系统(也包括闭源软件)构建的开发环境的环境安全、过程安全,以及更广泛的供应链安全,我们还需擦亮双眼。