| # | 判定 | 内容 |
|---|---|---|
| 1 | OK | CVE-2026-0073: System / adbd RCE |
CVE-2026-0073: System / adbd RCE
判定した脆弱性adbdのワイヤレスADB/TLSクライアント証明書検証で、未承認クライアントの証明書が承認済みADB鍵として扱われる認証バイパス。 成功するとADB接続が確立し、shell userとしてコード実行可能になる。 根本原因
特定根拠
validated.md を表示# CVE-2026-0073 System / adbd RCE 検証メモ
## 結論
特定できた。CVE-2026-0073 は adbd の TLS クライアント証明書検証で、`EVP_PKEY_cmp()` の戻り値を真偽値として扱ったため、比較エラーを「公開鍵一致」と誤認する認証バイパスである。
このバイパスにより、ワイヤレスADB/TLS接続で未承認クライアントが既存の承認済みADB公開鍵として扱われ、adbd の shell 権限でADB接続を確立できる。Android Security Bulletin の分類は System / RCE / Critical / remote proximal-adjacent code execution as shell user。
## 参照情報
- Android Security Bulletin May 2026: https://source.android.com/docs/security/bulletin/2026/2026-05-01
- Pixel Update Bulletin May 2026: https://source.android.com/docs/security/bulletin/pixel/2026/2026-05-01
- AOSP修正コミット: https://android.googlesource.com/platform/packages/modules/adb/+/842d331f9e5fb10770a09379e19240daea057dba
- 修正コミット: `842d331f9e5fb10770a09379e19240daea057dba`
- 親コミット: `1a4091e7b8d980ee3a7f7d9cdb00285a69d88639`
- Bug ID: `A-469080888`
- 変更ファイル: `daemon/auth.cpp`
- 付帯ファイル: `artifacts/`
## パッチ差分
変更は `adbd_tls_verify_cert()` 内の1箇所。
脆弱版:
```cpp
if (EVP_PKEY_cmp(known_evp.get(), evp_pkey.get())) {
VLOG(AUTH) << "Matched auth_key=" << public_key;
verified = true;
}
```
修正版:
```cpp
int cmp_result = EVP_PKEY_cmp(known_evp.get(), evp_pkey.get());
if (cmp_result == 1) {
VLOG(AUTH) << "Matched auth_key=" << public_key;
verified = true;
}
```
`artifacts/patch.diff` に公式Gitilesから取得した差分を保存した。
## 根本原因
根本原因は OpenSSL/BoringSSL API の戻り値契約の取り違え。
Android側BoringSSLヘッダでは `EVP_PKEY_cmp()` は次の契約になっている。
- `1`: 公開鍵が等しい
- `0`: 公開鍵が等しくない
- 負数: エラー
実装でも、鍵タイプが違う場合は `-1`、比較処理が存在しない場合は `-2` を返す。保存した証拠は `artifacts/boringssl_evp_pkey_cmp_header.txt` と `artifacts/boringssl_evp_pkey_cmp_impl.txt`。
しかし脆弱版adbdは `if (EVP_PKEY_cmp(...))` と書いていたため、`-1` や `-2` もC/C++の真として扱い、`verified = true` に到達する。
## 攻撃が成立する状況
成立条件は次の通り。
1. デバイス側adbdでADB認証が必要である。
2. デバイスに少なくとも1つ承認済みADB公開鍵が保存されている。
3. 攻撃者がワイヤレスADB/TLS接続の到達範囲にいる。
4. 攻撃者が、保存済みADB公開鍵と同一ではないが、`EVP_PKEY_cmp()` が負数エラーを返す公開鍵を入れたクライアント証明書を提示する。
特に分かりやすいケースは、登録済みADB鍵がAndroidの通常形式どおりRSAで、攻撃者のTLSクライアント証明書がEC/Ed25519などRSA以外の公開鍵を持つ場合。`adbd_tls_verify_cert()` は登録済み公開鍵を `android_pubkey_decode()` でRSAとして読み、`EVP_PKEY_set1_RSA()` で `known_evp` を作る。一方、TLS証明書から得た `evp_pkey` が別タイプなら、BoringSSLの `EVP_PKEY_cmp()` は `a->type != b->type` で `-1` を返す。脆弱版ではこの `-1` が成功扱いになる。
`transport.cpp` ではサーバ側adbdが `SetCertVerifyCallback()` に `adbd_tls_verify_cert()` を登録し、TLSハンドシェイク成功時に接続を継続する。つまりこの誤判定は単なるログ上の問題ではなく、TLSクライアント認証の許可判定に直結する。
## 影響
未承認の近接/隣接ネットワーク攻撃者が、ユーザー承認済みADB鍵を持っていなくても、adbdにTLSクライアント証明書を承認済みと誤認させられる。成功するとADB接続が確立し、Androidブリテン記載どおり shell user としてコード実行可能になる。
この問題は旧来の `A_AUTH` トークン署名検証経路ではなく、ワイヤレスADBのTLS証明書検証経路にある。`adbd_auth_verify()` の `RSA_verify(...) == 1` は明示比較になっており、今回の直接原因ではない。
## 修正の意味
修正は `EVP_PKEY_cmp()` の戻り値を `cmp_result == 1` に限定し、負数エラーを失敗扱いにするもの。ログにも戻り値が出るようになったため、将来同種の比較不能ケースを追跡しやすくなっている。
## Pixelについて
Pixel Update Bulletin May 2026 には、このCVEに対応する追加のPixel固有行はなかった。Googleデバイスは May 2026 Android Security Bulletin の修正を含むため影響を受けるが、今回の原因はAOSP `platform/packages/modules/adb` の公開ソースで完全に説明できる。したがってPixelファームウェアのバイナリ取得や `../binaries` への保存は不要と判断した。
## 調査時のメモ
- コミットメッセージは `Fix EVP_PKEY_cmp usage.` で、`Bug: 469080888` と `CVE_FIX` を含む。ブリテンの `A-469080888` と対応する。
- 公開ドキュメントの一部では `EVP_PKEY_cmp()` を「一致なら1、不一致なら0」と簡略に説明しているものがあるが、Androidの実際のBoringSSLヘッダと実装では負数エラーが存在する。今回のバグはまさにその負数を見落としたもの。
- 登録済みADB公開鍵がない場合は `IteratePublicKeys()` のループが成立しないため、このバグだけでは承認済み鍵を捏造できない。
- RSA同士で単に別鍵を提示した場合は通常 `pub_cmp` が `0` を返すため、このパッチ差分から読める主な悪用形は「鍵タイプ不一致」または「比較不能鍵」による負数戻り値の成功扱いである。
## 保存した付帯ファイル
- `artifacts/patch.diff`: 公式修正コミットの差分
- `artifacts/auth_before.cpp`: 親コミットの `daemon/auth.cpp`
- `artifacts/auth_after.cpp`: 修正コミットの `daemon/auth.cpp`
- `artifacts/adbd_tls_verify_cert_before.txt`: 脆弱版の該当関数抜粋
- `artifacts/adbd_tls_verify_cert_after.txt`: 修正版の該当関数抜粋
- `artifacts/boringssl_evp_pkey_cmp_header.txt`: Android BoringSSLヘッダの戻り値契約
- `artifacts/boringssl_evp_pkey_cmp_impl.txt`: Android BoringSSL実装の `-1` / `-2` 戻り値
- `artifacts/transport_tls_callback_after.txt`: adbd TLSハンドシェイクで検証コールバックを登録する箇所
| ||
該当する項目がありません