PHPでデータベースパスワードを保護する方法


404

PHPアプリケーションがデータベース接続を確立するときは、もちろんログインとパスワードを渡す必要があります。アプリケーションに単一の最小権限のログインを使用している場合、PHPはそのログインとパスワードをどこかに知っている必要があります。そのパスワードを保護する最良の方法は何ですか?PHPコードでそれを書くだけでは良い考えではないようです。


1
完全に安全にするには、ssl接続を設定する必要があります。そうしないと、ネットワーク上の誰もが入力したパスワードを盗聴する可能性があります。
Charles Ma

1
接続文字列で使用されるユーザーパスワードまたはデータベースパスワードですか?
Ozgur Ozcitak

4
接続文字列で使用されるデータベースパスワード。ありがとう!
user18359 2008

回答:


238

何人かの人々はこれをデータベースにパスワードを保存する方法についての質問と誤解しています。それは間違いです。それはあなたが得ることができますパスワード保存方法についてですデータベースを。

通常の解決策は、パスワードをソースコードから構成ファイルに移動することです。次に、管理とその構成ファイルの保護をシステム管理者に任せます。そうすれば、開発者は本番パスワードについて何も知る必要がなく、ソース管理にパスワードの記録がありません。


8
ありがとう。私がこれを正しく理解している場合、phpファイルには構成ファイルへのインクルードがあり、パスワードを使用できるようになります。たとえば、ログイン、pword、およびdb名を格納する「app1_db_cfg.php」というファイルを作成します。次に、私のapplication.phpページに「app1_db_cfg.php」が含まれており、私は仕事中です!
user18359 2008

28
構成を適切に保護する必要があることに同意します。ただし、その方法を知ることは、開発者ではなくシステム管理者の仕事です。この場合の強力な暗号化の価値については同意しません。構成ファイルを保護できない場合、キーを保護できると思われる理由は何ですか?
user11318 '09 / 09/21

10
私は、Webサーバーからのデータベースへのアクセスのみが許可されているデータベースアカウントを使用することを好みます。そして、構成を暗号化する手間を省き、Webルートの外に格納するだけです。
gnud

11
私はapache環境変数を使用してパスを設定しているため、ファイルへのパスもソースコードでは不明です。これにより、サーバー上のApacheの設定に基づいて、開発用と本番用に異なるパスワードを設定することもできます
geedew

15
Webアクセス可能なディレクトリの外部に保存されているファイルであっても、それらを使用するスクリプトで読み取る必要があることに注意してください。誰かがそのファイルをインクルードすると、そのファイルからデータがダンプされ、パスワードが表示されます。
リックマックギリス14年

104

他の誰かのサーバーをホストしていて、webrootの外にアクセスできない場合は、いつでもパスワードやデータベース接続をファイルに入れ、.htaccessを使用してファイルをロックできます。

<files mypasswdfile>
order allow,deny
deny from all
</files>

3
ありがとう、それがまさに私が探していたものでした。
デビッドグラッドフェルター2009

28
もちろん、誰かがシェルアクセスを持っている場合は、とにかくあなたのアカウント全体が侵害されています。
kellen

4
資格情報を誤ってリポジトリにコミットする可能性があるため、これは悪い習慣です。
Porlune 2016年

2
@Ankit:フレンドリでないユーザーがファイルをサーバーにアップロードして実行できる場合は、サーバーが適切に構成されていません。
kellen

6
@Porlune:開発者はバージョンコントロールシステムにパスワードファイルを無視させる、つまり.gitignoreを使用する必要があります。しかし、はい、機密データを含むファイルには注意が必要です。
kellen 2016年

45

最も安全な方法は、PHPコードで情報を指定しないことです。

Apacheを使用している場合は、httpd.confまたは仮想ホストファイルファイルに接続の詳細を設定することを意味します。その場合、パラメーターなしでmysql_connect()を呼び出すことができます。これは、PHPが情報を出力することは決してないことを意味します。

これは、これらのファイルでこれらの値を指定する方法です。

php_value mysql.default.user      myusername
php_value mysql.default.password  mypassword
php_value mysql.default.host      server

次に、mysql接続を次のように開きます。

<?php
$db = mysqli_connect();

またはこのように:

<?php
$db = mysqli_connect(ini_get("mysql.default.user"),
                     ini_get("mysql.default.password"),
                     ini_get("mysql.default.host"));

1
ini_get( 'default values')php.net/manual/en/class.mysqli.php
Val

4
はい。ただし、すべてのユーザー(またはハッカーが不適切に記述されたphpスクリプトを悪用しているユーザー)は、を介してパスワードを読み取ることができますini_get()
Marki555 2016年

1
@ Marki555これにbut any user (or a hacker abusing badly written php script) can read the password via ini_get()どう対処するの?
tonix、2016年

2
Marki555は、PHPコードを実行できる攻撃者がPHP関数を呼び出すこともできると言っていますが、これは明らかに真実であり、何かを行うことは不可能です。また、私が自分でこの回答で与えたアドバイスに従うのではなく、環境変数を使用することも付け加えておきます。コンセプトは似ていますが、コードに資格情報を保存しないでください。ini_get()またはを使用しても問題はありませんgetenv()
LarsNyström2016年

2
@DeepBlue ini_get()を注入できる場合は、file_get_contents(anypath)も注入できます。phpにパスワードを取得する方法がある限り、悪意のあるコードも同様です。
varesa

40

それらをWebルート外のファイルに保存します。


29
また、他の場所で言及されているように、ソース管理の外部にあります。
フランクファーマー

6
それを含めることができますか?たとえば、PHPでそれを行うことができますinclude('../otherDirectory/configfile.conf')か?
mtk 2013年

1
資格情報をwwwroot以外に保存することをお勧めします。わかりました、セキュリティの背景を理解しました。しかし、それをどのようにバージョン管理に保存する必要がありますか(サンプル構成)?通常、wwwrootはgit repoのルートであるため、外部に何かがある場合、VCの外部になります。新しい開発者が開発用のローカルインスタンスをセットアップしようとしているところを想像してみてください。「このファイルを取り出し、外部にコピーして入力する」などの魔法をどのようにして知っているのでしょうか。
ゴッドファーザー

@TheGodfatherアイデアは、新しい開発者は自分の開発環境に対して独自の資格を持つ必要があるということです。しかし、実際のデータではなく構成方法を示すコード内の指示またはコメントを含むreadmeを用意することをお勧めします。
PhoneixS

@ TheGodfather、readmeファイル?
パセリエ

35

非常に安全なシステムでは、データベースパスワードを構成ファイルで暗号化します(構成ファイル自体はシステム管理者によって保護されています)。アプリケーション/サーバーの起動時に、アプリケーションはシステム管理者に復号化キーを要求します。その後、データベースのパスワードが構成ファイルから読み取られ、復号化されて、将来使用するためにメモリに格納されます。復号化されたメモリに保存されるため、100%安全ではありませんが、ある時点で「十分に安全」と呼ぶ必要があります。


85
管理者が死亡した場合はどうなりますか?
Radu Murzea 2013年

36
ばかげている@RaduMurzea。システム管理者が亡くなるのをいつ聞いたのですか?彼らはマクドナルドのようで、どこからともなく現れたり消えたりします!
ILikeTacos

13
@Radu Murzea 2人以上の管理者がいるだけで、RAIDアレイのようなパリティが得られます。一度に複数のドライブが故障する可能性ははるかに低くなります。
element11

5
サーバーが再起動したときはどうですか?管理者をウェイクアップしてパスワードを入力させるのにかかる時間はどうですか。笑
ジョン・ハント

1
「メモリに保存」の意味がわからない。PHP Webアプリは通常、ページを表示する個々の要求に応答するのにかかる時間よりも長い間、何もメモリに保存しません。
bdsl 2017

15

このソリューションは一般的であり、オープンソースアプリケーションとクローズドソースアプリケーションの両方に役立ちます。

  1. アプリケーションのOSユーザーを作成します。http://en.wikipedia.org/wiki/Principle_of_least_privilegeを参照してください
  2. パスワードを使用して、そのユーザーの(非セッション)OS環境変数を作成します
  3. そのユーザーとしてアプリケーションを実行します

利点:

  1. 誤ってソース管理にパスワードをチェックインすることはできません。
  2. 誤ってファイルのアクセス許可を台無しにすることはありません。まあ、そうかもしれませんが、これは影響しません。
  3. rootまたはそのユーザーのみが読み取ることができます。ルートはとにかくすべてのファイルと暗号化キーを読み取ることができます。
  4. 暗号化を使用する場合、どのようにキーを安全に保存しますか?
  5. X-プラットフォームで動作
  6. envvarを信頼できない子プロセスに渡さないようにしてください

この方法は、非常に成功しているHerokuによって提案されています。


11

資格情報が格納されているのと同じファイルにデータベース接続を作成できる場合。接続ステートメントに資格情報をインライン化します。

mysql_connect("localhost", "me", "mypass");

それ以外の場合は、connectステートメントの後に資格情報を設定解除するのが最善です。メモリにない資格情報はメモリから読み取ることができないためです;)

include("/outside-webroot/db_settings.php");  
mysql_connect("localhost", $db_user, $db_pass);  
unset ($db_user, $db_pass);  

9
誰かがメモリにアクセスできる場合は、とにかくねじ込まれています。これは無意味な偽のセキュリティです。安全なオプションは、ウェブルートの外(または、ウェブルートより上のアクセス権がない場合は少なくとも.htaccessで保護されている)です。
公証人2012

2
@uliwitness-誰かがアセチレントーチでネットワークオペレーションセンターのロックを突破できるからといって、ドアも偽のセキュリティであると言っているようなものです。機密情報を可能な限り狭い範囲にバインドすることは常に理にかなっています。
ルークA.レーバー2017年

1
$ db_userをエコーするか、$ db_passを出力しますか?同じチームの開発者でさえ、プロダクションの資格情報を理解することはできません。コードには、ログイン情報について印刷可能なものは何も含めないでください。
Mohammed Joraid 2017年

8

データベースにアクセスするためにパスワードが必要であると言うように、選択肢は制限されています。一般的なアプローチの1つは、ユーザー名とパスワードをメインスクリプトではなく、別の構成ファイルに保存することです。次に、それをメインのWebツリーの外に保存してください。これは、phpファイルが実行されるのではなく単にテキストとして表示されるWeb構成の問題がある場合に、パスワードを公開していないためです。

それ以外は、使用されているアカウントへの最小限のアクセス権で正しい方向に進んでいます。それに追加

  • 他のものにユーザー名/パスワードの組み合わせを使用しないでください
  • そのユーザーのWebホストからの接続のみを受け入れるようにデータベースサーバーを構成します(DBが同じマシン上にある場合はlocalhostの方が適しています)。これにより、資格情報が公開されている場合でも、他のアクセス権がない限り誰も使用できません。機械。
  • パスワードを難読化すると(ROT13でも可能です)、一部のユーザーがファイルにアクセスしても防御力は高くありませんが、少なくともそれが偶然に表示されることはありません。

ピーター



8

以前は、構成ファイルにDBユーザー/パスを格納していましたが、それ以降は偏執狂モードに陥っています-多層防御のポリシーを採用しています

アプリケーションが侵害された場合、ユーザーは設定ファイルへの読み取りアクセス権を持つため、クラッカーがこの情報を読み取る可能性があります。設定ファイルは、バージョン管理に巻き込まれたり、サーバー間でコピーされたりする可能性もあります。

Apache VirtualHostで設定された環境変数にユーザー/パスを保存するように切り替えました。この設定はrootだけが読み取ることができます-うまくいけば、Apacheユーザーはrootとして実行されていません。

これとの欠点は、パスワードがグローバルPHP変数にあることです。

このリスクを軽減するために、次の予防策があります。

  • パスワードは暗号化されています。PDOクラスを拡張して、パスワードを復号化するロジックを含めます。誰かが接続を確立する場所でコードを読んだ場合、接続がパスワード自体ではなく暗号化されたパスワードで確立されていることは明らかではありません。
  • 暗号化されたパスワードは、グローバル変数からプライベート変数に移動されます。アプリケーションはこれをすぐに実行して、グローバルスペースで値を使用できるウィンドウを縮小します。
  • phpinfo()無効になっています。PHPInfoは、環境変数を含むすべての概要を取得するための簡単なターゲットです。

6

データベースのパスワードをファイルに入れ、ファイルを提供するユーザーに対して読み取り専用にします。

PHPサーバープロセスにデータベースへのアクセスのみを許可する手段がない場合を除き、これでほぼすべてのことを実行できます。


5

ブラウザからのパスワードではなく、データベースのパスワードについて話している場合、標準的な方法は、データベースのパスワードをサーバー上のPHP構成ファイルに配置することです。

パスワードを含むphpファイルに適切な権限があることを確認する必要があるだけです。つまり、Webサーバーとユーザーアカウントのみが読み取り可能である必要があります。


1
残念ながら、PHP設定ファイルはphpinfo()で読み取ることができ、誰かが偶然にテストスクリプトを置いてしまった場合、幸運な攻撃者がパスワードを読み取ることができます。代わりに、接続パスワードをWebサーバーのルート外のファイルに残すことをお勧めします。その後、それにアクセスする唯一の方法は、シェルを使用するか、任意のコードを実行することですが、そのシナリオでは、とにかくすべてのセキュリティが失われます。
MarioVilas 14

5

どこかにそれを設定ファイルに入れるだけで、通常行われます。次のことを確認してください。

  1. ネットワーク外のサーバーからのデータベースアクセスを禁止します。
  2. ユーザーに誤ってパスワードを表示しないように注意してください(エラーメッセージで、またはPHPファイルが誤ってHTMLとして提供されているなど)。

5

このようにして解決しました:

  1. サーバーでmemcacheを使用し、他のパスワードサーバーからの接続を開きます。
  2. memcacheにパスワード(または暗号化されたすべてのpassword.phpファイル)と復号化キーを保存します。
  3. Webサイトは、パスワードファイルパスフレーズを保持するmemcacheキーを呼び出し、メモリ内のすべてのパスワードを復号化します。
  4. パスワードサーバーは、5分ごとに新しい暗号化パスワードファイルを送信します。
  5. プロジェクトで暗号化されたpassword.phpを使用している場合は、監査を行い、このファイルが外部から変更されたか、または表示されたかどうかを確認します。これが発生した場合、メモリを自動的にクリーンアップし、アクセスのためにサーバーを閉じることができます。

4

追加のトリックは、次のようなPHPの別の構成ファイルを使用することです。

<?php exit() ?>

[...]

Plain text data including password

これにより、アクセスルールを正しく設定できます。ただし、Webサイトがハッキングされた場合、「require」または「include」は最初の行でスクリプトを終了するだけなので、データを取得するのはさらに困難です。

それでも、Web経由でアクセスできるディレクトリに設定ファイルを置かないでください。コントローラーコード、css、画像、jsを含む「Web」フォルダーが必要です。それで全部です。それ以外のものはオフラインフォルダに入ります。


しかし、phpスクリプトはどのようにしてファイルに保存されている資格情報を読み取るのでしょうか。
Christopher Mahan、

3
通常のテキストファイルと同じように、fopen()を使用します。
e-satis

2
@電子SatisでOK、それはやってハッカーを防ぐことができますrequire/ includeしかし、どのように行うことを防ぐためにfopen
dmnc 2013年

「これにより、アクセスルールを適切に設定できなくなることはありません」
e-satis 2013年

@ e-satis、これはかなり賢いです。なぜ誰もそれを考えなかったのだろうか。 ただし、それでもエディタのコピーの問題に対して脆弱です。feross.org/cmsploit
Pacerier

4

最善の方法は、パスワードをまったく保存しないことです。
たとえば、WindowsシステムでSQL Serverに接続している場合、統合認証を使用すると、現在のプロセスのIDを使用して、パスワードなしでデータベースに接続できます。

パスワード、最初に接続する必要がある場合は暗号化して、(たとえば、AES-256を使用して、暗号化キーを保護する、または証明書を保護するOSを非対称暗号化を使用して持っている)強力な暗号化を使用して、その後、Aに保管し強力なACLを含む構成ファイル(Webディレクトリ外)。


3
パスワードを再度暗号化しても意味がありません。暗号化されていないパスワードを入手できる人物は、パスワードを復号化するために必要なパスフレーズを入手することもできます。ただし、ACLと.htaccessを使用することをお勧めします。
公証人2012

2
@uliwitness誤解されていると思います-「encrypt again」とはどういう意味ですか?暗号化は1つだけです。また、パスフレーズ(人間が使用することを目的としたもの)を使用して暗号化するのではなく、ファイルシステムにアクセスするだけではキーへのアクセスが許可されないような、OSで保護された強力なキー管理が必要です。
AviD 2012

3
暗号化は魔法ではありません-ACLでAESキーを保護する代わりに、パスワードをそこに格納するだけで済みます。AESキーまたは復号化されたパスワードへのアクセスに違いはありません。このコンテキストでの暗号化は単なる蛇の油です。
MarioVilas 14

@MarioVilasえ?OSで保護された暗号化キーを使用してパスワードが暗号化されている場合、違いは何ですか?暗号化は魔法ではありません。すべての機密性を小さな暗号化キーに圧縮するだけです。スネークオイルはほとんどありません。このコンテキストでは、すべての秘密をOSに移動しているだけです。
AviD 2014

6
@AviD OSはなぜキーを保護できるが、データ自体は保護できないのですか?回答:両方を保護できるため、暗号化は実際には役立ちません。データのみが保存され、暗号化キーが、たとえば、ユーザーが入力する必要のあるパスワードから派生した場合は異なります。
MarioVilas 2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.