2012-04-24 14 views
53

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

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

+3

プログラムがそれを読むことができるならば、あなたが望むことができる最高のものは目障りです。ファイルへのアクセス権を持つ人も誰でもできます。それはアクセスが難しい気にはならないと言っているわけではありません。 – lynks

+0

管理者の肩を覗いている人が主な脅威である場合、コードに保持されている一定のパスワードで暗号化することは正当な方法のようです。 – ZeroOne

+0

データベースには何人の人がアクセスしていますか?コアデータベースへのアクセスにパスワードを必要としませんか?なぜあなたは2番目のもの/これを保管すべきですか? –

答えて

40

enter image description here

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"... 
+12

だから、基本的にパスワードはプログラムでハードコードされていますか? – mazaneicha

+8

例の「パスワード」は、値の暗号化/復号化を実行するために使用されます。この例では、ハードコーディングされていますが、どこからでも検索することができます(環境変数など)。ただし、プレーンテキストに保存したくないプロパティ値は**暗号化**され、 'getProperty()'メソッドで読み取られると解読されます。これは基本的に卵巣の層ですが、肩のサーフィンや機密データへの一時的なアクセスに問題はありません。 –

+1

@MadsHansen情報をありがとう。私はこのプロジェクトのために使用するとは思わない(既にコードが凍結されていない...)が、次のバージョン/プロジェクトではそれを覚えているだろう。 – daramasala

9

乏しいマン妥協溶液は、単純マルチ署名アプローチを使用することです。

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

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

プライベート文字列PASS1 =「TAKqWskc4ncvKaJTyDcgAHq82」

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

のjava -jar /myapplication.jar -pass2 X7tX6GfK2fc386bmNw3muknjU

アプリケーションは、それがPASS1 +パス2を使用して起動し、データベースに接続するとき。

このソリューションには、上記の欠点を除いて多くの利点があります。

パスワードの半分を持っている開発者でない限り、コマンドライン引数にパスワードの半分を安全に置くことができます。

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

また、ソースコードは読んだらセミパブリックにすることもでき、パスワードではアプリケーションにアクセスできません。

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

+1

これは安全ではないかもしれません。コマンドラインを使用して資格情報を提供することは、OSのロギングのために一般的に推奨されません。侵入者はソースファイルを開くだけです - >パスワードの半分を読んでから、コマンドラインに 'history'と入力してください! –

7

カスタムNファクタ認証メカニズムの提供はどうですか?利用可能な方法を組み合わせる前に

、我々は次のことを行うことができますと仮定してみましょう:

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

2 .propertiesファイルで)ストア

3ファイル)ユーザーに依頼)コマンドラインから

4パスワードを入力

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

6)ネットワークを介して、

7パスワードを入力します)多くの選択肢(例えば秘密、指紋を描き、IP-特定、かくかくしかじか)

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

第二オプション:我々は暗号化された形式で.propertiesファイルにパスワードを保存することができますので、(単にjasyptのように行います)直接攻撃者からは見えません。パスワードマネージャが必要な場合は、マスターパスワードも必要になります。クラスファイル、キーストア、カーネル、別のファイル、またはメモリ内であっても、すべて賛否両論があります。
しかし、ユーザーはパスワード変更のために.propertiesファイルを編集するだけです。

3番目のオプション:コマンドラインから実行したときのパスワード。 java -jar /myprogram.jar -p sdflhjkiweHIUHIU8976hyd

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

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

第4オプション:コマンドラインではなくカスタムフォームからパスワードを入力します。これは、暴露暴露の問題を回避する。

5番目のオプション:以前の別のメディアに保存されているパスワードとしてファイルを提供してから、ハード・ファイルを削除します。これは、再び暴露暴露の問題を回避し、肩を盗まれて盗まれる可能性のあるタイピングは必要ありません。変更が必要な場合は、別のファイルを指定してから、もう一度削除してください。

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

私は最大のセキュリティを実現するために、.classファイル、プロパティファイル、ログ、ネットワークチャネル、ショルダーサーフィン、中央の人、その他のファイルにアクセスする必要があります。bla bla bla 。これは、実際のパスワードを生成するためにすべてのsub_passwords間の排他的論理和演算を使用して簡単に実装できます。

権限のないメモリ内アクセスから保護することはできませんが、アクセス制限されたハードウェア(スマートカード、HSM、SGXなど)を使用することによってのみ行うことができます。正当な所有者は解読キーまたはアルゴリズムにアクセスすることができる。また、このハードウェアも盗むことができます。鍵の抽出には攻撃者を助けるかもしれないside-channel attacksが報告されています。場合によっては、他の人を信頼する必要があります。もちろん、セキュア・エンクレーブ・クローニング(デアセンブル)が可能になると状況が悪化する可能性がありますが、実用的には数年かかるでしょう。

また、完全なキーが異なるサーバー間で分割されるキー共有ソリューションも考えられます。しかし、再構成の際に、フルキーを盗まれる可能性があります。上記の問題を緩和する唯一の方法は、secure multiparty computationです。

入力方法が何であれ、私たちはネットワークスニッフィング(MITM攻撃)やキーロガーから脆弱でないことを常に確認する必要があります。

関連する問題