Android/iOSアプリとインターネットからアクセス可能なバックエンドサービスの間で安全な通信をしたいので、HTTPS/SSLを調査しています。
自己署名証明書を作成する場合は、アプリにクライアント証明書を配置して、バックエンドサービスにthatクライアント証明書を要求させるisこれは本当に安全です?
これが私が尋ねている理由です。クライアント証明書は.apkに問い合わせることで「ハッキング」される可能性があるようです。クライアント証明書は単なる文字列定数ですよね?つまり、誰でもクライアント証明書を使用して私のバックエンドにアクセスできます。 。apk(およびiOSで同等のもの)は、クライアント証明書が検出されないように十分に不透明です?
証明書は無害です。保護が必要なのは秘密鍵であり、デバイス自体と同じくらい安全であり、安全ではありません。証明書と秘密キーをアプリケーションと共に配布するということは、アプリケーションを持っている人なら誰でもキーを持っていることを意味するだけなので、セキュリティはまったく提供されません。何らかのインストール後の登録手順が必要だと思います。
SSL経由の証明書を使用してクライアント側の認証を行っていますか?この質問にとってそれが本当に重要であるというわけではありません。アプリに保存した秘密キーはすべて、攻撃者がアクセスできます。大量の侵害を防ぐために、各クライアントには独自の証明書とキーのペアが必要です。また、サーバーは保護を実施し、侵害されたクライアントが何も要求できないようにします。
これは、どの認証スキームにも当てはまります。パスワード、APIキー、復号化キーなどを埋め込む場合。デバイス上のすべてがアクセス可能であると想定する必要があります。
証明書による追加のセキュリティは、ブルートフォースに何もないことが原因です。各クライアントのユーザー名/パスワードルートを使用した場合、パスワードは推測されます。 APIキーと同じです(ただし、長くて難しい)。証明書を使用すると、それはまったく異なる種類の攻撃であり、かなり難しい問題になります。
ただし、最も重要なこととして、バックエンドサービスでは、アプリが通常は実行できないことをすべて実行できないようにする必要があります。
さて、証明書を扱うと、他にも多くの問題が発生します。おそらく、各クライアント証明書に自己署名CA証明書で署名する必要があります。ユースケースによっては、CA証明書の管理に問題が生じる可能性があります。これらのクライアント証明書をオンザフライで生成しますか、それとも手動で生成しますか?つまり、これは100万人がダウンロードできるアプリであり、それらを生成するための自動化システムが必要ですか?それとも、個人的に証明書の生成を処理するプライベート/内部アプリですか?
通常、クライアントSSL証明書はキーストア(Androidの場合はBKS形式)に保存され、キーストアはAPK内のリソースとして含まれています。キーストアは暗号化され、パスワードで保護されています。したがって、そのクライアント証明書は暗号化された形式で保存されているため、APKから簡単に抽出できません。
さて...パスワードはどうしますか?これが問題の核心であり、2つの選択肢があります。
ユーザーの操作なしでアプリケーションがサーバーと通信できるようにする(つまり、証明書にアクセスできるようにする)場合は、アプリケーションにパスワードを埋め込む必要があります。そうすれば、攻撃者がコードをリバースエンジニアリングする可能性があります。それを見つけるには、キーストアを取得し、それを復号化して証明書を回復します。コードを難読化するなどの手法を適用して、攻撃者がコードを難読化するのを困難にすることができますが、これは誰かを遅くし、それを妨げることはありません。
別の方法として、アプリケーションがサーバーと通信するたびにユーザーにパスワードを要求し、それを使用してキーストアを復号化することもできます(または、アプリがいつ起動して証明書を一定時間キャッシュするかを尋ねます)。ここでの利点は、誰かがAPKをリバースエンジニアリングした場合、暗号化されたキーストアが見つかり、パスワードがないため、証明書が安全であることです。欠点は、ユーザーにパスワードを提供させることです。
どのアプローチが最適ですか?それは、関心のあるデータの機密性と、受け入れようとするリスクのレベルに完全に依存します。あなただけがその質問に答えることができます。
ダニエル・ギラモット、私がやってきたいくつかのトリック:
誰か他のアイデアがあればもっと聞いてみたいです。
APKはアクセスしてコピーできるため、何かを入れても役に立ちません。インストール後にアクティベーションを行い、場合によっては証明書をデバイスにバインドする必要があります。バインドは、たとえば、デバイスのIMEIを証明書拡張の1つに置き、アプリケーションによってIMEIを証明書と一緒に渡す(または、IMEI after認証を渡して安全なチャネルを確立する)ことで実行できます。 )。