70

webviewで開くリンクがあります。問題は、次のように onReceivedSslError をオーバーライドするまで開くことができないことです。

 @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
            handler.proceed();
        }

Google Play から次のようなセキュリティ アラートが表示されます。

セキュリティ アラート アプリケーションには、WebViewClient.onReceivedSslError ハンドラーの安全でない実装があります。特に、この実装では SSL 証明書の検証エラーがすべて無視されるため、アプリは中間者攻撃に対して脆弱になります。攻撃者は、影響を受ける WebView のコンテンツを変更し、送信されたデータ (ログイン資格情報など) を読み取り、JavaScript を使用してアプリ内でコードを実行する可能性があります。

SSL 証明書の検証を適切に処理するには、コードを変更して、サーバーによって提示された証明書が期待どおりである場合は常に SslErrorHandler.proceed() を呼び出し、それ以外の場合は SslErrorHandler.cancel() を呼び出します。影響を受けるアプリとクラスを含む電子メール アラートが開発者アカウント アドレスに送信されました。

できるだけ早くこの脆弱性に対処し、アップグレードされた APK のバージョン番号を増やしてください。SSL エラー ハンドラの詳細については、開発者ヘルプ センターのドキュメントを参照してください。その他の技術的な質問については、https: //www.stackoverflow.com/questions に投稿し、タグ「android-security」および「SslErrorHandler」を使用できます。これを担当するサードパーティのライブラリを使用している場合は、サードパーティに通知し、協力して問題に対処してください。

正しくアップグレードされたことを確認するには、更新されたバージョンを開発者コンソールにアップロードし、5 時間後にもう一度確認してください。アプリが正しくアップグレードされていない場合は、警告が表示されます。

これらの特定の問題は、WebView SSL を使用するすべてのアプリに影響するわけではありませんが、すべてのセキュリティ パッチを最新の状態にしておくことをお勧めします。ユーザーを侵害のリスクにさらす脆弱性を持つアプリは、コンテンツ ポリシーと開発者配布契約のセクション 4.4 に違反する危険な製品と見なされる可能性があります。

公開されたすべてのアプリが、開発者配布契約とコンテンツ ポリシーに準拠していることを確認してください。ご質問やご不明な点がございましたら、Google Play デベロッパー ヘルプ センターからサポート チームまでお問い合わせください。

を削除するonReceivedSslError (handler.proceed())と、ページが開かなくなります。

とにかく、webview でページを開き、セキュリティ アラートを回避できますか。

4

8 に答える 8

129

SSL 証明書の検証を適切に処理するには、コードを変更して、サーバーによって提示された証明書が期待どおりである場合は常に SslErrorHandler.proceed() を呼び出し、それ以外の場合は SslErrorHandler.cancel() を呼び出します。

電子メールが言ったように、onReceivedSslErrorユーザーが通知ダイアログなどの無効な証明書を持つページに行くことを処理する必要があります。直接進めるべきではありません。

たとえば、ユーザーに確認させるアラート ダイアログを追加すると、Google が警告を表示しなくなったようです。


@Override
public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
    final AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage(R.string.notification_error_ssl_cert_invalid);
    builder.setPositiveButton("continue", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            handler.proceed();
        }
    });
    builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            handler.cancel();
        }
    });
    final AlertDialog dialog = builder.create();
    dialog.show();
}

メールについて詳しく説明します。

特に、この実装では SSL 証明書の検証エラーがすべて無視されるため、アプリは中間者攻撃に対して脆弱になります。

電子メールには、デフォルトの実装が重要な SSL セキュリティの問題を無視したことが記載されています。そのため、WebView を使用した独自のアプリで処理する必要があります。アラート ダイアログでユーザーに通知するのは簡単な方法です。

于 2016-03-22T06:53:03.367 に答える
9

これまでに提案されたソリューションは、セキュリティ チェックをバイパスするだけなので、安全ではありません。

私が提案するのは、アプリに証明書を埋め込むことです。SslError が発生した場合は、サーバー証明書が埋め込まれた証明書の 1 つと一致することを確認してください。

手順は次のとおりです。

  1. Web サイトから証明書を取得します。

    • Safariでサイトを開く
    • Web サイト名の近くにある南京錠アイコンをクリックします。
    • 証明書の表示をクリックします
    • 証明書をフォルダーにドラッグ アンド ドロップします。

https://www.markbrilman.nl/2012/03/howto-save-a-certificate-via-safari-on-mac/を参照してください

  1. 証明書 (.cer ファイル) をアプリの res/raw フォルダーにコピーします。

  2. コードで、loadSSLCertificates() を呼び出して証明書をロードします。

    private static final int[] CERTIFICATES = {
            R.raw.my_certificate,   // you can put several certificates
    };
    private ArrayList<SslCertificate> certificates = new ArrayList<>();
    
    private void loadSSLCertificates() {
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            for (int rawId : CERTIFICATES) {
                InputStream inputStream = getResources().openRawResource(rawId);
                InputStream certificateInput = new BufferedInputStream(inputStream);
                try {
                    Certificate certificate = certificateFactory.generateCertificate(certificateInput);
                    if (certificate instanceof X509Certificate) {
                        X509Certificate x509Certificate = (X509Certificate) certificate;
                        SslCertificate sslCertificate = new SslCertificate(x509Certificate);
                        certificates.add(sslCertificate);
                    } else {
                        Log.w(TAG, "Wrong Certificate format: " + rawId);
                    }
                } catch (CertificateException exception) {
                    Log.w(TAG, "Cannot read certificate: " + rawId);
                } finally {
                    try {
                        certificateInput.close();
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (CertificateException e) {
            e.printStackTrace();
        }
    }
    
  3. SslError が発生した場合、サーバー証明書が 1 つの組み込み証明書と一致することを確認します。証明書を直接比較することはできないため、SslCertificate.saveState を使用して証明書データをバンドルに入れ、すべてのバンドル エントリを比較します。

    webView.setWebViewClient(new WebViewClient() {
    
        @Override
        public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
    
            // Checks Embedded certificates
            SslCertificate serverCertificate = error.getCertificate();
            Bundle serverBundle = SslCertificate.saveState(serverCertificate);
            for (SslCertificate appCertificate : certificates) {
                if (TextUtils.equals(serverCertificate.toString(), appCertificate.toString())) { // First fast check
                    Bundle appBundle = SslCertificate.saveState(appCertificate);
                    Set<String> keySet = appBundle.keySet();
                    boolean matches = true;
                    for (String key : keySet) {
                        Object serverObj = serverBundle.get(key);
                        Object appObj = appBundle.get(key);
                        if (serverObj instanceof byte[] && appObj instanceof byte[]) {     // key "x509-certificate"
                            if (!Arrays.equals((byte[]) serverObj, (byte[]) appObj)) {
                                matches = false;
                                break;
                            }
                        } else if ((serverObj != null) && !serverObj.equals(appObj)) {
                            matches = false;
                            break;
                        }
                    }
                    if (matches) {
                        handler.proceed();
                        return;
                    }
                }
            }
    
            handler.cancel();
            String message = "SSL Error " + error.getPrimaryError();
            Log.w(TAG, message);
        }
    
    
    });
    
于 2018-04-05T14:24:50.257 に答える
6

Google Security Alert: Unsafe implementation of the interface X509TrustManagerによると、Google Play はX509TrustManager2016 年 7 月 11 日からサポートされなくなります。

Google Play デベロッパー様、こんにちは。

このメールの最後に記載されているあなたのアプリは、インターフェース X509TrustManager の安全でない実装を使用しています。特に、この実装では、リモート ホストへの HTTPS 接続を確立するときに SSL 証明書の検証エラーがすべて無視されるため、アプリが中間者攻撃に対して脆弱になります。攻撃者は、送信されたデータ (ログイン資格情報など) を読み取ったり、HTTPS 接続で送信されたデータを変更したりする可能性があります。アカウントに影響を受けるアプリが 20 個以上ある場合は、Developer Console で完全なリストを確認してください。

SSL 証明書の検証を適切に処理するには、カスタム X509TrustManager インターフェースの checkServerTrusted メソッドのコードを変更して、サーバーによって提示された証明書が期待どおりでない場合は常に CertificateException または IllegalArgumentException を発生させます。技術的な質問については、「android-security」および「TrustManager」のタグを使用して Stack Overflow に投稿できます。</p>

できるだけ早くこの問題に対処し、アップグレードされた APK のバージョン番号を増やしてください。2016 年 5 月 17 日以降、Google Play は、インターフェイス X509TrustManager の安全でない実装を含む新しいアプリまたはアップデートの公開をブロックします。

変更が正しく行われたことを確認するには、アプリの更新バージョンをデベロッパー コンソールに送信し、5 時間後にもう一度確認してください。アプリが正しくアップグレードされていない場合は、警告が表示されます。

これらの特定の問題は、TrustManager 実装を使用するすべてのアプリに影響するわけではありませんが、SSL 証明書の検証エラーを無視しないことをお勧めします。ユーザーを侵害のリスクにさらす脆弱性を持つアプリは、コンテンツ ポリシーと開発者配布契約のセクション 4.4 に違反する危険な製品と見なされる可能性があります。

...

于 2016-07-21T08:42:05.723 に答える