SafetyNet はパスできてるのに Google Pay の非接触決済が使えなくなった件
7 月 21 日、僕のスマホで Google Pay が使えなくなった。朝コンビニで使用して、昼頃に非接触決済が使えなくなった事をお知らせする通知を受け取り、それ以降どんなに頑張っても非接触決済を使えるよう設定することができなくなってしまった。
僕のスマホの状態
- OnePlus 9 (Android 12 / Oxygen OS 12 C.61)
- セキュリティパッチ : 5 月 5 日
- Play システムアップデート : 6 月 1 日
- Magisk 25.2 でルート化済
- SafetyNet は Universal SafetyNet Fix を導入してパスできている (
evalutionType
はBASIC
のみ) - DenyList は使用せず Shamiko でルート化隠蔽
21 日の 5 時頃に、Google Pay から Google Wallet にリニューアルされたことに気づいたが、日本での展開はまだらしく、中身はただの Google Pay だった。ちょうど非接触決済が使えなくなったのと Google Wallet へのリニューアルが重なったので何かしらの関連性があると疑ったが、Google Pay のバージョンを差し戻しても非接触決済が使えるようにはならなかったので、アプリバージョンは関係ないと推測する。
New Google Wallet update breaks universal safetyet fix · Issue #203 · kdrag0n/safetynet-fix
Universal SafetyNet Fix の Issues にてこの件について議論が行われている。
とりあえず分かっていること
Google Wallet (Google Pay) で非接触決済が使えなくなった人に共通することがある。それは「従来の SafetyNet はパスできているのに使えない」ということだ。どうやら SafetyNet とは別に Play Integrity という仕組みがあるらしく、デバイスが改ざんされていないかどうかチェックする新しい API が存在するようだ。Google は SafetyNet を廃止し、この新しい API に移行することをアナウンスしている。
また、この変更は段階的に行われているらしく、人によってこうなるタイミングが異なるようだ。
なぜ非接触決済が使えなくなったのか、の技術的な説明は最後の節で行う。
現時点での解決方法
非接触決済が弾かれるのはどうやら Android 12 のみ (現時点では) らしいので、デバイスの fingerprint を同機種の Android 11 のときの fingerprint に変更すれば、SafetyNet をパスしたまま Google Pay での非接触決済が可能になる。fingerprint の変更は自己責任で。
実際にやってみた。MagiskHide Props Config にて OnePlus 9 の Android 11 の fingerprint に書き換えた後、関連するアプリのデータを消去してみた。
しばらくすると非接触決済対応のクレジットカードを Google Pay に追加できるようになった。
ただ、Android 11 以下でも仕様変更が起こらないとも限らないので、その場しのぎの対策に近い。どこかの天才ハカーがなんとかしてくれるのを祈るばかりだ……。ひ、非接触決済の為だけのスマホとか持ち歩きたくないよ……。
追記 : 有志による Universal SafetyNet Fix の対応版が登場
Displax 氏による、Play Integrity をバイパスする Universal SafetyNet Fix の修正版が配布されている。Google Mobile Services にのみ fingerprint の変更が行われるので、MagiskHide Props Config で端末の fingerprint を変えるより影響が少ない1そもそも fingerprint を見るアプリが少ないといえばそれまでだが。。図らずも MagiskHide の廃止と同時に登場した Zygisk に救われるという。
僕の環境では、こちらのモジュールで問題なく動作する。これからどうなるかわからないけど、ありがとう天才ハカー!
追記 (2) : 新たに登場した Play Integrity について
現状、Play Integrity は SafetyNet とほぼ同じことをしている。
Play Integrity のデバイス完全性のレスポンスは以下の 0 つ以上の値を返す。
MEETS_DEVICE_INTEGRITY
MEETS_BASIC_INTEGRITY
MEETS_STRONG_INTEGRITY
MEETS_VIRTUAL_INTEGRITY
端的に言うと、健全な端末 (= とくに何もしていない端末) だと MEETS_STRONG_INTEGRITY
, MEETS_BASIC_INTEGRITY
, MEETS_DEVICE_INTEGRITY
という 3 つの値が返される。
ルート化すると、0 つの値が返される (デバイス完全性を満たせていない) が、Universal SafetyNet Fix を導入すると MEETS_BASIC_INTEGRITY
, MEETS_DEVICE_INTEGRITY
という 2 つの値が返されるようになる状態まで持って行ける。この状態が、SafetyNet でいう ctsProfileMatch
と basicIntegrity
が true
でかつ evaluationType
が BASIC
の時と同義になる。MEETS_STRONG_INTEGRITY
を得るには evaluationType
が HARDWARE_BACKED
である必要性がある。
また、このデバイス完全性チェックはアプリ上だけでなく、Google Play のアプリをどのくらいの範囲に公開するかの判断基準としても使われていて、デベロッパー側が自由に設定できる。
7 月 21 日以降、Google Wallet (Google Pay) の非接触決済は MEETS_STRONG_INTEGRITY
を要求するようになった。つまり Universal SafetyNet Fix を導入した状態であっても、ルート化している時点で非接触決済は使えない。
では何故 fingerprint を変更すると非接触決済が使えるようになるのか? 現時点においては、Google Play において、Android 12 のみ、Play Integrity を使用している挙動になっているからだと推測する。Google Play サービス内にて SafetyNet と Play Integrity が抽象化されていて、”今は” Android 12 のみ Play Integrity を使用している、という仕組みになっているのだろう。
この Android 11 以下はセーフ、がいつまでなのかは分からない、数日後には Android 11 もこうなってしまうかもしれない。少なくとも SafetyNet が廃止されるのは確定なので、fingerprint を変更する手法はいずれ使えなくなる。
ちなみに、MEETS_DEVICE_INTEGRITY
以外の値に関しては、Play ストアにアプリが公開されている、かつ、オプトインしなければ取得できないような仕組みなっている。Universal SafetyNet Fix の Issue で公開された Play Integrity を検証するアプリは、ストアに公開されてないので、MEETS_DEVICE_INTEGRITY
が取得できるかどうかしか分からない。故に非接触決済が使えるかどうかの指標にはならない。Netflix は MEETS_STRONG_INTEGRITY
のない端末でインストールを禁じているので、Play ストアで Netflix がインストールできるかどうかは、非接触決済が使えるかどうかの指標になり得る。
追記 (3) : Play Integrity API をチェックするアプリが登場
Play Integrity API のレスポンスをチェックするアプリ、Play Intergrity API Checker2スペルミス? が Play ストアで公開された。これで MEETS_DEVICE_INTEGRITY
以外の値がどうであるか確認することができる。
これは Play Integrity API “のみ” 確認するので、前節のように fingerprint を変更したり対応版の Universal SafetyNet Fix をインストールしたりして、Google Pay が使えるようになっている状態であっても MEETS_STRONG_INTEGRITY
はバツになる。
- 1そもそも fingerprint を見るアプリが少ないといえばそれまでだが。
- 2スペルミス?