问题背景
几个月前,我偶然读到Mark Murphy 2016年关于安卓FLAG_SECURE窗口泄露的博客文章。这类漏洞已存在多年,因此我最初不确定是否还能在现代安卓应用中利用相同弱点。但事实证明我过于乐观了——经过简短调查,我发现该问题至今仍在许多密码管理器(及其他应用)中存在。
FLAG_SECURE的作用与误解
FLAG_SECURE最初作为WindowManager.LayoutParams的附加设置引入,用于防止受DRM保护的内容出现在截图、屏幕录像或“非安全显示”中。后者专指通过MediaProjection API(捕获屏幕内容的原生API)创建的虚拟屏幕,与物理显示设备(如具有DRM安全视频输出的电视)区分。谷歌通过此机制防止未签名应用创建虚拟“安全”显示,仅允许投射到物理“安全”设备,从而规避了盗版应用问题。
尽管FLAG_SECURE如今很好地实现了其原始目的(令Netflix、Google Play Movies、Youtube Red等满意),但多年来开发者误将此“安全”标志视为安卓提供的简易全能安全功能,认为它能阻止整个应用被截图或录屏。遗憾的是,该功能并非全局生效,只能设置在包含敏感数据的特定屏幕上。更糟糕的是,应用中的每个安卓片段都不会遵循为Activity设置的FLAG_SECURE,也不会将该标志传递给您该Activity创建的任何其他Window实例。因此,许多原生UI组件(如Spinner、Toast、Dialog、PopupWindow等)仍会将内容泄露给具有适当权限的第三方应用。
研究方法
经过简短调查,我决定研究内容泄露影响最大的应用类别:移动密码管理器。这也是普通攻击者可能首选的目标类别(与银行应用并列)。基于此,我启动了一款屏幕录制应用(mnml)开始测试。
几天后,发现所有受测的安卓密码管理器(4款)均存在不同程度漏洞。以下章节总结了发现的问题。所有漏洞均在2019年5月第二周披露给供应商。
漏洞详情
1Password
在1Password的“账户设置”部分,用户可管理1Password账户。其中一项功能是“Large Type”,用于以大字清晰格式显示账户的Secret Key。显示Secret Key的片段会将生成的密码泄露给受害者设备上安装的第三方应用。Secret Key与用户的主密码结合,用于创建加密账户数据的完整密钥,并在服务器端提供保护。
该漏洞于2019年5月29日发布的1Password for Android 7.1.5版本中修复。
Keeper
当用户点击密码字段时,Keeper会显示“已复制到剪贴板”的Toast提示。但如果用户通过“眼睛”图标显示明文密码,Toast也会包含秘密的明文密码。显示复制密码的片段会将密码泄露给第三方应用。
该漏洞于2019年6月21日发布的Keeper for Android 14.3.0版本中修复,并发布了官方公告。
Dashlane
Dashlane提供随机密码生成功能,可在插入或编辑账户条目时使用。遗憾的是,负责选择“安全”密码参数的窗口对受害者设备上的第三方应用可见。
请注意,攻击者还可能推断出泄露密码关联的服务,因为服务列表和自动完成片段也缺少FLAG_SECURE标志,导致其泄露。
该漏洞在Dashlane for Android 6.1929.2版本中修复。
攻击场景
多种场景可能导致用户手机上安装的应用记录其活动:
- 需要录制权限的恶意投射应用(用户通常不知道投射应用也能录制屏幕);
- 使用Cloak & Dagger攻击的看似无害的应用;
- 通过第三方安卓应用商店安装或绕过Play Store PHA检测过滤器的恶意应用;
- 在浏览器中间人攻击场景中通过Play Store功能推送至智能手机的恶意应用。
如果这些场景在现实中看似不太可能发生,值得注意的是近年来已发生多起滥用此类攻击的应用事件。
致谢
非常感谢1Password、Keeper和Dashlane安全团队以专业方式处理报告、提供奖励并允许披露。请记住,使用密码管理器仍是当前保护数字账户的最佳选择,且所有上述问题现已修复。
一如既往,此项研究得益于我在Doyensec的25%研究时间!