ChatGPT 安卓端订阅机制缺陷分析
ChatGPT 安卓端订阅机制缺陷分析,从 API 注入到内存替换的零元订阅攻击路径。
本文技术分析基于公开的安全研究资料整理,所述内容仅供安全研究与技术交流。
一、漏洞概述#
OpenAI 旗下 ChatGPT 安卓客户端在处理订阅支付流程时存在关键的业务逻辑缺陷。核心问题在于,服务端与 RevenueCat 支付平台未对客户端传入的订阅凭证进行有效的二次验证,导致攻击者可以通过本地篡改手段绕过付费门槛,以零成本获取 Plus/Pro 会员权益。
该问题并非传统意义上的客户端破解,而是一种因信任边界设计不当引发的逻辑漏洞。Google Play Billing 的支付回调数据被服务端过度信任,且优惠资格校验未在服务端侧进行强约束。
二、攻击路径一:API 响应注入#
2.1 技术原理#
ChatGPT 安卓应用在启动阶段会向以下接口发起请求以获取当前用户的账户状态:
GET https://android.chat.openai.com/backend-api/accounts/check/v4-2023-04-27
该接口返回的 JSON 数据中包含 eligible_promo_campaigns 字段,用于描述当前账户可参与的优惠活动。正常情况下,该字段内容由服务端根据账户实际资格动态生成。
攻击者通过在客户端与服务器之间建立中间人(MITM)代理,拦截上述响应数据包,并向 eligible_promo_campaigns 字段中强行注入预设的优惠码结构,使客户端误认为当前账户具备免费试用资格。
2.2 注入载荷示例#
以下为注入 1 个月免费试用优惠的响应片段:
{
"eligible_promo_campaigns": {
"plus": {
"id": "plus-1-month-free",
"metadata": {
"discount": { "percentage": 100 },
"duration": { "num_periods": 1, "period": "month" },
"no_auto_renewal_at_discount_end": true
}
}
}
}
其中 discount.percentage: 100 表示完全免单,no_auto_renewal_at_discount_end: true 表示优惠周期结束后不自动扣费续订。
2.3 可用优惠码#
根据公开资料,以下固定优惠码可被注入并生效:
| 优惠码 | 效果 |
|---|---|
3-day-free-trial | 3 天免费试用 |
plus-1-month-free-trial | 1 个月免费试用 |
1-month-10-dollars | 半价优惠(首月 $5) |
pro-winback-1-month-free | Pro 挽回试用 1 个月(特定资格) |
此外还存在限时优惠码如 2wqkodfx51z2x(6 个月免费)和 2ispxs5mtgz35(12 个月免费),这些优惠码的持续可用性是卡商批量生成低价会员的根本原因。
2.4 验卡绕过#
由于最终生成的订单金额为零,Google Play 的风控系统对该类交易仅执行基础验卡流程。攻击者只需绑定一张有效的支付卡(不实际扣款)即可通过验证。
三、攻击路径二:offerToken 内存替换#
3.1 技术原理#
该路径直接作用于 Google Play Billing 的计费数据流。ChatGPT 客户端在发起订阅请求时,会将当前 SKU 对应的 offerToken 参数传递给 Google Play。攻击者利用 Frida 动态插桩框架,在内存中定位并替换该 offerToken 为目标免费试用档位对应的 token,从而欺骗 Google Play 以零元处理该笔订阅。
3.2 反篡改绕过#
ChatGPT 集成了 Appdome 反篡改 SDK,其核心模块 libpairipcore.so 会在运行时检测注入行为并强制退出。绕过方法是在注入后立即将该模块的所有可执行代码段用 0xC3(x86/x64 架构中的 RET 指令)填充,使所有检测函数直接返回而失效。
3.3 四步攻击流程#
第一步:捕获免费试用 offerToken
通过 Frida 的 Java.choose 接口遍历内存中名为 c3q 的混淆计费类实例,利用反射读取其私有字段 b(对应 offerId)与 c(对应 offerToken)。当识别到目标免费试用档位的 offerId 时,缓存其对应的 offerToken。
第二步:Hook 系统框架方法
对 Android 框架层的三个关键方法进行 Hook:
android.content.Intent.putExtra(String, String)android.os.Bundle.putString(String, String)android.os.Bundle.putStringArrayList(String, ArrayList)
这些方法在 Google Play Billing 构建购买 Intent 时被调用,是 offerToken 传入的关键通道。
第三步:实时替换
在 ChatGPT 发起订阅请求的瞬间,Hook 代码拦截到即将写入的原始付费档位 offerToken,并将其替换为已缓存的免费试用 token。
第四步:完成订阅
被篡改后的购买请求被 Google Play 以“免费试用成功”处理,支付成功后返回有效回执,RevenueCat 同步激活会员权益。
3.4 订阅套餐 offerId 对照表#
| offerId | 优惠内容 |
|---|---|
2ispxs5mtgz35 | 免费 1 年 |
2wqkodfx51z2x | 免费 6 个月 |
plus-1-month-free-trial | 免费 1 个月 |
3-day-free-trial | 免费 3 天 |
1-month-10-dollars | 首月 $10 |
四、漏洞根源与影响分析#
4.1 信任边界问题#
RevenueCat 的支付回调数据由客户端上报,服务端未与 Google Play 官方接口进行二次核对。攻击者可以完全绕过服务端的资格校验逻辑,在本地构造任意优惠凭证并成功获得会员权益。
4.2 凭证未绑定#
订阅凭证(fetch_token、offerToken)未与账号 ID、设备指纹或支付账户进行强绑定。攻击者完成一次零元订阅后,可提取 fetch_token 并用于为其他账号批量开通会员。
4.3 客户端防护缺失#
ChatGPT 客户端未实现 SSL Pinning,使得中间人攻击成为可能;同时反 Hook 与反调试机制薄弱,libpairipcore.so 的检测逻辑可被简单绕过。
4.4 影响范围#
该漏洞已在实际环境中被广泛利用,卡商通过自动化脚本批量生成低价 Plus 会员,在灰色市场上以远低于官方的价格出售。由于服务端修复涉及架构调整,该问题在一段时间内持续有效。
五、防御与加固建议#
5.1 服务端侧#
- 强制二次验证:所有订阅状态变更必须由服务端主动调用 Google Play Developer API 进行核实,而非仅依赖客户端上报数据。
- 凭证绑定与一次性消费:将订阅凭证与账号 ID、设备指纹、支付账户绑定,并在首次激活后标记为已消费,防止跨账号复用。
- 异常监控:对同一优惠码的高频使用、同一收据的多账号激活等异常模式进行实时告警。
5.2 客户端侧#
- 启用 SSL Pinning:防止中间人攻击篡改 API 响应。
- 强化反篡改机制:对注入检测、调试检测、Hook 检测进行多层加固,增加绕过成本。
- 启用 Trusted Entitlements:RevenueCat 官方提供了该功能,通过对 entitlements 响应进行签名校验来防止中间人篡改。
风险提示:利用上述技术手段绕过付费机制的行为严重违反 OpenAI 服务条款及《中华人民共和国网络安全法》等相关法律法规,可能导致账号永久封禁,甚至面临民事或刑事责任。本文仅从技术防御角度对漏洞成因与攻击路径进行剖析,旨在帮助开发者提升支付安全水位,严禁用于任何非法用途。
Comments
评论
欢迎留下你的看法,也欢迎补充不同视角。