一条看不见的短信,不用点击,甚至不会在收件箱里留下一丝痕迹,就能让一台 Android 手机当场断网、挂断正在拨打的紧急求助电话。安全研究员 Mark Blaszczyk 在 2026 年 5 月 5 日向 Google 提交了这个名为 SMS of Death 的远程零点击漏洞,并附上了仅需 1 行逻辑的修复补丁。历时近半年、经过 3 个工单和 4 名工程师评估后,Google 在 2026 年 10 月 29 日给出了最终裁定:这不是安全问题,不予修复(Won't Fix)。
漏洞的触发机制简单得像教科书里的低级错误。Android 电话框架在通过 WapPushOverSms 组件解析 2948 端口发来的 WAP Push 数据短信时,会把协议头长度先读成一个长整型(long),随后在没有任何边界检查的情况下,直接强制转换成 32 位有符号整型(int)去分配字节数组。攻击者只要构造一段 5 字节的畸形数据(88 80 80 80 00),解码出的长度就会变成负数 -2147483648。系统试图创建一个长度为负数的数组,主线程当场抛出未捕获的 NegativeArraySizeException 异常,直接杀死负责蜂窝通信的 com.android.phone 特权进程。
2秒闪断为什么会变成无限死循环
单发一条畸形短信,手机通信模块只会崩溃重启 1 到 2 秒。但因为手机在崩溃瞬间没来得及向基站返回接收确认(ACK),运营商会把这条短信当成投递失败,在后台反复重发。测试中仅发了一条短信,就导致目标手机在长达一周的时间里间歇性断网。如果攻击者连续快速发送 20 到 30 条,手机开机就会立刻崩溃,连恢复出厂设置都救不回来。
关于手机为什么会彻底变砖,研究员与底层源码审计给出了两种截然不同的解释:
- SQLite 数据库竞争损坏说:研究员认为,连续 30 条短信引发的高频崩溃,会打断电话服务向本地数据库写入短信的过程,触发竞争条件并物理损坏 SQLite 数据库;此后系统每次开机读取受损数据库都会崩溃。
- 状态机未确认重放说.如果顺着 AOSP 源码里的
InboundSmsHandler机制往下看,这更像是一场由可靠性设计引发的逻辑死锁——短信在触发解析崩溃前就已经落盘存入了原料数据库,但状态还没来得及标记为已处理;系统每次重启后,InboundSmsHandler都会忠实地把数据库里未确认的畸形短信重新捞出来再解析一遍,从而形成无限崩溃循环。
不论底层是物理损坏还是逻辑重放,普通用户面对的现实代价完全一致。因为运营商队列里还憋着未确认的毒丸短信,单纯格式化手机毫无意义,开机连上网就会再次中招。唯一的自救办法是拔出实体 SIM 卡,插进一台 iPhone 等非 Android 设备里,借用其他系统的短信栈把运营商队列里的重发消息消化并确认掉,再用电脑通过 ADB 命令清空 Android 手机里的残留数据。如果受害者用的是无法物理拔卡的 eSIM 手机,普通人基本只能眼睁睁看着手机沦为一台没有通信功能的砖头。
1行代码能修好的洞,Google 为什么死活不认
整件事最反常的地方,是修复成本与破坏后果的极度不对等。研究员在提交漏洞当天就给出了修补方案,只需要在 WapPushOverSms.java 的第 217 行前加一行范围判断:如果读出来的长度小于 0 或者大于数据包的实际长度,直接返回通用错误即可。但在当前 AOSP 主线源码里,这段裸奔的类型转换依然原封不动。
我不太买账的是 Google 拿着僵化的漏洞分级教条当挡箭牌。在传统操作系统安全团队的计分板里,C/C++ 层面的缓冲区溢出、能偷数据的远程代码执行(RCE)才叫高危安全漏洞;而 Java 层抓到一个未处理异常导致进程重启,往往被归类为普通的功能稳定性缺陷(Bug),算不上安全问题。
拿实验室里的内存教条去丈量生死攸关的通信基建,是大型科技公司最冷血的官僚主义。
但 com.android.phone 不是一个普通的计算器应用,它是整台手机唯一与基站对话的咽喉要道。把这起拒绝修复放到现实监管环境里看,会引出一个荒诞的连锁反应。以澳大利亚 2024 年收紧的《电信(紧急呼叫服务)决定》为例,监管机构要求运营商必须识别出无法拨打 000 紧急电话的手机,并在通知用户 28 天后将其强制断网封禁。这套法规原本是为了清理 3G 退网后留下的老旧设备,如今却成了攻击者的免费放大器:既然监管对打不通急救电话的手机采取的救济手段是踢出网络,而不是给系统打补丁,那么攻击者只要用几十条短信把你的 Android 手机打进死循环,就能借运营商的手,合法地把你的手机彻底封杀出局。
历史遗产里的幽灵与现代系统的软肋
把视角再拉远一点,这次闯祸的 WAP Push 其实是功能机时代的活化石。二十多年前移动互联网刚起步时,为了把彩信通知或后台服务链接推送到性能孱弱的手机上,行业设计了这套紧凑的二进制短信协议。今天绝大多数普通用户根本用不到它,但为了向下兼容全球数百家运营商的陈旧计费与配置网关,Android 依然在特权极高的电话进程里保留着这套年久失修的解析器。
《韩非子》里讲,千丈之堤,以蝼蚁之穴溃。软件工程里的历史技术债也是如此。类似的一幕在 2015 年 Android 的 Stagefright 彩信漏洞上就演过一回,区别在于当年是 C++ 媒体库引发了内存破坏,Google 不得不连夜修补;而今天碰到 Java 层的逻辑崩溃,哪怕同样是通过旧时代协议实现零点击远程打击,Google 却选择了装聋作哑。系统大厂的算盘打得很精:去动底层遗留电话框架的代码,哪怕只改一行,都可能触发全球某个角落古董运营商网关的兼容性故障;相比之下,把安全研究员的报告摁死在“非安全问题”的分类里,显然省事得多。
- 风险.目前攻击验证代码(PoC)与编译好的 APK 已经完全公开,而搭载 2026 年 4 月固件的 Pixel 9 及多款三星 Galaxy 机型实测复现率高达 100%;在 Google 松口下发月度安全补丁之前,唯一の防线只能寄望于电信运营商在骨干网短信中心(SMSC)层面紧急拦截畸形的 2948 端口数据短信。
那段只有 5 字节的 88 80 80 80 00 就像一面照妖镜,照出了现代智能手机金玉其外的尴尬:上层塞满了动辄百亿参数的端侧大模型,底层却还能被二十年前的遗留协议用一行负数转换轻易击穿。当一家掌控全球最大移动操作系统的公司,认为远程掐断一个人的救命电话“达不到安全严重性门槛”时,真正崩溃的其实不是手机里的电话进程,而是安全承诺的底线。
