Signal 安卓客户端 0 点击漏洞深度解析:一条音频消息如何接管你的手机
引言:当安全通讯不再安全
2026 年 1 月 28 日,Hunters Security 研究团队披露了一项针对 Signal 安卓客户端的重磅安全发现。这款被全球隐私倡导者推崇为最安全通讯工具的应用,被发现存在一个无需用户任何交互即可触发远程代码执行的漏洞。
想象一下,你收到了一条看似普通的消息,没有点击任何链接,没有打开任何文件,但你的手机已经在后台被完全控制。这就是 0 点击漏洞的可怕之处。
什么是 0 点击漏洞
0 点击漏洞是指攻击者无需受害者进行任何操作即可成功利用的安全漏洞。这类漏洞之所以危险,是因为用户完全无法察觉攻击的发生。传统的网络攻击通常需要用户点击恶意链接、下载并打开附件,或者执行某些操作。而 0 点击攻击则完全不同,它可以在用户毫无察觉的情况下完成入侵。
Signal 作为端到端加密的标杆产品,其安全性一直备受信赖。然而,正是这种信赖可能成为攻击者的突破口。
漏洞技术原理
自动媒体处理管道
这个漏洞的核心在于 Signal 安卓客户端的自动媒体处理机制。当用户收到包含音频附件的消息时,应用会执行以下操作:
第一步,应用通过 WebSocket 连接接收消息通知,这个过程在后台静默进行。
第二步,DataMessageProcessor 组件将消息和附件元数据存入本地数据库。
第三步,AttachmentDownloadJob 自动启动,在后台下载加密的音频附件。
第四步,也是最关键的一步,当下载完成后,AttachmentTable.kt 中的 finalizeAttachmentAfterDownload 方法会检查文件的 MIME 类型:
// AttachmentTable.ktif (MediaUtil.isAudio(existingPlaceholder)) { GenerateAudioWaveFormJob.enqueue(existingPlaceholder.attachmentId)}
如果识别为音频文件,系统会自动将波形生成任务加入后台处理队列。
原生媒体栈的危险交互
问题出在下一步。GenerateAudioWaveFormJob 执行时会调用 AudioWaveFormGenerator,这个组件使用 Android 原生媒体框架的 MediaExtractor 和 MediaCodec 来处理音频文件:
// AudioWaveFormGenerator.javapublicstatic@NonNullAudioFileInfo generateWaveForm( @NonNull Context context, @NonNull Uri uri)throws IOException {try (MediaInput dataSource = DecryptableUriMediaInput.createForUri(context, uri)) {// 创建原生提取器 - 第一个危险点 MediaExtractor extractor = dataSource.createExtractor();// 创建原生编解码器 - 第二个危险点 MediaCodec codec = MediaCodec.createDecoderByType(mime); codec.configure(format, null, null, 0); codec.start(); }}
这里的关键问题在于,来自发送方的未经验证的二进制数据被直接传递给了系统级的媒体处理组件。如果攻击者精心构造一个畸形的音频文件,利用 Android 媒体框架中的漏洞,就可能触发内存破坏问题。
攻击链完整流程
攻击者首先识别 Android 媒体编解码器中的已知或零日漏洞,比如 MP4 容器解析中的堆溢出问题。
然后,攻击者构造一个特殊的畸形文件,这个文件在正常播放器中可能无法播放,但能够触发特定的内存破坏。
接下来,攻击者通过 Signal 发送这个恶意文件给目标用户。
当受害者的 Signal 应用收到消息后,会在后台自动下载并尝试生成波形图,这个过程完全不需要用户参与。
最后,Android 媒体进程崩溃或执行攻击者的代码,而用户甚至不知道这条消息的存在。
隐蔽的攻击载体
直接音频附件
最直接的攻击方式就是发送一个恶意音频文件。攻击者可以将文件命名为看似正常的内容,比如语音消息或音乐文件。Signal 收到后会自动处理,触发漏洞。
链接预览伪装
更隐蔽的攻击方式是利用链接预览机制。攻击者发送一条包含普通链接的消息,比如指向知名网站的 URL,但在 Protobuf 负载中构造一个特殊的预览对象。
这个预览对象的 image 字段实际上指向恶意音频文件,但 contentType 被设置为 audio/mpeg。Signal 会验证 URL 的安全性,但会信任发送方提供的附件元数据。
于是,所谓的预览图片实际上是音频文件,下载完成后被识别为音频类型,触发波形生成任务。这种攻击方式将远程代码执行隐藏在看似无害的文本消息背后,极难被发现。
代码层面的脆弱点分析
脆弱点一:无条件的任务入队
在 AttachmentTable.kt 中,finalizeAttachmentAfterDownload 方法在检测到音频文件后无条件地调用 GenerateAudioWaveFormJob.enqueue。这里没有任何额外的验证或延迟处理机制。
if (MediaUtil.isAudio(existingPlaceholder)) { GenerateAudioWaveFormJob.enqueue(existingPlaceholder.attachmentId)}
这个设计假设所有音频文件都是安全的,但事实上,发送方完全控制着附件内容。
脆弱点二:原生媒体库的信任
AudioWaveFormGenerator 直接使用 MediaExtractor 和 MediaCodec 处理文件。这些原生库用 C/C++ 编写,历史上曾多次出现严重漏洞,包括著名的 Stagefright 漏洞。
MediaExtractor extractor = dataSource.createExtractor();MediaCodec codec = MediaCodec.createDecoderByType(mime);
将未经验证的用户输入直接传递给这些底层组件,相当于将大门敞开。
脆弱点三:后台静默执行
整个处理流程都在后台 Job 中执行,用户界面没有任何提示。这意味着即使处理过程中出现异常,用户也不会察觉。
修复建议
延迟处理策略
最根本的修复方案是移除自动入队的逻辑。波形生成不应该在消息接收时立即执行,而应该推迟到用户明确尝试播放音频或打开对话时。
// 移除这段代码// if (MediaUtil.isAudio(existingPlaceholder)) {// GenerateAudioWaveFormJob.enqueue(existingPlaceholder.attachmentId)// }
将波形生成逻辑移动到用户点击播放按钮时执行,这样可以将攻击面从自动触发改为需要用户交互。
沙箱隔离
如果必须进行后台处理,可以考虑在隔离的、低权限的进程中执行媒体解析。虽然 Android 的媒体服务器已经有一定程度的隔离,但其中的漏洞仍然可能危及设备安全。
文件头验证
在将文件传递给原生编解码器之前,使用纯 Java 或 Kotlin 编写的解析器验证文件头与声明的 MIME 类型是否匹配。这样可以过滤掉一部分明显的恶意文件。
链接预览加固
对于与链接预览关联的附件,应该强制要求必须是图片类型,并进行严格验证。预览功能不应该成为音频或其他媒体类型的传输通道。
历史背景与影响
Stagefright 漏洞的阴影
2015 年,Android 的 Stagefright 媒体处理库被曝出多个严重漏洞,影响数十亿设备。攻击者可以通过发送特制的 MMS 消息远程执行代码。这次 Signal 漏洞的发现,让人不禁想起那段历史。
隐私工具的安全悖论
Signal 作为隐私保护的代表产品,其用户群体包括记者、活动人士、政府官员等高风险人群。这类用户对通讯安全的需求最高,但一旦底层平台出现漏洞,他们面临的风险也最大。
开源安全研究的价值
这次研究由 Hunters Security 团队使用 WormGPT 辅助完成,体现了 AI 在安全研究领域的应用。开源代码使得独立安全研究人员能够深入分析潜在问题,这正是开源软件安全性的体现。
用户防护建议
虽然这个漏洞的修复需要应用开发者的行动,但用户也可以采取一些防护措施。
保持系统和应用更新是基本要求。Google 和 Signal 团队都会定期发布安全补丁。
对于高风险用户,可以考虑在敏感对话中禁用自动媒体下载功能,手动选择是否下载附件。
提高安全意识,对来源不明的消息保持警惕,即使是来自已知联系人。
结语:安全是持续的过程
这次 Signal 漏洞的发现再次提醒我们,安全不是一劳永逸的状态,而是一个持续改进的过程。即使是设计最严谨的系统,也可能存在意想不到的攻击面。
对于普通用户来说,了解这些风险有助于提高安全意识。对于开发者来说,这个案例提供了宝贵的经验教训:自动处理用户输入时必须格外谨慎,尤其是当涉及到底层系统组件时。
在数字安全的世界里,没有绝对的安全,只有不断演进的攻防对抗。
参考资料
https://github.com/hunters-sec/signal_research
标签