web-dev-qa-db-ja.com

PHP-小さなアプリケーションのパスワードを暗号化/ハッシュするのに助けが必要

仕事用の小さなスクリプトを作成しました。これは内部Webスクリプトですが、パブリックドメインでホストする必要があるため、非常に小さなPHPベースのログインシステムをログインフォームとセッションチェックを使用して作成しました。パスワードを定義する代わりにプレーンテキストで、データベースや外部ファイルを使用せずに、暗号化された形式でパスワードを追加する方法を誰かに教えてもらえますか?

私のログインコードは一番下に投稿されています-そのすぐ上に、このパスワードをある種の暗号化に変更して、誰かがファイルにアクセスした場合にプレーンテキストを読み取れないようにするか、PHP失敗し、プレーンテキストで印刷を開始します。すべてのDBと外部のconfファイルに関連するすべてのSEを検索して検索しました。

$ logins = array( 'username' => 'password123');

    <?php session_start();

if(isset($_POST['Submit'])){
$logins = array('username' => 'password123');


$Username = isset($_POST['Username']) ? $_POST['Username'] : '';
$Password = isset($_POST['Password']) ? $_POST['Password'] : '';


if (isset($logins[$Username]) && $logins[$Username] == $Password){


$_SESSION['UserData']['Username']=$logins[$Username];
  if (isset($_SESSION["login_redirect"])) {
        header("Location: " . $_SESSION["login_redirect"]);
        unset($_SESSION["login_redirect"]);
    } else {
        header("Location: index.php");
    }
exit;
} else {

/* Login failed display message */
$msg="<span style='color:red'>Invalid Login Details</span>";
}
}

助けてくれてありがとう!

pSスクリプトは、PHP 7xおよびApacheでHTTPSおよびHTTP2からホスト/提供されます。違いがある場合に備えて。

編集:

まず、ユーザーとパスワードは1つだけです。将来、ユーザーが増える可能性があります。しかし現状では、スタッフに必要なのは1つだけです。現時点では、ユーザーのアクションなどをログに記録する必要はありません。

スクリプトは、サブディレクトリも保護する独自のWAFを持っているパブリックWebサイトのサブドメイン上にあるため、ブルートフォースなどのものがピックアップされます。サーバーにもMod SecurityとCSFがあり、これも役立ちます。

会社は内部のイントラネット、VPN、LDAP/ADサーバーなどを利用していないため、スクリプトはパブリックサイドでホストされています。上司が自宅やスターバックスで作業する場合は、オフィス外からもスクリプトにアクセスできる必要があります。 。

パスワード部分はlogin.phpファイル内にプレーンテキストで保存されているので、保護したいだけです。誰かがサーバーまたはFTPなどを介してそれにアクセスした場合、彼らはパスワードに簡単にアクセスできます。そして、前述のようにPHP breakする必要があります。パスワードも画面にプレーンテキストとして表示したくないので、.

だから私の質問を少し更新します。代わりに、パスワードをハッシュ化されたパスワードシステムに置き換えるための指針を誰かに教えてもらえますか?

繰り返しますが、ここにいる多くの人々が企業イントラネット、VPN、専用プラットフォームなどを使用することを提案することを理解しています。これは小さな会社であり、さらに小さなプロジェクトであることを理解してください。スタッフがパスワードを漏らすようなことはそれほど心配ではありません。既に設定されているパスワードを保護し、スクリプトをできるだけ小さく軽量に保つことに、もっと興味があります。

2
Greg

いくつかのポイント:

  • パスワードは暗号化するのではなく、ハッシュ化する必要があります。暗号化は元に戻すことができます。アクセスすべきではないが、アプリのソースコードを見ることができる誰かが、暗号化されたパスワードとその暗号化キーを見つけ、パスワードを復号化して、アクセス権を得ることができます。ハッシュは一方向です。ハッシュダイジェストをハッシュされたテキストに戻すことはできません。
    • 高速なハッシュはブルートである可能性があるため、理想的には遅いハッシュ関数(セキュリティを向上させるためにPBKDF2、bcrypt、scrypt、またはargon2)が必要です。最新のハードウェアで簡単に強制できます。
    • ソルトハッシュを使用することをお勧めします(上記のアルゴリズムはソルトを予期または自動生成します)。そうしないと、攻撃者がRainbowテーブル(または単にGoogleハッシュダイジェスト)を使用してパスワードをすばやく見つけることができます。
  • あなたが説明するシステムは非常に壊れやすいです。このシステムのすべてのユーザーが1つのパスワードを共有すると、それが漏洩します。誰かが会社を辞めるか、危険にさらされたシステムからサインインするか、付箋に残しておくべきではない場所に置くか、安全でない通信チャネルなどで送信します。 つまり、求めていることを実行するための非常に安全な方法はありません。ユーザーごとのアクセス制御が必要です。そうです、それはおそらくデータベースを意味します。
    • ユーザーを区別しないと、意味のあるロギング機能も失われます。誰かがシステムに侵入して悪用した場合、すべてのログインは同じように見えるため、誰がそれをしたのかわかりません。もちろん、上記のスニペットでは、ロギングはまったくありません...
  • パスワードの総当たり攻撃に対する保護については言及していません。これがないと、外部の攻撃者はおそらく最悪の場合、数日間の試行でパスワードを解読できます。

シナリオを処理する正しい方法がありますが、それらはすべて、説明している方法とは異なる働きをします。

  1. 内部サイトをイントラネット(企業ネットワーク)のIPアドレスに制限し、外部ユーザーがVPNに接続していることを要求します。
  2. 認証を内部ログイン認証局に委任します。 LDAP/Active Directoryサーバーがある場合は、認証要求をそこに渡すことができます。実際、Active DirectoryとIIS(おそらくPHPからではないが)を使用している場合)は、「Windows認証」を要求するようにアプリを設定するのと同じくらい簡単です。
  3. 認証を外部プロバイダーに委任します(使用する場合)。たとえば、会社でGoogle Suiteを使用している場合は、Google SSO(シングルサインオン)を使用して、ユーザーが会社のメールアドレスを持っていることを確認できます。 Auth0などの外部認証プロバイダーを使用することもできます。
  4. あなたのパブリックドメインでホストされる必要がない必要がないことを保証しますが、理由を知らないため、より良いアプローチを提供できません。それでも、このシナリオはまさにイントラネットサーバーが存在する目的であり、必要に応じてバックエンドチャネルを介して(またはクライアント経由のCORSを介して)パブリックWebサーバーと通信できます。

より一般的には、これを尋ねているという事実は、おそらく独自の認証システムを導入しようとすべきではないことを示しています。シナリオの詳細を知らなければ、リスクとは正確には言えませんが、このようなシステムでそれらすべてを説明できれば、私は非常に驚きます。セキュリティは難しいです。自分が何をしているかを知っている人々によって開発された実績のあるシステムを使用する方がはるかに良い考えです。

3
CBHacking

たくさんのセキュリティ担当者に、どの程度のセキュリティが必要か尋ねてください。そうすれば、「たくさん」と言われます。

はい、パスワードをクリアテキストで保持することはお勧めできません。プログラムでパスワードをハードコーディングしておくことはお勧めできません。

@FutureSecurityが言うように、PHPには便利な関数password_hashがあります。これは、パスワードの扱いの複雑さをすべて抽象化します(sha1()またはmd5( )、 塩を追加 および 他のものも )にする必要があります。

しかし、ここで何をしたいですか?より優れたプログラマーになる方法を学ぶ場合は、password_hash()の使用方法を読んでください。ただし、安全なアクセス制御を適用したいだけの場合は、 Apacheの認証メカニズム を使用することをお勧めします。

1
symcbean

何/方法?

password_hash を使用します。返された文字列値をコピーして、ソースに貼り付けます。 password_verify を使用して、パスワードが正しいかどうかをテストします。

password_hashのアルゴリズムはPASSWORD_DEFAULTにすることができます。 bcryptのコストパラメータを増やすことは、おそらく良い考えです。コストパラメータが適切に調整されている場合、Argon2の方が優れていますが、デフォルトが適切かどうかはわかりません。

password_verifyは、最初の引数としてログインフォームに提供されたパスワードを受け取り、2番目の引数としてpassword_hashによって返される文字列を受け取ります。

どうして?

これはパスワードハッシュと呼ばれます。 (暗号化ではありません。)パスワードハッシュアルゴリズムは、暗号化ハッシュ関数のバリエーションです。これらは一方向のプロセスです。ユーザーのパスワードは、最初に正しく推測しないと回復できません。強力なパスワードを選択するのは、パスワード作成者次第です。

オフラインパスワードクラッキングでは、クラッカーは候補となるパスワードを次々と試すことができ、一致するものが見つかるまでpassword_verifyと同等の作業を行います。 (オフラインクラックとは、誰かがパスワードハッシュを盗み、自分のコンピューターでそれを検証しようとするときに、サーバーがレート制限のように行うことをバイパスします。)

パスワードハッシュアルゴリズムは、パスワードをテストしたいすべての人に、正当かどうかにかかわらず、推測ごとにさらに多くの作業を強制することで、あまり強力でないパスワードに対応しようとします。

ほかに何か?

レート制限を実装する必要があります。多分一時的なアカウントのロックアウトも。 IPアドレスのホワイトリストも良い考えですが、状況によってはユーザビリティの問題が発生する可能性があります。ホワイトリストは、誰にでもできる防御策ではありません。

ロックアウトおよびレート制限を行うには、何らかのタイプの読み取り/書き込みストアが必要です。攻撃者が新しいセッションを開始する可能性があるため、セッション変数は機能しません。このため、おそらく要件を再検討してください。または、ドキュメントルートまたはキー値ストア以外の読み取り/書き込みファイルのような別のストレージを見つけます。

PHPソースへのアクセス権を持つユーザーからパスワードハッシュを隠すには、私が聞いた最も単純な読み取り専用の方法は SetEnvまたはfastcgi_param を使用することですが、おそらくそれは重要です「外部confファイル」として。

ハッシュを非表示にすると、パスワードハッシュを盗むことが難しくなります。ハッシュを取得できない場合、オフラインクラッキングは使用できません。しかし、それは多くの助けになるとは思わない。多分あなたはまだハッキングされていません。たぶん、誰かがあなたのサーバーをハッキングして、PHPソースを読み取る機能よりもはるかに多くのアクセス権を持っています。誰かがPHPソースへの読み取りアクセス権しか持っていない可能性がありますが、 PHPソースリークが最初に発生するのを防ぐために、バグや設定ミスを回避するために費やす方がよいと思います。

1
Future Security