web-dev-qa-db-ja.com

アプリケーションが資格情報をどのように保存するか

環境

デスクトップアプリケーションを開発するとき、アプリケーションを認証できるように、資格情報をどこかに保存する必要がある場合があります。この例は FacebookアプリID +シークレット で、もう1つはMySQL資格情報です。

これらのプレーンテキストをアプリケーションのソースコードに格納しても、 プログラムのリバースエンジニアリング を行うのにそれほど面倒ではないため、真のセキュリティは提供されません。ハッカーが自分でリクエストを簡単に実行できるため、サーバーから資格情報を収集してもトリックはありません。アプリケーションは資格情報を使用できるようにするために復号化キーにアクセスする必要があるため、保存された資格情報の暗号化は何の違いも生じません。


質問

アプリケーション固有の資格情報を安全に保存するにはどうすればよいですか?できればクロスOS。

注:関連する言語はJavaですが、これは言語にとらわれない質問だと思います

36
Zar

プログラムにパスワードや暗号キーをハードコードしないでください。

一般的な経験則は次のとおりです:ユーザーのマシンに保存する必要がある唯一の資格情報は、そのユーザーに関連付けられた資格情報です。彼/彼女のアカウントにログインします。

your開発者の認証情報をuser'sマシンに保存しないでください。それは安全ではありません。

ユーザーのマシンに保存されているものはすべてユーザーが知っているか、ユーザーが簡単に学習できると想定する必要があります。 (これは正しい仮定です。アプリケーションバイナリをリバースエンジニアリングして、埋め込まれている可能性のある鍵や秘密を知ることは難しくありません。)

この一般原則を理解すると、すべてが簡単になります。基本的に、クライアントソフトウェアがクライアントに安全に格納できる資格情報のみを使用して自身を認証できるように、システムの残りの部分と認証プロトコルを設計する必要があります。

例1。アプリに関連付けられている(つまり、開発者アカウントに関連付けられている)FacebookアプリIDとキーがあるとします。ユーザーに出荷するデスクトップソフトウェアにアプリIDとキーを埋め込みますか?番号!絶対違う。これは絶対に行わないでください。これを行うと、すべてのユーザーがアプリIDとキーを学習して独自のリクエストを送信し、評判を損なう可能性があります。

代わりに、別の方法を見つけます。たとえば、アプリIDとキーを持ち、Facebookプラットフォームへのリクエストを行う(適切な制限とレート制限が適用される)独自のサーバーをセットアップする場合があります。次に、クライアントがサーバーに接続します。たぶん、各ユーザーを自分のサーバーに自分のユーザーアカウントを設定してクライアントにアカウントの資格情報を保存し、クライアントにこれらの資格情報を使用して自分自身を認証させることで、各クライアントを認証できます。

クライアントアプリで最初の実行時に新しいユーザーアカウントを生成する(独自のログイン認証情報を生成してローカルに保存し、サーバーに送信する)ことで、これをユーザーから完全に見えなくすることができます。クライアントアプリはこれらの保存された資格情報を使用して、将来(たとえば、SSL経由で)接続し、アプリが実行されるたびに自動的にログインできます。

ユーザーのマシンに保存されているのは、そのユーザーのアカウントにログインできる資格情報だけであることに注意してください。ただし、他のユーザーのアカウントへのログインを許可するものや、開発者のアプリキーを公開するものはありません。

例2。ユーザーのGoogleアカウントでユーザーのデータにアクセスする必要があるアプリを作成するとします。 Googleのユーザー名とパスワードの入力を求め、アプリのローカルストレージに保存しますか?ユーザーの資格情報がユーザーのマシンに保存されているため、問題はありません。ユーザーは自分のマシンをハッキングしようとする動機はありません。なぜなら、彼らはすでに自分の資格情報を知っているからです。

さらに良いのは、OAuth=を使用してアプリを認証することです。これにより、アプリはOAuthトークンをアプリのローカルストレージに保存し、アプリがアクセスできるようにします。ユーザーのGoogleアカウント。ユーザーのGoogleパスワード(特に機密性が高い)をアプリのローカルストレージに保存する必要もないため、侵害のリスクが軽減されます。

例3。すべてのユーザー間で共有されるMySQLデータベースバックエンドを持つアプリを作成しているとします。 MySQLデータベースを取得して、アプリのバイナリに埋め込みますか?番号!どのユーザーでもパスワードを抽出して、MySQLデータベースに直接アクセスできます。

代わりに、必要な機能を提供するサービスを設定します。クライアントアプリはサービスに接続し、それ自体を認証して、リクエストをサービスに送信します。その後、サービスはこの要求をMySQLデータベースで実行できます。 MySQLパスワードはサーバーのマシンに安全に保存され、ユーザーのマシンからはアクセスできません。サーバーは、必要な制限やアクセス制御を課すことができます。

これには、クライアントアプリがサービスに対して認証できる必要があります。これを行う1つの方法は、初回実行時にクライアントアプリでサービスに新しいアカウントを作成し、ランダムな認証資格情報を生成し、以降のたびにサービスに自動的にログインすることです。ランダムなパスワードでSSLを使用することもできますが、さらに良いのは、クライアントごとに一意のクライアント証明書でSSLのようなものを使用することです。


もう1つのルールは、プログラムに資格情報をハードコードしないことです。ユーザーのマシンに認証情報を保存する場合は、プライベートな場所に保存します。おそらく、構成ファイルまたはディレクトリ、できれば、この特定のアプリまたはこの特定のユーザーのみが読み取り可能なもの(世界中で読み取り可能なファイルではない)に保存します。

30
D.W.

これは完全な解決策がなく、不完全なものである古典的なセキュリティ問題であり、ソフトウェアを改ざんやリバースエンジニアリングから保護するというより一般的な問題に要約されます。

  1. 資格情報に到達するためにユーザーが積極的に提供する必要のある外部認証方法を使用します:手動で入力したパスワード(ハッシュダイジェストは資格情報の復号化に使用されます)、証明書と一致する秘密鍵を含む安全な認証ドングルUSBポート、正しい指紋を提供する指紋リーダーなどに入力します。理想的には、この結果はプログラムに対する単純な「はい」/「いいえ」の回答ではなく、オーバーライド/パッチ/偽装される可能性がありますが、実際の値(a資格情報(または保護しようとしているその他の情報)を復号化するために必要な暗号化キー。認証システムから直接取得されます。復号化キーがさまざまなソースからその場で計算されるマルチソースアプローチ(どのソースについては、これは実際にはシステムに依存します)はさらに優れている可能性があります。

  2. プログラムを大幅に(自動的かつ大規模に)難読化して、リバースエンジニアリングを阻止します。確かに、静的分析ツールは最先端の技術になっていますが、リバースエンジニアリングに非常に時間がかかり、困難で面倒な[専用の高価な]難読化ツール(コンパイラ、パッカーなどを難読化)があります。より簡単なターゲットを探すために攻撃者を送るのに十分です。デバッグおよび改ざん防止メソッドに対する保護メカニズムを追加すると、プログラムのセキュリティをさらに強化できます。確かに、Javaバイトコード言語は、ネイティブコードの逆コンパイル/逆アセンブルと比較して)逆コンパイルがかなり単純であるため、この点で特に脆弱です。

7
Harel