Google Play提示Intent重定向漏洞:实现一键OTP验证后仍触发告警
安卓一键同意式OTP验证码Intent重定向漏洞问题解决
问题根因
你收到Intent重定向漏洞告警的核心原因是动态注册的广播接收器未添加权限校验,Manifest中配置的权限仅对静态注册的广播生效,无法防护动态注册的接收器。具体配置错误如下:
- 依赖版本混淆:你混淆了Google Play服务运行时版本和客户端依赖库版本。
SmsRetriever.SEND_PERMISSION对应的客户端依赖是play-services-auth-api-phone:18.0.0及以上,和play-services-auth的版本无关,你当前使用的17.5.1版本的auth-api-phone不存在带权限参数的registerReceiver重载,才会出现类型不匹配错误。 - 动态注册无防护:你代码中动态注册的
smsBroadcastReceiver未指定权限,任意三方应用都可以向该接收器发送伪造的SMS_RETRIEVED_ACTION广播,直接触发漏洞告警。 - 重复注册冗余:你同时使用静态+动态两种方式注册广播接收器,属于冗余配置,还会导致同一条验证码触发两次回调,增加业务逻辑出错概率。
解决方案
1. 升级依赖版本
将build.gradle中的auth-api-phone依赖升级到18.0.0及以上:
implementation 'com.google.android.gms:play-services-auth-api-phone:18.0.0'
2. 修正广播注册逻辑
二选一即可,不要同时使用两种注册方式:
方案A:保留动态注册(官方推荐)
完全删除Manifest中的<receiver>静态注册配置,动态注册时添加权限参数:
override fun onCreate(savedInstanceState: Bundle?) { // ... val intentFilter = IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION) registerReceiver(smsVerificationReceiver, SmsRetriever.SEND_PERMISSION, intentFilter) }
记得在onDestroy中注销动态注册的广播,避免内存泄漏:
override fun onDestroy() { super.onDestroy() unregisterReceiver(smsVerificationReceiver) }
方案B:保留静态注册
完全删除代码中的动态注册逻辑,仅保留Manifest中的静态注册配置即可。
3. 添加额外安全校验
在广播接收器的onReceive回调中增加多层校验,不要直接信任所有传入的Intent数据:
override fun onReceive(context: Context?, intent: Intent?) { // 先校验Action是否合法 if (intent?.action != SmsRetriever.SMS_RETRIEVED_ACTION) return val extras = intent.extras ?: return val status = extras.get(SmsRetriever.EXTRA_STATUS) as Status // 校验返回状态是否为成功 if (status.statusCode != CommonStatusCodes.SUCCESS) return // 再提取验证码内容做后续处理 val message = extras.getString(SmsRetriever.EXTRA_SMS_MESSAGE) ?: return // 业务逻辑处理 }
注意事项
- 不要使用18.0.0以下版本的auth-api-phone依赖,低版本本身存在已知的安全漏洞。
- 提交审核前可以构造伪造的
SMS_RETRIEVED_ACTION广播主动测试,验证接收器是否会响应非官方发送的广播。 - 广播接收器中不要处理其他未声明的Action,避免被恶意Intent利用。
内容的提问来源于stack exchange,提问作者Prasenjit
相关产品推荐
相关产品推荐

