73

データベースに接続する Java アプリケーションがあります。
データベースのユーザー名とパスワードは、プロパティ ファイルに保存されます。
ユーザーがパスワードを変更できるオプションを保持しながら、パスワードをクリアテキストでプロパティ ファイルに格納しないようにするための一般的な方法は何ですか?
ここでの主な動機は、管理者がプロパティ ファイルを編集しているときに、誰かが管理者の肩越しにパスワードを見ないようにすることです。ここで、C# でそれを行う方法が組み込まれていること
を読みました。
Javaを知っているので、組み込みのソリューションが見つかるとは思っていませんが、他の人が何をしているのか聞きたいです.
適切な選択肢が見つからない場合は、コードに保持される一定のパスワードで暗号化することになるでしょう。しかし、私はそれが間違っていると感じるので、このようにするのは嫌いです.

編集 2012 年 12 月 12 日 魔法はないようです。パスワードをコードなどに保存する必要があります。最後に、回答の1つで言及されたJasyptと非常によく似たものを実装しました。だから私はJasyptの答えを受け入れています。それは明確な答えに最も近いからです。

4

4 に答える 4

55

ここに画像の説明を入力

Jasypt は、.properties ファイル内の暗号化された値をロード、管理、および透過的に復号化するためのorg.jasypt.properties.EncryptablePropertiesクラスを提供し、同じファイル内で暗号化された値と暗号化されていない値の両方を混在させることができます。

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"...
于 2012-04-25T00:10:58.727 に答える
13

貧乏人の妥協案の解決策は、単純化されたマルチ署名アプローチを使用することです。

たとえば、DBA はアプリケーション データベースのパスワードを 50 文字のランダムな文字列に設定します。 TAKqWskc4ncvKaJTyDcgAHq82X7tX6GfK2fc386bmNw3muknjU

彼または彼女はパスワードの半分をアプリケーション開発者に渡し、開発者はそれを Java バイナリにハード コードします。

プライベート文字列 pass1 = "TAKqWskc4ncvKaJTyDcgAHq82"

パスワードの残りの半分は、コマンド ライン引数として渡されます。DBA は pass2 をシステム サポートまたは管理者に渡します。システム サポートまたは管理者は pass2 にアプリケーションの開始時刻を入力するか、自動化されたアプリケーションの起動スクリプトに入力します。

java -jar /myapplication.jar -pass2 X7tX6GfK2fc386bmNw3muknjU

アプリケーションが起動すると、pass1 + pass2 を使用してデータベースに接続します。

このソリューションには、前述の欠点がなくても多くの利点があります。

パスワードの残りの半分を持っている開発者でない限り、パスワードを読んでもあまり役に立たないので、パスワードの半分をコマンドライン引数に安全に入れることができます。

DBA はパスワードの後半を変更することもでき、開発者はアプリケーションを再デプロイする必要はありません。

ソースコードは、それを読み取るため半公開にすることもでき、パスワードではアプリケーションへのアクセスは許可されません。

データベースが接続を受け入れる IP アドレス範囲に制限を追加することで、状況をさらに改善できます。

于 2014-10-22T06:53:34.820 に答える
10

カスタム N-Factor 認証メカニズムの提供についてはどうですか?

利用可能なメソッドを組み合わせる前に、次のことを実行できると仮定しましょう。

1) Java プログラム内のハードコード

2) .properties ファイルに保存する

3)コマンドラインからパスワードを入力するようにユーザーに依頼します

4) フォームからパスワードを入力するようにユーザーに依頼する

5) コマンドラインまたはフォームからパスワードファイルをロードするようにユーザーに依頼する

6) ネットワーク経由でパスワードを提供する

7) 多くの選択肢 (例: Draw A Secret、Fingerprint、IP 固有、bla bla bla)

第 1 のオプション:難読化を使用することで、攻撃者にとって状況をより複雑にすることができますが、これは適切な対策とは見なされません。優れたコーダーは、ファイルにアクセスできれば、それがどのように機能するかを簡単に理解できます。ユーザーごとのバイナリ (または難読化部分またはキー部分のみ) をエクスポートすることもできるため、攻撃者は別のディストリビューションではなく、このユーザー固有のファイルにアクセスできる必要があります。繰り返しますが、パスワードを変更する方法を見つける必要があります。たとえば、再コンパイルするか、リフレクションを使用してオンザフライでクラスの動作を変更します。

2 番目のオプション:パスワードを暗号化された形式で .properties ファイルに保存できるため、攻撃者から直接見ることはできません ( jasyptと同様)。パスワード マネージャーが必要な場合は、マスター パスワードも必要になります。マスター パスワードも、.class ファイル、キーストア、カーネル、別のファイル、さらにはメモリ内など、どこかに保存する必要があります。すべてに長所と短所があります。
ただし、ユーザーはパスワード変更のために .properties ファイルを編集するだけです。

3 番目のオプション:コマンド ラインから実行するときにパスワードを入力しますjava -jar /myprogram.jar -p sdflhjkiweHIUHIU8976hyd

これにより、パスワードを保存する必要がなくなり、メモリに残ります。ただし、historyここではコマンドと OS ログが最大の敵になる可能性があります。オンザフライでパスワードを変更するには、いくつかのメソッドを実装する必要があります (コンソール入力、RMI、ソケット、REST bla bla bla をリッスンするなど) が、パスワードは常にメモリに残ります。

必要な場合にのみ一時的に復号化することもできます->復号化されたものを削除しますが、暗号化されたパスワードは常にメモリに保持します。残念ながら、前述の方法では不正なメモリ内アクセスに対するセキュリティは向上しません。これを達成した人は、使用されているアルゴリズム、salt、およびその他の秘密にアクセスできる可能性があるためです。

4 番目のオプション:コマンド ラインではなく、カスタム フォームからパスワードを指定します。これにより、ログの公開の問題を回避できます。

5 番目のオプション:別のメディアに以前に保存されたパスワードとしてファイルを提供します -> 次に、ファイルを完全に削除します。これにより、ログの露出の問題が回避され、さらに、ショルダー サーフィンを盗まれる可能性のあるタイピングが不要になります。変更が必要な場合は、別のファイルを提供してから、再度削除してください。

6 番目のオプション:再びショルダー サーフィンを回避するために、RMI メソッド呼び出しを実装して、別のデバイス (たとえば携帯電話) から (暗号化されたチャネルを介して) パスワードを提供することができます。ただし、ネットワーク チャネルと他のデバイスへのアクセスを保護する必要があります。

上記の方法の組み合わせを選択して最大限のセキュリティを実現すると、.class ファイル、プロパティ ファイル、ログ、ネットワーク チャネル、ショルダー サーフィン、man in the middle、その他のファイル bla bla bla にアクセスする必要があります。これは、実際のパスワードを生成するために、すべての sub_passwords 間の XOR 演算を使用して簡単に実装できます。

ただし、不正なインメモリ アクセスから保護することはできません。これは、アクセスが制限されたハードウェア (スマートカード、HSM、SGX など) を使用することによってのみ実現できます。復号化キーまたはアルゴリズムにアクセスできます。繰り返しになりますが、このハードウェアも盗むことができます。サイドチャネル攻撃が報告されており、攻撃者がキーを抽出するのに役立つ可能性があり、場合によっては別のパーティを信頼する必要があります (たとえば、SGX では Intel を信頼します)。もちろん、セキュア エンクレーブ クローニング (分解) が可能になると状況は悪化する可能性がありますが、これが実用化されるまでには数年かかると思います。

また、完全なキーが異なるサーバー間で分割されるキー共有ソリューションを検討することもできます。ただし、再構築すると、完全なキーが盗まれる可能性があります。前述の問題を軽減する唯一の方法は、安全なマルチパーティ計算です。

入力方法が何であれ、ネットワーク スニッフィング (MITM 攻撃) やキーロガーから脆弱にならないようにする必要があることを常に心に留めておく必要があります。

于 2015-12-21T12:28:53.797 に答える