Java.class
ファイルはかなり簡単に逆コンパイルできます。コードでログインデータを使用する必要がある場合、データベースを保護するにはどうすればよいですか?
Java.class
ファイルはかなり簡単に逆コンパイルできます。コードでログインデータを使用する必要がある場合、データベースを保護するにはどうすればよいですか?
回答:
パスワードをコードにハードコーディングしないでください。これは最近、プログラミングの最も危険な間違いトップ25で取り上げられました。
秘密のアカウントとパスワードをソフトウェアにハードコーディングすると、熟練したリバースエンジニアにとって非常に便利です。パスワードがすべてのソフトウェアで同じである場合、そのパスワードが必然的に知られるようになると、すべての顧客が脆弱になります。また、ハードコーディングされているため、修正するのは非常に面倒です。
パスワードを含む構成情報は、アプリケーションの起動時に読み取る別のファイルに保存する必要があります。これが、逆コンパイルの結果としてパスワードがリークするのを防ぐ唯一の実際の方法です(最初からバイナリにコンパイルしないでください)。
このよくある間違いの詳細については、CWE-259の記事を参照してください。この記事には、より完全な定義、例、および問題に関するその他の多くの情報が含まれています。
Javaでは、これを行う最も簡単な方法の1つは、Preferencesクラスを使用することです。あらゆる種類のプログラム設定を保存するように設計されており、その一部にはユーザー名とパスワードが含まれている可能性があります。
import java.util.prefs.Preferences;
public class DemoApplication {
Preferences preferences =
Preferences.userNodeForPackage(DemoApplication.class);
public void setCredentials(String username, String password) {
preferences.put("db_username", username);
preferences.put("db_password", password);
}
public String getUsername() {
return preferences.get("db_username", null);
}
public String getPassword() {
return preferences.get("db_password", null);
}
// your code here
}
上記のコードでsetCredentials
は、ユーザー名とパスワードを尋ねるダイアログを表示した後、メソッドを呼び出すことができます。データベースに接続する必要がある場合は、getUsername
andgetPassword
メソッドを使用して保存された値を取得できます。ログイン資格情報はバイナリにハードコードされないため、逆コンパイルによってセキュリティリスクが発生することはありません。
重要な注意:設定ファイルはプレーンテキストのXMLファイルです。許可されていないユーザーがrawファイル(UNIXのアクセス許可、Windowsのアクセス許可など)を表示しないように、適切な手順を実行してください。Linuxでは、少なくともこれは問題ではありません。呼び出すPreferences.userNodeForPackage
と、現在のユーザーのホームディレクトリにXMLファイルが作成され、他のユーザーはそれを読み取ることができないためです。Windowsでは、状況が異なる場合があります。
より重要な注意事項:この回答や他の人のコメントでは、この状況に適したアーキテクチャについて多くの議論がありました。元の質問では、アプリケーションが使用されているコンテキストについては実際には言及されていないため、考えられる2つの状況について説明します。1つ目は、プログラムを使用している人がデータベースの資格情報をすでに知っている(そして知ることを許可されている)場合です。2つ目は、開発者であるあなたが、プログラムを使用している人からデータベースの資格情報を秘密にしようとしている場合です。
最初のケース:ユーザーはデータベースのログイン資格情報を知ることを許可されています
この場合、上記の解決策が機能します。JavaPreference
クラスはユーザー名とパスワードをプレーンテキストで保存しますが、設定ファイルは許可されたユーザーのみが読み取ることができます。ユーザーは、設定XMLファイルを開いてログイン資格情報を読み取るだけで済みますが、ユーザーは最初から資格情報を知っているため、セキュリティ上のリスクはありません。
2番目のケース:ユーザーからログイン資格情報を隠そうとしている
これはより複雑なケースです。ユーザーはログイン資格情報を知らないはずですが、それでもデータベースにアクセスする必要があります。この場合、アプリケーションを実行しているユーザーはデータベースに直接アクセスできます。つまり、プログラムは事前にログイン資格情報を知っている必要があります。上記の解決策は、この場合には適切ではありません。データベースのログイン資格情報は設定ファイルに保存できますが、所有者になるため、ユーザーはそのファイルを読み取ることができます。実際、このケースを安全な方法で使用する良い方法は実際にはありません。
正しいケース:多層アーキテクチャを使用する
これを行う正しい方法は、データベースサーバーとクライアントアプリケーションの間に、個々のユーザーを認証し、限られた一連の操作を実行できるようにする中間層を設けることです。各ユーザーは独自のログイン資格情報を持っていますが、データベースサーバー用ではありません。資格情報は、中間層(ビジネスロジック層)へのアクセスを許可し、ユーザーごとに異なります。
すべてのユーザーは独自のユーザー名とパスワードを持っており、セキュリティ上のリスクなしに設定ファイルにローカルに保存できます。これは、3層アーキテクチャ(データベースサーバー、ビジネスロジックサーバー、およびクライアントアプリケーションである層)と呼ばれます。それはもっと複雑ですが、それは本当にこの種のことをするための最も安全な方法です。
操作の基本的な順序は次のとおりです。
getInventoryList
です。プロセス全体で、クライアントアプリケーションがデータベースに直接接続することは決してないことに注意してください。ビジネスロジック層は、認証されたユーザーから要求を受け取り、インベントリリストに対するクライアントの要求を処理してから、SQLクエリを実行します。
アプリケーションが読み取るファイルにパスワードを入力します。ソースファイルにパスワードを埋め込まないでください。限目。
Rubyには、そのような使用法のためのDBI :: DBRCと呼ばれるあまり知られていないモジュールがあります。Javaに同等のものがあることは間違いありません。とにかく、書くのは難しくありません。
Webアプリケーションを作成していますか?その場合は、JNDIを使用してアプリケーションの外部で構成します。概要はこちらから入手できます:
JNDIは、アプリケーションがネットワーク経由でリモートサービスを見つけてアクセスするための統一された方法を提供します。リモートサービスは、メッセージングサービスやアプリケーション固有のサービスを含む任意のエンタープライズサービスですが、もちろん、JDBCアプリケーションは主にデータベースサービスに関心があります。DataSourceオブジェクトが作成されてJNDIネーミングサービスに登録されると、アプリケーションはJNDI APIを使用してそのDataSourceオブジェクトにアクセスでき、それを使用して、それが表すデータソースに接続できます。
何をしても、機密情報はどこかのファイルに保存されます。あなたの目標は、取得をできるだけ難しくすることです。これをどれだけ達成できるかは、プロジェクト、ニーズ、および会社のウォレットの厚さによって異なります。
最善の方法は、パスワードをどこにも保存しないことです。これは、ハッシュ関数を使用してパスワードハッシュを生成および保存することで実現されます。
hash("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
hash("hbllo") = 58756879c05c68dfac9866712fad6a93f8146f337a69afe7dd238f3364946366
ハッシュアルゴリズムは一方向性関数です。それらは、任意の量のデータを、元に戻すことができない固定長の「フィンガープリント」に変換します。また、入力が少しでも変化すると、結果のハッシュが完全に異なるという特性もあります(上記の例を参照)。これは、パスワードファイル自体が侵害された場合でもパスワードを保護する形式でパスワードを保存するため、パスワードの保護に最適ですが、同時に、ユーザーのパスワードが正しいことを確認できる必要があります。
無関係な注意:インターネットの昔、「パスワードを忘れた」リンクをクリックすると、Webサイトからプレーンテキストのパスワードが電子メールで送信されていました。彼らはおそらくそれらをどこかのデータベースに保存していたのでしょう。ハッカーがデータベースにアクセスできるようになると、すべてのパスワードにアクセスできるようになります。多くのユーザーが複数のWebサイトで同じパスワードを使用するため、これは大きなセキュリティ問題でした。幸いなことに、今日ではこれは一般的な方法ではありません。
ここで質問があります:パスワードを保存するための最良の方法は何ですか?私はこの(認証およびユーザー管理サービスのストームパスの)ソリューションを非常に理想的なソリューションと見なします。
明らかにあなたはグーグルでも銀行でもないので、これはあなたにとってやり過ぎの解決策です。しかし、次に問題が発生します。プロジェクトに必要なセキュリティの量、時間とお金の量はどれくらいですか。
多くのアプリケーションでは、推奨されていませんが、ハードコードされたパスワードをコードに保存することで十分な解決策になる可能性があります。ただし、上記のリストからセキュリティのいくつかの追加手順を簡単に追加することで、アプリケーションをはるかに安全にすることができます。
たとえば、ステップ1がプロジェクトにとって受け入れ可能なソリューションではないと仮定しましょう。ユーザーに毎回パスワードを入力させたくない、またはユーザーにパスワードを知られたくない/必要としない。それでもあなたはどこかに機密情報を持っていて、これを保護したいと思っています。単純なアプリケーションがあり、ファイルを保存するサーバーがないか、これはプロジェクトにとって非常に面倒です。アプリケーションは、ファイルを安全に保存できない環境で実行されます。これは最悪のケースの1つですが、それでもいくつかの追加のセキュリティ対策を講じることで、はるかに安全なソリューションを得ることができます。たとえば、機密情報をファイルに保存したり、ファイルを暗号化したりできます。暗号化秘密鍵をコードにハードコーディングすることができます。コードを難読化できるので、誰かがコードを解読するのが少し難しくなります。このリンク。(これは100%安全ではないことをもう一度警告したいと思います。適切な知識とツールを備えた賢いハッカーはこれをハッキングできます。しかし、要件とニーズに基づいて、これはあなたにとって十分な解決策かもしれません)。
この質問は、パスワードやその他のデータを暗号化されたファイルに保存する方法を示しています。Java256ビットAESパスワードベースの暗号化
MD5はハッシュアルゴリズムであり、暗号化アルゴリズムではありません。つまり、ハッシュされたワットを取り戻すことはできず、比較することしかできません。データベースのユーザー名とパスワードではなく、ユーザー認証情報を保存するときに使用するのが理想的です。db usernameとpwdは暗号化して、最小限のことを行うために構成ファイルに保持する必要があります。