web-dev-qa-db-ja.com

データベースパスワードをPerlスクリプトに入力しないようにするにはどうすればよいですか?

私のデータベースに接続し、さまざまな種類のルックアップと整合性チェックを行うcron化されたPerlスクリプトがあります。オリジナルのスクリプトはずっと前に誰かが書いたものです。私の仕事はそれにいくつかの変更を加えることです。しかし、データベースにアクセスするためにそこにハードコーディングされたusername="foo", password="bar"パラメータをじっと見たくありません。

これを行うには、より安全な方法が必要です。とりあえず、cronジョブをコメントアウトし、パスワードが含まれているスクリプトの行を削除して、これをより安全にする方法についてブレーンストーミングを開始することだけが考えられます。しかし、その間、スクリプトの処理は手動で行う必要があります。

何か案は?

23
Luke Sheppard

標準的な方法は、資格情報を構成ファイルに入れ、構成ファイルをPerlファイルよりも読みやすくしないように保護することです。これにより、セキュリティがある程度向上します。たとえば、コードがソース管理にあり、開発者がアクセスできる場合、構成ファイルはそうではありません。コードはWebサーバーのcgiルートにある必要があり、特定の設定ミスでダウンロードできる可能性があり、構成ファイルはそうである必要はありません。

野心的な方法は、資格を可逆的に暗号化し、構成ファイルに入れることです。もちろん、可逆的に暗号化されたものはすべて復号化できます。 BladeLogicアプリケーションがこれを行い、Java資格情報を復号化し、それを使用して資格情報を私の満足感に復号化するために使用するのに十分なほど、それらを逆コンパイルすることは簡単でした(<1日) 。それらに対するマークではなく、これは可逆暗号化ゲームの名前にすぎません。

もう1つのオプションは、厳密に制限されたデータベース制限と連携してOSベースの承認を使用することです。たとえば、データベースクライアントユーザーの一連のストアドプロシージャへのアクセスを制限して、悪用の可能性を制限し、そのユーザーがパスワードなしでデータベースにアクセスできるようにします。クライアントサーバーをネットワーク経由で使用している場合、これは機能しません。これにより、その有用性が制限されます。また、「パスワードなし」のOSユーザーアクセスについては、パスワードを気ままに書き留めるよりも疑問視される傾向があります。それは完全に論理的ではありませんが、すべてのデータベースユーザーがパスワードを持っている必要があると言っている標準があります。

24
gowenfawr

多くの場合、パスワードを環境変数でスクリプトに渡すので、スクリプトはパスワードを含む安全な場所にアクセスする必要がありません。

PASSWORD=`cat passwd_file`  Perl_script.pl

次に、スクリプトはパスワードを読み取ります

my $password = $ENV{'PASSWORD'}

perlスクリプトが特権を落とした場合のボーナスポイント

8
Arthur Ulfeldt

他の人がすでに言ったように、資格情報をスクリプトがロードする別のファイルに入れます。スクリプトにパスワードが含まれているリスクには、ショルダーサーフィンにさらされたり、リビジョン管理システムや構成管理システムでコミットされたり、本来あるべき範囲をはるかに超えて配布されたり、コードの一部を再利用するときに誤って別の場所にコピーしたりすることが含まれます。

資格情報ファイルには、必要最小限の権限が必要です。構成管理システムに含まれたり、別の方法で処理したりしないでください。

可能であれば、資格情報ファイルへのアクセスを許可よりも制限するオペレーティングシステム機能の使用を検討してください。たとえば、LinuxのAppArmorまたはSELinuxは、資格情報ファイルへのアクセスを、それを必要とする1つのスクリプトに制限できます。これは、正当なスクリプトを制御できない攻撃者に対してのみ保護するため、正当なスクリプトがそれを実行するユーザーによって所有されていないことを確認します(これは一般的な推奨事項です:実行可能なプログラムを実行するユーザーが所有しないようにします)。

コンセンサスは次のようです:

  1. パスワードは、バージョン管理の一部ではなく、別のファイルに保存し、スクリプトよりも厳しい権限で保護する必要があります。
  2. スクリプトはとにかくパスワードを復号化できる必要があるため、保存されたパスワードの暗号化は時間の無駄です。

しかし、その上に3つ目のコントロールを追加することを考えています。時間ベースの(時間的な)アクセスコントロールは、ここでも少し役立つかもしれません。クリアテキストのパスワードがより低い特権のユーザーに利用可能である時間を制限すると、パスワードとローカルの攻撃者との間に別の(小さいながら)アクセス制御層が追加されます。

私の考えは、rootにパスワードファイルを所有させ、 mode 04 に設定することです。そして、スクリプトを実行する特権の低いcronjobの直前に、パスワードファイルで chmod 0404 を実行するroot cronjobを用意します。指定された間隔で(できればスクリプトの実行が完了した後)、2番目のルートcronjobがパスワードファイルに対してchmod 0400を実行します。これはすべて、スクリプトがsome期間alwaysよりも短い期間だけパスワードを必要とすることを前提としています。このスキームについてのあなたの考えは?

2
Luke Sheppard

これは適切な解決策ですか?

  1. パスワードは、次のように難読化されたコンパイル済みのC/C++プログラムに格納されます。char password [100];パスワード[0] = 'a';パスワード[1] = 'b';パスワード[2] = 'c';パスワード[3] = '\ 0';

または、パスワードを難読化する他の方法。 (実行可能ファイルで「文字列」を実行してもパスワードは使用できません)

  1. C/C++プログラムは、信頼された登録済みスクリプトにのみパスワードを返します。スクリプトは変更されませんでした。

設定を~/config/appnameと私のローカルmysql(または他の)接続の一般的な構成があります。家にXアクセス許可を与えたくない場合は、別のユーザーが標準の構成フォルダーをどこかに持っているときにアプリを実行します。私はこれを行うので、誤ってパッケージ化したり、パスワードやユーザー名を他のプログラマーに提供したりしません。私はそれは大したことだとは思いませんが、私の上司はセキュリティフリークであり、特に何かをウェブに公開するときは良い習慣です。

構成ファイル用の標準​​のワンライナーまたはツーライナーを作成し、それらをコピーして、作成する新しいスクリプトに貼り付けるのが賢明です

0
user5575

これは、リモートデータベースに接続するスクリプトに対して私が計画していることです。暗号化された値とは別にキーを保存するには、2つのサーバーが必要です。

  1. サーバー2(キーが格納される場所)で、キーパラメーターを受け入れてローカルに格納するスクリプトを作成します。
  2. サーバー1(スクリプトが格納されている場所)で、接続文字列(Host、db_name、username、password)をパラメーターとして受け入れ、ランダム文字キーを生成して接続文字列を暗号化するスクリプトを作成します。暗号化された文字列をローカルに保存し、キーをハッシュしてローカルに保存してから、キーを(SSL経由で)サーバー2に送信します。このスクリプトは、実際の接続文字列を使用して手動で実行して初期化し、次のように再実行できます。 2番目のサーバーが何らかの理由で危険にさらされた場合は、キーをリセットしてください。
  3. サーバー1で、キーパラメータを受け入れるように元のスクリプトを設定し、格納されているハッシュに対してキーを検証し、キーを使用して暗号化された接続文字列を復号化します。
  4. サーバー2上キーを送信してスクリプトを実行するサーバー1(SSL経由)上のスクリプトへのcURL呼び出しを設定します。これはcronで設定できますが、実行することもできます。
0
knsheely