データベースに接続するJavaアプリケーションがあります。
データベースのユーザー名とパスワードは、プロパティファイルに保存されます。
パスワードをクリアテキストでプロパティファイルに保存せずに、ユーザーに変更を許可するオプションを保持する一般的な方法は何ですか?
ここでの主な動機は、管理者がプロパティファイルを編集している間、誰かが管理者の肩越しに見てパスワードを見るのを防ぐことです。
「 here 」と読みます。C#でそれを行うための組み込みの方法があります。
Javaを知っているので、組み込みのソリューションを見つけることは期待できませんが、他の人が何をしているかを聞きたいです。
適切な選択肢が見つからない場合は、コードに保持される一定のパスワードで暗号化することになるでしょう。しかし、私はそれが間違っていると感じるので、このようにするのは嫌です。
2012年12月12日編集魔法はないようで、パスワードをコードなどに保存する必要があります。最後に、回答の1つで言及されたJasyptと非常によく似たものを実装しました。だから私はJasyptの答えを受け入れています。それは明確な答えに最も近いからです。
Jasyptは、 org.jasypt.properties.EncryptableProperties .propertiesファイル内の暗号化された値をロード、管理、透過的に復号化するクラスを提供し、暗号化されたものとそうでないものの両方を混在させることができます-同じファイル内の暗号化された値。
http://www.jasypt.org/encrypting-configuration.html
Org.jasypt.properties.EncryptablePropertiesオブジェクトを使用することにより、アプリケーションは次のように.propertiesファイルを正しく読み取って使用できるようになります。
datasource.driver=com.mysql.jdbc.Driver
datasource.url=jdbc:mysql://localhost/reportsdb
datasource.username=reportsUser
datasource.password=ENC(G6N718UuyPE5bHyWKyuLQSm02auQPUtm)
データベースのパスワードは暗号化されていることに注意してください(実際、データベースの構成に関連するかどうかに関係なく、他のプロパティも暗号化できます)。
この値をどのように読みますか?このような:
/*
* First, create (or ask some other component for) the adequate encryptor for
* decrypting the values in our .properties file.
*/
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setPassword("jasypt"); // could be got from web, env variable...
/*
* Create our EncryptableProperties object and load it the usual way.
*/
Properties props = new EncryptableProperties(encryptor);
props.load(new FileInputStream("/path/to/my/configuration.properties"));
/*
* To get a non-encrypted value, we just get it with getProperty...
*/
String datasourceUsername = props.getProperty("datasource.username");
/*
* ...and to get an encrypted value, we do exactly the same. Decryption will
* be transparently performed behind the scenes.
*/
String datasourcePassword = props.getProperty("datasource.password");
// From now on, datasourcePassword equals "reports_passwd"...
貧乏人の妥協の解決策は、単純なマルチ署名アプローチを使用することです。
たとえば、DBAはアプリケーションデータベースのパスワードを50文字のランダムな文字列に設定します。 TAKqWskc4ncvKaJTyDcgAHq82X7tX6GfK2fc386bmNw3muknj
彼または彼女はパスワードの半分をアプリケーション開発者に渡し、アプリケーション開発者はそれをJavaバイナリにハードコーディングします。
プライベート文字列pass1 = "TAKqWskc4ncvKaJTyDcgAHq82"
パスワードの残りの半分は、コマンドライン引数として渡されます。 DBAはシステムサポートまたは管理者にpass2を提供し、管理者はアプリケーションの開始時間を入力するか、自動化されたアプリケーションの起動スクリプトに入力します。
Java -jar /myapplication.jar -pass2 X7tX6GfK2fc386bmNw3muknjU
アプリケーションが起動すると、pass1 + pass2を使用してデータベースに接続します。
このソリューションには、前述の欠点がなく、多くの利点があります。
パスワードの残り半分を持っている開発者でない限り、それを読むことはあまり役に立ちませんので、コマンドライン引数にパスワードの半分を安全に入れることができます。
DBAは引き続きパスワードの後半を変更でき、開発者はアプリケーションを再デプロイする必要がありません。
また、ソースコードは読み取り専用であり、パスワードによってアプリケーションにアクセスできなくなります。
データベースが接続を許可するIPアドレス範囲に制限を追加することにより、状況をさらに改善できます。
カスタムN-Factor認証メカニズムの提供についてはどうですか?
利用可能なメソッドを組み合わせる前に、次のことを実行できると仮定しましょう。
1)Javaプログラム内のハードコード
2).propertiesファイルに保存する
3)ユーザーにコマンドラインからパスワードを入力するように依頼する
4)ユーザーにフォームからパスワードを入力してもらう
5)ユーザーにコマンドラインまたはフォームからパスワードファイルをロードするように依頼します
6)ネットワーク経由でパスワードを提供します
7)多くの選択肢(例:秘密の描画、指紋、IP固有、bla bla bla)
1番目のオプション:難読化を使用することにより、攻撃者にとって事態をより複雑にすることができますが、これは良い対策とは見なされません。優れたコーダーは、ファイルにアクセスできる場合、その仕組みを簡単に理解できます。ユーザーごとのバイナリ(または難読化部分またはキー部分のみ)をエクスポートすることもできるため、攻撃者は別のディストリビューションではなく、このユーザー固有のファイルにアクセスする必要があります。繰り返しますが、パスワードを変更する方法を見つける必要があります。たとえば、再コンパイルするか、リフレクションを使用してクラスの動作をオンザフライで変更します。
2番目のオプション:.propertiesファイルにパスワードを暗号化された形式で保存できるため、攻撃者から直接見えません(ちょうど jasypt はありません)。パスワードマネージャーが必要な場合は、マスターパスワードも必要になります。マスターパスワードも.classファイル、キーストア、カーネル、別のファイル、またはメモリ内のどこかに保存する必要があります。すべて長所と短所があります。
しかし、ユーザーはパスワード変更のために.propertiesファイルを編集するだけです。
3番目のオプション:コマンドラインから実行するときにパスワードを入力します。 Java -jar /myprogram.jar -p sdflhjkiweHIUHIU8976hyd
。
パスワードを保存する必要はなく、メモリ内に残ります。ただし、history
コマンドとOSログは、ここでの最悪の敵かもしれません。その場でパスワードを変更するには、いくつかのメソッド(コンソール入力、RMI、ソケット、REST bla bla blaをリッスンする)を実装する必要がありますが、パスワードは常にメモリに残ります。
必要な場合にのみ一時的に復号化することもできます->その後、復号化されたものを削除しますが、暗号化されたパスワードは常にメモリに保持します。残念ながら、前述の方法では、不正なメモリ内アクセスに対するセキュリティは向上しません。これを達成した人は、アルゴリズム、ソルト、および使用されているその他のシークレットにアクセスできる可能性が高いからです。
4番目のオプション:コマンドラインではなく、カスタムフォームからパスワードを提供します。これにより、ログの露出の問題を回避できます。
5番目のオプション:以前に別のメディアに保存されたパスワードとしてファイルを提供する->次にファイルを完全に削除する。これにより、ロギングの露出の問題が回避されます。また、ショルダーサーフィンが盗まれる可能性のあるタイピングは不要です。変更が必要な場合は、別のファイルを指定してから再度削除してください。
6番目のオプション:ショルダーサーフィンを回避するには、RMIメソッド呼び出しを実装して、別のデバイスから(暗号化されたチャネルを介して)パスワードを提供します。例:携帯電話経由。ただし、ネットワークチャネルと他のデバイスへのアクセスを保護する必要があります。
上記の方法を組み合わせて最大限のセキュリティを実現するため、.classファイル、プロパティファイル、ログ、ネットワークチャネル、ショルダーサーフィン、中間者、その他のファイルにアクセスする必要があります。これは、すべてのsub_password間のXOR操作を使用して簡単に実装し、実際のパスワードを生成できます。
ただし、不正なメモリ内アクセスから保護することはできません。これは、アクセス制限されたハードウェア(スマートカード、HSM、SGXなど)を使用することによってのみ実現できます。復号化キーまたはアルゴリズムにアクセスできる。繰り返しになりますが、このハードウェアも盗むことができると報告されています サイドチャネル攻撃 これは攻撃者がキーを抽出するのに役立ち、場合によっては他のパーティを信頼する必要があります(たとえば、SGXではIntelを信頼します)。もちろん、セキュアエンクレーブクローニング(逆アセンブル)が可能になると状況は悪化する可能性がありますが、実用化するには数年かかると思います。
また、完全なキーが異なるサーバー間で分割されるキー共有ソリューションを検討することもできます。ただし、再構築すると、完全なキーが盗まれる可能性があります。前述の問題を軽減する唯一の方法は、 セキュアなマルチパーティ計算 です。
入力方法が何であれ、ネットワークスニッフィング(MITM攻撃)やキーロガーから脆弱でないことを確認する必要があることに常に留意する必要があります。
実際には、これは 設定ファイルのパスワードを暗号化しますか? の複製です。
私がこれまでに見つけた最良の解決策は、この回答にあります: https://stackoverflow.com/a/1133815/1549977
長所:パスワードは文字列ではなく、文字配列で保存されます。それはまだ良くありませんが、何よりも優れています。