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
830
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.2k
Other Decks in Technology
See All in Technology
2025-06-26_Lightning_Talk_for_Lightning_Talks
_hashimo2
2
110
登壇ネタの見つけ方 / How to find talk topics
pinkumohikan
5
590
Lambda Web Adapterについて自分なりに理解してみた
smt7174
5
140
Node-REDのFunctionノードでMCPサーバーの実装を試してみた / Node-RED × MCP 勉強会 vol.1
you
PRO
0
130
KubeCon + CloudNativeCon Japan 2025 Recap
ren510dev
1
300
低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 / Building a C Compiler for PHPers Who Want to Dive into Low-Level Programming - Expanded
tomzoh
4
3.4k
高速なプロダクト開発を実現、創業期から掲げるエンタープライズアーキテクチャ
kawauso
1
270
モバイル界のMCPを考える
naoto33
0
360
GitHub Copilot の概要
tomokusaba
1
150
Zephyr RTOSを使った開発コンペに参加した件
iotengineer22
0
150
AWS Organizations 新機能!マルチパーティ承認の紹介
yhana
1
220
タイミーのデータモデリング事例と今後のチャレンジ
ttccddtoki
4
1.5k
Featured
See All Featured
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.9k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.4k
Typedesign – Prime Four
hannesfritz
42
2.7k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
161
15k
Statistics for Hackers
jakevdp
799
220k
Docker and Python
trallard
44
3.5k
Why Our Code Smells
bkeepers
PRO
337
57k
How to Think Like a Performance Engineer
csswizardry
24
1.7k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
130
19k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
29
9.5k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
233
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の対象外にすること は可能だが、本当に外しても問題ないかは要検討。 まとめ