Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
WebViewを守るSafeBrowsingのコントロール / Control result ...
Search
Aki
February 08, 2019
Technology
1
770
WebViewを守るSafeBrowsingのコントロール / Control result of SafeBrowsing in WebView
DroidKaigi2019 Day2での発表スライドです。
Aki
February 08, 2019
Tweet
Share
More Decks by Aki
See All by Aki
厳しくなったSafetyNet Attestationによる端末チェック
akihiroshiota
2
2.1k
Other Decks in Technology
See All in Technology
サイボウズフロントエンドエキスパートチームについて / FrontendExpert Team
cybozuinsideout
PRO
5
38k
レンジャーシステムズ | 会社紹介(採用ピッチ)
rssytems
0
150
ずっと昔に Star をつけたはずの思い出せない GitHub リポジトリを見つけたい!
rokuosan
0
150
C++26 エラー性動作
faithandbrave
2
710
Jetpack Composeで始めるServer Cache State
ogaclejapan
2
170
GitHub Copilot のテクニック集/GitHub Copilot Techniques
rayuron
26
11k
PHPからGoへのマイグレーション for DMMアフィリエイト
yabakokobayashi
1
170
終了の危機にあった15年続くWebサービスを全力で存続させる - phpcon2024
yositosi
0
430
Wantedly での Datadog 活用事例
bgpat
1
430
サーバレスアプリ開発者向けアップデートをキャッチアップしてきた #AWSreInvent #regrowth_fuk
drumnistnakano
0
190
なぜCodeceptJSを選んだか
goataka
0
160
Wvlet: A New Flow-Style Query Language For Functional Data Modeling and Interactive Data Analysis - Trino Summit 2024
xerial
1
110
Featured
See All Featured
Designing Dashboards & Data Visualisations in Web Apps
destraynor
229
52k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
The Art of Programming - Codeland 2020
erikaheidi
53
13k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.2k
Documentation Writing (for coders)
carmenintech
66
4.5k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
95
17k
How to Ace a Technical Interview
jacobian
276
23k
Testing 201, or: Great Expectations
jmmastey
40
7.1k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
5
440
Dealing with People You Can't Stand - Big Design 2015
cassininazir
365
25k
Side Projects
sachag
452
42k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Transcript
WebViewを守る SafeBrowsingのコントロール DroidKaigi 2019 2019/2/8 17:40 Room4 Akihiro Shiota
自己紹介 ◼塩田 明弘(シオタ アキヒロ) ◼Twitter:@aki_sh_7 ◼セキュリティ系のお仕事をしてます
注意事項 ◼本セッションの内容は2019年1月25日時点の 内容を基にしています。将来のAndroidOS、 JetPack、GMS、chrome、webviewのバージョン によっては動作しない、または異なる動作を する可能性があります。
目次 1. WebViewでのSafeBrowsing 2. SafeBrowsingのコントロール 3. Safetynet SafeBrowsingとの関係 4. まとめ
WebViewでの SafeBrowsing
WebViewの脆弱性 ⚫Fileスキーマでのファイルアクセス ⚫キャッシュの平文での保存 ⚫addJavascriptInterfaceによるメソッド呼び出し ⚫onReceivedSslError ハンドラの安全でない実装 ⚫etc…
コンテンツに対する判断 ◼コンテンツ自体の危険性も判断が必要 (特にアクセス先を限定できないアプリ) ◼PCブラウザ等でも利用されていた、 SafeBrowsing機能がAndroidでも使える
SafeBrowsingとは ◼「安全ではないウェブサイト」へ のアクセス時に警告を出すサービス。 ◼収集したデータベースと合致する サイトを検出。
安全ではないウェブサイト ◼不正なソフトウェアサイト マルウェア 望ましくないソフトウェア ◼フィッシングサイト
WebViewでのSafeBrowsing ◼WebViewでの利用開始(2017)。 サポート対象はAndroid5.0以上 ◼バージョン66以上でデフォルト有効 ◼SafeBrowsingの動作を前提にアプリを開発するなら、 minSDKVersionは21以上に。
SafeBrowsingの使い方 使うだけならマニフェストに以下の記述をすればOK この設定をしておくことで、バージョン66未満の WebViewでも有効になる <manifest> <application> <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing" android:value=“true" />
... </application> </manifest>
WebViewでのSafeBrowsing
WebViewでのSafeBrowsing シンプルすぎ?
SafeBrowsingの表示条件 ◼この表示はWebViewのViewのサイズが原因。 以下の条件の時だけ、Chromeと同じ表示になる。 ➢RootViewとWidthが同じ ➢HeightがRootViewの7割以上 ◼どちらかでも当てはまらなければ簡易表示になる (Widthがオーバーしていると説明も表示されない)
chrome://interstitials ◼SafeBrowsingの警告ページは、 chrome://interstitialsで確認可能。
SafeBrowsingの コントロール
SafeBrowsingのコントロール APIレベル26・27で挙動をコントロールするAPIが追加 ➢SafeBrowsingの初期化機能 ➢SafeBrowsingで検出された時の挙動にかかわる機能 ➢WebViewインスタンス単位での有効化API ➢SafeBrowsingのホワイトリストによる検査除外 実装時には、JetPackを使うことをお勧めする。 (単純なバージョン分岐でなく、APIレベル26・27未満でも上 記機能が使えるようになる。4.4以下では使えません。) implementation
'androidx.webkit:webkit:1.0.0'
WebViewCompat# startSafeBrowsing SafeBrowsingの初期化を行う WebViewCompatはWebViewの拡張クラスでないので注意 if(WebViewFeature.isFeatureSupported(START_SAFE_BROWSING)) { if(WebSettingsCompat.getSafeBrowsingEnabled(webView.settings)) WebViewCompat.startSafeBrowsing(this) { success
-> mSafeBrowsingIsInitialized = true if (!success) { Log.w("WebView SafeBrowsing", "Unable to initialize Safe Browsing!") } else { Log.i("SafeBrowsing", "SafeBrowsing initialization success!") webView.loadUrl("http://testsafebrowsing.appspot.com/") } }else { Log.w("SafeBrowsing", "SafeBrowsing is disabled") } }else{ Log.w("SafeBrowsing", "SafeBrowsing initialization is not supported...") } 処理開始前に有効化されているか確認。 実行はできる為、リソースが準備されてしまう
WebViewFeature# isFeatureSupported 機能の確認をしてから呼び出す この後出てくる各機能を呼ぶ前にもそれぞれ確認する if(WebViewFeature.isFeatureSupported(START_SAFE_BROWSING)) { if(WebSettingsCompat.getSafeBrowsingEnabled(webView.settings)) WebViewCompat.startSafeBrowsing(this) { success
-> mSafeBrowsingIsInitialized = true if (!success) { Log.w("WebView SafeBrowsing", "Unable to initialize Safe Browsing!") } else { Log.i("SafeBrowsing", "SafeBrowsing initialization success!") webView.loadUrl("http://testsafebrowsing.appspot.com/") } }else { Log.w("SafeBrowsing", "SafeBrowsing is disabled") } }else{ Log.w("SafeBrowsing", "SafeBrowsing initialization is not supported...") }
WebViewClientCompat# onSafeBrowsingHit 安全でないウェブページと判断されると呼ばれる。 override fun onSafeBrowsingHit(view: WebView, request: WebResourceRequest, threatType:
Int, callback: SafeBrowsingResponseCompat){ val dlg = AlertDialog.Builder(view.context) dlg.setTitle("Warning") dlg.setMessage(StringThreatType + request.url + "にアクセスしようとしています。¥n 元のページに戻る場合には「戻る」、詳しい説明を確認する場合は「詳細確認」をクリックしてください") dlg.setPositiveButton("詳細確認") { _, _ -> callback.showInterstitial(false) } dlg.setNegativeButton("元のページへ戻る") { _, _ -> callback.backToSafety(true) } dlg.setNeutralButton("ホームへ戻る") { _, _ -> view.loadUrl("https://www.google.co.jp")} dlg.show() }
SafeBrowsingResponseCompat SafeBrowsingResponseCompatは3つのアクションが可能 ⚫showInterstitial:遷移やレポート送付を選択可能なページを表示。 1章でも説明した画面が表示。デフォルトではこれ。 ⚫backToSafety:「セキュリティで保護されたページに戻る」と同じ ⚫Proceed:「安全でないサイトにアクセスする」と同じ
WebViewClientCompat# onSafeBrosingHit その他の引数でリクエスト情報と脅威のタイプを取得可能 override fun onSafeBrowsingHit(view: WebView, request: WebResourceRequest, threatType:
Int, callback: SafeBrowsingResponseCompat){ val dlg = AlertDialog.Builder(view.context) dlg.setTitle("Warning") dlg.setMessage(StringThreatType + request.url + "にアクセスしようとしています。¥n 元のページに戻る場合には「戻る」、詳しい説明を確認する場合は「詳細確認」をクリックしてください") dlg.setPositiveButton("詳細確認") { _, _ -> callback.showInterstitial(false) } dlg.setNegativeButton("元のページへ戻る") { _, _ -> callback.backToSafety(true) } dlg.setNeutralButton("ホームへ戻る") { _, _ -> view.loadUrl("https://www.google.co.jp")} dlg.show() }
WebViewClientCompat# onSafeBrosingHit 第二引数:requestからリクエストの情報を取得可能。 override fun onSafeBrowsingHit(view: WebView, request: WebResourceRequest, threatType:
Int, callback: SafeBrowsingResponseCompat){ val dlg = AlertDialog.Builder(view.context) dlg.setTitle("Warning") dlg.setMessage(StringThreatType + request.url + "にアクセスしようとしています。¥n 元のページに戻る場合には「戻る」、詳しい説明を確認する場合は「詳細確認」をクリックしてください") dlg.setPositiveButton("詳細確認") { _, _ -> callback.showInterstitial(false) } dlg.setNegativeButton("元のページへ戻る") { _, _ -> callback.backToSafety(true) } dlg.setNeutralButton("ホームへ戻る") { _, _ -> view.loadUrl("https://www.google.co.jp")} dlg.show() }
WebViewClientCompat# onSafeBrowsingHit 第三引数:threatTypeは安全でないページと判断された理由。 以下の4種類が定義されている。 MALWARE、PHISHING、UNWANTED_SOFTWARE、UNKNOWN override fun onSafeBrowsingHit(view: WebView, request:
WebResourceRequest, threatType: Int, callback: SafeBrowsingResponseCompat){ ~~~~~~~~~ val StringThreatType:String = when(threatType){ 0 -> "未知の危険が検出された" 1 -> "マルウェア感染の疑いのある" 2 -> "フィッシングサイトの疑いのある" 3 -> "望まないアプリが配布される疑いのある" else -> "" } ~~~~~~~~~ dlg.setMessage(StringThreatType + request.url + "にアクセスしようとしています。¥n 元のページに戻る場合には「戻る」、詳しい説明を確認する場合は「詳細確認」をクリックしてください")
WebViewClientCompat# onSafeBrosingHit SafeBrowsingResponseCompatのアクションを、ダイアログのボタ ンに割り当てて、独自の確認ダイアログの設定も可能 override fun onSafeBrowsingHit(view: WebView, request: WebResourceRequest,
threatType: Int, callback: SafeBrowsingResponseCompat){ val dlg = AlertDialog.Builder(view.context) dlg.setTitle("Warning") dlg.setMessage(StringThreatType + request.url + "にアクセスしようとしています。¥n 元のページに戻る場合には「戻る」、詳しい説明を確認する場合は「詳細確認」をクリックしてください") dlg.setPositiveButton("詳細確認") { _, _ -> callback.showInterstitial(false) } dlg.setNegativeButton("元のページへ戻る") { _, _ -> callback.backToSafety(true) } dlg.setNeutralButton("ホームへ戻る") { _, _ -> view.loadUrl("https://www.google.co.jp")} dlg.show() }
WebViewClientCompat# onSafeBrosingHit WebViewインスタンスで直接特定ページに遷移させることも可能 override fun onSafeBrowsingHit(view: WebView, request: WebResourceRequest, threatType:
Int, callback: SafeBrowsingResponseCompat){ val dlg = AlertDialog.Builder(view.context) dlg.setTitle("Warning") dlg.setMessage(StringThreatType + request.url + "にアクセスしようとしています。¥n 元のページに戻る場合には「戻る」、詳しい説明を確認する場合は「詳細確認」をクリックしてください") dlg.setPositiveButton("詳細確認") { _, _ -> callback.showInterstitial(false) } dlg.setNegativeButton("元のページへ戻る") { _, _ -> callback.backToSafety(true) } dlg.setNeutralButton("ホームへ戻る") { _, _ -> view.loadUrl("https://www.google.co.jp")} dlg.show() }
threatTypeの注意事項 ◼WebViewClient(compat)で定義されているのは先に紹介した4つ ◼Chrome 71よりbillingが追加。 ◼不明瞭な支払い登録プロセスが対象 ◼このタイプはonSafeBrosingHitでは 0(UNKNOWN)として返ってきている。
WebSettingsCompat# setSafeBrowsingEnabled WebViewインスタンスごとに、 個別にSafeBrowsingの有効・無効を設定する。 Manifestファイルでの設定よりこっちが優先。 //第1引数に、SafeBrowsingを設定するWebViewインスタンスのWebSettingsを指定する WebSettingsCompat.setSafeBrowsingEnabled(webView.settings,true)
WebViewCompat# setSafeBrowsingWhitelist ホワイトリスト形式で、SafeBrowsingの対象外とするホ ストを指定可能。 ドメインかIPアドレス(v4,v6)での指定のため、一部ペー ジのみ対象とすることは出来ない。 if(WebViewFeature.isFeatureSupported(SAFE_BROWSING_WHITELIST)) { WebViewCompat.setSafeBrowsingWhitelist( ArrayList(Arrays.asList("testsafebrowsing.appspot.com"))
) { result -> Log.i("SafeBrowsing", “Add Whitelist " + result!!.toString()) } }
無効・除外設定の使いどころ ◼使いどころが難しい(安易に設定できない) ◼基本的な考え方は信頼できる対象を設定する。 ◼設定した対象が改ざんされていたら? ◼自サイトが間違って検出されることがあった場合に、 再審査の申請をして、受け入れられるまでのつなぎ? (ただし、その場合も自サイトに問題ないことを確認しないと、 ユーザに被害を及ぼすかもしれないので注意。)
Safeynet SafeBrowsing
◼Androidで使えるSafeBrowsingはもう一つ存在する。 ◼SafetyNet APIの一種であるSafeBrowsing ◼SafetyNet APIなのでGooglePlay開発者サービス ◼GooglePlay開発者サービスver8.1以降で利用可能 SafetyNet SafeBrowsing
◼Android版のchromeでは、SafeBrowsingの実行のために Safetynetを利用している。 ◼WebViewも同様 ◼つまり、WebViewでのSafeBrowsingも GooglePlay開発者サービスが入っていない端末では 利用できない。 SafeBrowsingの関係
まとめ
◼アクセス先のリスクをGoogleのデータベースを用 いて調べることができる機能。アクセス先を限定 できないときに利用するのがよい。 ◼SafeBrowsingのレスポンスを用いて、自アプリの ポリシに従った対応にすることができる。 ◼特定のホストをSafeBrowsingの対象外にすること は可能だが、本当に外しても問題ないかは要検討。 まとめ