仮定のPHPアプリケーションが同じディレクトリ内のファイルにハッシュ化されたパスワードを保存するとします。最初は、名前を推測できるため、これは非常に安全ではないようです。ファイルを開き、Webブラウザー(http://example.com/php-app/hashed_passwords.txt
)。
しかし、私はこれがいくつかの異なる方法を使用して提供するセキュリティのレベルについて疑問に思っていました:
hashed_password_wefhbweifvbewuivgbwueigfvu4gf.txt
)hashed_password.secret
)、およびリクエストされたときに403を返すようにWebサーバーに指示するデータベースと比較して、これらの方法のいずれかは多かれ少なかれ安全であり、攻撃者に対して妥当なレベルのセキュリティ(データベースのそれと同等)を提供できるでしょうか?
これを行う最善の方法は、そのようなファイルをWebルートのoutsideに保存することです。
基本的に、すべての解決策は、パスワードファイルを使用不可にすることで問題を「解決」します。それらの違いは、それが壊れるのに発生する必要がある種類の構成エラーに由来します。
驚くべきことに、このような構成ミスは時々発生し(システムを更新または再インストールする場合など)、これらのソリューションは、それらに対する堅牢性が異なるだけです。また、これらの構成は.htaccessファイルで設定されることもありますが、サーバーで構成が変更され、適用されませんでした。
ファイルをWebルートの外に配置すると(_/etc/php-app/hashed_passwords.txt
_など)、悪意のある俳優によるダウンロードが困難になります。
明らかに、これらの方法のいくつかを組み合わせることを妨げるものは何もありません(ただし、ある時点ではほとんどメリットがありません)。
注:.phpルートを使用する場合、悪意のあるユーザーが生成されたファイルにコードを挿入できないようにし、コード実行の脆弱性を引き起こす必要があります。通常、これは最初に死ぬことを意味します(たとえば、<?php die(1);
でファイルを開始します)。 __ halt_compiler を使用して、ファイルの残りの部分がPHPによって解釈されないようにすることもできます。
ファイルの使用とデータベースサーバーへの接続で見られる主な違い(SQliteを使用した場合、ファイルに名前を付ける方法と同じジレンマに直面することに注意してください)は、競合状態に対する堅牢性にあります。ユーザーがパスワードの変更アクションを実行しているときに、別のユーザーがサインアップしていると仮定します。ファイルを使用する単純な実装は、ファイルを新しいパスワードハッシュで置き換えるときに最近作成されたユーザーが失われるという競合状態に対して脆弱ですが、データベースは自動的にそれを処理します(単純な実装はSQLインジェクションに対して脆弱です。ただし)。
その他の違いは、権限、バックアップ、およびスケーラビリティです。
そして明らかに、データベースサーバーを実行すると、特定のオーバーヘッドが発生します。まだ使用する必要がなく、サーバーのリソースに制約がある場合は、単純にファイルを使用することをお勧めします。
ご覧のとおり、ファイルとデータベースサーバーのどちらを使用するかを決める主な理由はセキュリティに関するものではありません。どちらの場合も同等に安全なアプリを作成できるためです。
任意の意味でデータベースはファイルです-Unixシステムでは間違いなくファイルです。しかし、なぜアクセスしたくないファイルに何かを保存したいのであれば、それをWebルートの外部に保存しないのはなぜかわかりません。これをすぐに実行すると、箇条書き1と2は役に立たなくなります(さらに、あいまいさによるセキュリティなどはありません)。
攻撃者が実行せずにファイルをダンプできる場合、箇条書き4は失敗します。番号3は、ソリューションの側面を示します。
データベースの利点の1つは、データベースを読み書きできるユーザーを完全に制御できることです。これらはある意味ではファイルのアクセス許可と同じように存在しますが、同程度の粒度ではありません。
これはすべて、データベースでのルックアップの速度など、データベースの他の利点を無視しています。 1000人のユーザーをファイルに保存すると、検索が非常に困難になります...バックアップも面倒になり、データベースと安全に対話するために必要なすべてのツールがすでに存在しています。ユーザーとパスワードをコロンで区切るとします。ユーザーがコロンを含む名前を送信するとどうなりますか?
Webルートの外に1つまたは2つのキーを含み、暗号化され(アプリケーションでハードコード化されていないキー)、データベースが利用できないルートとPHPのみが読み取り可能なファイルは、正当化でき、セキュリティポイントから問題ない可能性があります表示されますが、リストされた解決策は役に立ちません。私は、本番サービスでは決して行われませんが、そのようなものがどのように機能するかについての初期のPoCを実証しているシステムでこれを行いました。
あいまいさによるセキュリティ:テキストファイルに、推測しにくい意味のない名前を付ける(
hashed_password_wefhbweifvbewuivgbwueigfvu4gf.txt
)
これは、誰もディレクトリリストをオンにしない限り安全です。 Apache + PHPを使用している場合は、Apacheの設定が不適切な場合でも、PHPを安全にすることをお勧めします。結局のところ、神はApacheがどのように構成されてしまうのか知っています...
また、偶発的なソースコード開示のリスクがあります(3番目のポイントを参照)。
テキストファイルに特定のファイル拡張子(
hashed_password.secret
)を付け、要求されたときに403を返すようにWebサーバーに指示する
上記と同じ問題。しかし、これは改善だと思います。
PHPアプリケーションにハードコードされたキーでテキストファイルを暗号化する
少し良いが、それでも良くない。誤ったソースコードが公開されるリスクがまだあります。これは、構成の誤りまたはパブリックgitリポジトリへのコミットによって簡単に発生する可能性があります。
テキストファイルを暗号化し、暗号化キーを別の場所に保存する(代替案については この質問 を参照)ほうがはるかに優れています。
PHPファイルのコメントアウトされた部分に情報を保存し、バックエンドからのみ読み取ることができるようにする(Webブラウザーで空のファイルを返す)
上記と同じ問題に加えて、非常に深刻なコード実行の問題 Ángelが書いている 。これは絶対に避けます。
ファイルをWebルートの外に置きます!誤って提供される可能性は低くなります。うまくいけば、それはあなたのすべてのgitリポジトリからもそれを除外するでしょう(それはそれらにあるべきではありません)。
これを最初の3つの提案のいくつかの組み合わせと組み合わせることができます。フォースを使用しないでください!
番号。いいえ。
-4。ウェブサーバーの設定に特別な注意を払い、それを扱う設定ファイルに警告コメントを入れ、それを文書化してください。実際には、一部のピエロが関連する構成を誤って無効にするまで、平均時間ウィンドウが延長されます(悪名高い:インタープリターが失敗したときにソースファイルを返すフォールバック!)。
中心的な問題は、ファイルがPHPアプリにアクセスできる場合、PHPアプリを悪用するすべてのユーザーがファイルにアクセスできることです。それを回避する方法はありません。
攻撃者にとって少し難しいことは良い考えですが、対策を半分にしないでください。それをウェブルートの外に置いて、それで終わりです。どうしてでしょうか?
ほとんどの場合、データベースはファイルよりも安全です。たとえば、使用しているDBに応じて、行レベルのアクセス制御を使用できるようにすることができます。
さらに重要なのは、パスワードをどのように保存するかです。あなたがそれらを適切にハッシュして塩漬けし、そしておそらくこの答えで説明されているように少しのコショウを加えることさえできれば: パスワードハッシュ:塩+コショウを加えるか、十分な塩ですか?