novaek/CVE-2026-0073-Research

GitHub: novaek/CVE-2026-0073-Research

针对CVE-2026-0073(Android ADB TLS认证绕过漏洞)的深度原理分析与PoC构造项目。

Stars: 5 | Forks: 1

# CVE-2026-0073 研究 CVE-2026-0073 是一个 CVSS 严重性评分为 8.3 的 RCE 漏洞,在这里我们将解释其工作原理。 ## 第一部分:代码分析: 首先,唯一可能引起兴趣的事情是进一步了解这个漏洞本身。 我的第一个信息来源是: 该信息来源告诉我们,`auth.cpp` 文件中显示了一个名为 `adbd_tls_verify_cert` 的函数,该函数存在一个逻辑缺陷,允许进行未经身份验证的 RCE。 现在的主要目标是获取 `auth.cpp` 的源代码。 由于我在任何官方仓库中都无法找到它,我找到了 Project-Awaken 在此链接提供的仓库: 这就是我们要找的神秘函数: ``` int adbd_tls_verify_cert(X509_STORE_CTX* ctx, std::string* auth_key) { if (!auth_required) { // Any key will do. LOG(INFO) << __func__ << ": auth not required"; return 1; } bool authorized = false; X509* cert = X509_STORE_CTX_get0_cert(ctx); if (cert == nullptr) { LOG(INFO) << "got null x509 certificate"; return 0; } bssl::UniquePtr evp_pkey(X509_get_pubkey(cert)); if (evp_pkey == nullptr) { LOG(INFO) << "got null evp_pkey from x509 certificate"; return 0; } IteratePublicKeys([&](std::string_view public_key) { // TODO: do we really have to support both ' ' and '\t'? std::vector split = android::base::Split(std::string(public_key), " \t"); uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1]; const std::string& pubkey = split[0]; if (b64_pton(pubkey.c_str(), keybuf, sizeof(keybuf)) != ANDROID_PUBKEY_ENCODED_SIZE) { LOG(ERROR) << "Invalid base64 key " << pubkey; return true; } RSA* key = nullptr; if (!android_pubkey_decode(keybuf, ANDROID_PUBKEY_ENCODED_SIZE, &key)) { LOG(ERROR) << "Failed to parse key " << pubkey; return true; } bool verified = false; bssl::UniquePtr known_evp(EVP_PKEY_new()); EVP_PKEY_set1_RSA(known_evp.get(), key); if (EVP_PKEY_cmp(known_evp.get(), evp_pkey.get())) { LOG(INFO) << "Matched auth_key=" << public_key; verified = true; } else { LOG(INFO) << "auth_key doesn't match [" << public_key << "]"; } RSA_free(key); if (verified) { *auth_key = public_key; authorized = true; return false; } return true; }); return authorized ? 1 : 0; } ``` 但该函数中最有趣的部分如下: ``` bool verified = false; bssl::UniquePtr known_evp(EVP_PKEY_new()); EVP_PKEY_set1_RSA(known_evp.get(), key); if (EVP_PKEY_cmp(known_evp.get(), evp_pkey.get())) { LOG(INFO) << "Matched auth_key=" << public_key; verified = true; } else { LOG(INFO) << "auth_key doesn't match [" << public_key << "]"; } ``` 为什么?因为 `verified` 被设置为一个用于允许或拒绝连接的布尔值,并且它只能通过 `if` 语句进行修改。问题在于?`EVP_PKEY_cmp(known_evp.get(), evp_pkey.get())` 并不总是返回 1 或 0,它还会返回 -1 和 -2。因为 `EVP_PKEY_cmp()` 在密钥匹配时返回 1,不匹配时返回 0,密钥类型不同时返回 -1,以及操作不受支持时返回 -2。 因此,即使密钥不匹配,它也会验证不同密钥的证书,或者在操作不受支持时验证通过。 为了验证我们的会话,我们必须强制触发这两个选项之一。 ## 第二部分:POC 制作及 ADB 连接协议逆向 为了尝试利用该漏洞,我们需要建立一个 TLS 会话。 只有当攻击者和目标设备都支持使用 TLS 时,此操作才能生效,然而是否使用 TLS 仅由目标设备决定。 如果目标设备允许 TLS,你就可以建立 TLS 会话。 整个过程如下: - 第一步:CNXN 数据包(连接数据包) - 第二步:STLS 数据包(升级到 TLS 数据包) - 第三步:TLS 握手(使用 EC 密钥代替 RSA) 让我们开始动手吧
标签:0day漏洞, ADB, adbd, Android安全, C++, CISA项目, CVE-2026-0073, CVSS 8.3, RCE, TLS证书验证, X509证书, 云资产清单, 安全测试工具, 底层编程, 情报收集, 数据擦除, 漏洞分析, 漏洞研究, 目录枚举, 移动安全, 编程工具, 网络安全, 路径探测, 身份验证绕过, 远程代码执行, 逆向工程, 隐私保护, 高危漏洞