PHPセッションのセキュリティ


125

PHPで責任あるセッションセキュリティを維持するためのガイドラインは何ですか?Web全体に情報があり、すべてが1か所にまとまった時期です。

回答:


88

セッションを安全に保つには、いくつかのことを行う必要があります。

  1. ユーザーの認証または機密性の高い操作の実行時にSSLを使用します。
  2. セキュリティレベルが変更される(ログインなど)たびに、セッションIDを再生成します。必要に応じて、リクエストごとにセッションIDを再生成することもできます。
  3. セッションがタイムアウトする
  4. レジスタグローバルを使用しない
  5. 認証の詳細をサーバーに保存します。つまり、ユーザー名などの詳細をCookieで送信しないでください。
  6. を確認してください$_SERVER['HTTP_USER_AGENT']。これは、セッションのハイジャックに小さな障壁を追加します。IPアドレスを確認することもできます。しかし、これは、複数のインターネット接続での負荷分散などのためにIPアドレスを変更しているユーザーに問題を引き起こします(ここでの環境の場合)。
  7. ファイルシステム上のセッションへのアクセスをロックダウンするか、カスタムセッション処理を使用する
  8. 機密性の高い操作の場合は、ログインしたユーザーに認証の詳細を再度提供するよう要求することを検討

15
暗号化されたトラフィックと暗号化されていないトラフィックに個別のセッションがない限り、一部の操作でのみSSLを使用するだけでは不十分です。HTTPSとHTTPで単一セッションを使用する場合、攻撃者は最初の非HTTPSリクエストでそれを盗みます。
Kornel

6
-1ユーザーエージェントは、なりすましが簡単です。あなたが説明しているのはコードを浪費するものであり、セキュリティシステムではありません。
2010

24
@The Rook、それはささいな障壁である可能性があり(攻撃者は自分のサイトを使用して被害者のユーザーエージェントをキャプチャできる)、あいまいさを介してセキュリティに依存しますが、それでも1つの追加の障壁です。セッションの使用中にユーザーエージェントHTTPが変更された場合、それは非常に疑わしく、おそらく攻撃です。あなたがそれを一人で使うことができるとは決して言いません 他のテクニックと組み合わせると、はるかに安全なサイトになります。
グロム

5
@gromドアにスコッチテープを貼って、人々が侵入するのを防ぐと言っているようなものだと思います。– 2010
ルーク

8
ユーザーエージェントを確認している場合、互換モードを切り替えると、IE8ユーザーからのすべての要求がブロックされます。私自身のコードでこの問題を追跡した楽しさを確認してください:serverfault.com/questions/200018/http-302-problem-on-ie7。他の人が言ったように、偽装するのは簡単なことなので、ユーザーエージェントをチェックアウトします。
10

15

1つのガイドラインは、セッションのセキュリティレベルが変更されるたびにsession_regenerate_idを呼び出すことです。これにより、セッションのハイジャックを防ぐことができます。


11

私の2つ(またはそれ以上)のセント:

  • 誰も信じない
  • 入力のフィルター、出力のエスケープ(Cookie、セッションデータも入力です)
  • XSSを避けます(HTMLを適切な形式に保ち、PHPTALまたはHTMLPurifierを確認してください)
  • 多層防御
  • データを公開しない

このトピックについては、小さいながらも優れた本があります。ChrisShiflettによるEssential PHP Securityです。

必須のPHPセキュリティhttp://shiflett.org/images/essential-php-security-small.png

本のホームページには、興味深いコード例とサンプルの章があります。

:あなたはここで説明する、(IP&ユーザーエージェント)上記の技術を使用することができます個人情報の盗難を避けるためにどのように


XSS防止の場合は+1。これがないと、CSRFから保護することは不可能であるため、誰かがセッションIDを取得しなくてもセッションに「乗る」ことができます。
Kornel、2011年

11

(PHP 6で対処されている)主要な問題の1つはregister_globalsだと思います。現在、回避するために使用される標準的な方法の1つは、または配列register_globalsを使用することです。$_REQUEST$_GET$_POST

これを行う「正しい」方法(5.2の時点では少しバグがありますが、6の時点では安定しています)はフィルター使用する方法です。

だから代わりに:

$username = $_POST["username"];

あなたがするでしょう:

$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);

または単に:

$username = filter_input(INPUT_POST, 'username');

2
これは問題とはまったく関係がありません。
Pixel開発者、

5
本当に?では、なぜ受け入れられた回答で、レジスタグローバルを使用しないことに言及するのでしょうか。ほとんどのありふれた開発者に関する限り、グローバルおよびフォーム変数の処理は、技術的には「セッション」オブジェクトの一部でなくても、「セッション」の傘下に含まれるのではないでしょうか。
cmcculloh 2008

9
私は同意します、これは質問に完全に答えるものではありませんが、それは間違いなく質問への答えの一部です。繰り返しになりますが、これにより、「レジスタグローバルを使用しない」という受け入れられた回答の箇条書きが具体化されます。これは代わりに何をすべきかを伝えます。
cmcculloh 2010


5

私の経験では、IPアドレスを使用することは本当に最善の方法ではありません。例えば; 私のオフィスには負荷に応じて使用される2つのIPアドレスがあり、IPアドレスを使用すると常に問題が発生します。

代わりに、サーバー上のドメインの個別のデータベースにセッションを保存することを選択しました。この方法では、ファイルシステムの誰もそのセッション情報にアクセスできません。これは、3.0より前のphpBBで本当に役立ちました(それ以降は修正されています)が、それでも私は良い考えだと思います。


3

これはかなり簡単で明白ですが、使用するたびに必ずsession_destroyを実行してください。ユーザーが明示的にログアウトしないと、これを実装するのが難しい場合があるため、タイマーを設定してこれを実行できます。

これはsetTimer()とclearTimer()の良いチュートリアルです。


3

PHPセッションとセキュリティ(セッションハイジャック以外)の主な問題は、現在の環境にあります。デフォルトでは、PHPはセッションデータをOSの一時ディレクトリのファイルに保存します。特別な考えや計画がなければ、これは世界中で読み取り可能なディレクトリであるため、すべてのセッション情報はサーバーにアクセスできるすべての人に公開されます。

複数のサーバー上でセッションを維持することに関して。その時点で、提供された関数を呼び出してセッションデータをCRUD(作成、読み取り、更新、削除)するユーザー処理セッションにPHPを切り替えることをお勧めします。その時点で、データベースまたはmemcacheのようなソリューションにセッション情報を保存して、すべてのアプリケーションサーバーがデータにアクセスできるようにすることができます。

共有サーバーを使用している場合は、独自のセッションを保存すると、データベースに保存できるため、ファイルシステムを頻繁に制御できるので便利です。


3

私はこのようにセッションをセットアップしました

ログインページ:

$_SESSION['fingerprint'] = md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR']);

(設定ページで定義されたフレーズ)

次に、サイトの残りの部分全体にあるヘッダーに:

session_start();
if ($_SESSION['fingerprint'] != md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR'])) {       
    session_destroy();
    header('Location: http://website login page/');
    exit();     
}

3

php.ini

session.cookie_httponly = 1
change session name from default PHPSESSID

eq Apache add header:

X-XSS-Protection    1

httpd.conf-> <FilesMatch "\。(php | phtml | aspx | htm | html)$">ヘッダーセットX-XSS-Protection "1" </ FilesMatch>
user956584

これX-XSS-Protectionはまったく役に立ちません。実際、保護アルゴリズム自体が実際に悪用される可能性があり、以前よりも悪化しています。
パチェリエ

2

IPとユーザーエージェントの両方をチェックして、それらが変更されるかどうかを確認します

if ($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']
    || $_SESSION['user_ip'] != $_SERVER['REMOTE_ADDR'])
{
    //Something fishy is going on here?
}

5
ユーザーが負荷分散されたプロキシファームの背後にいる場合、IPは正当に変更される可能性があります。
Kornel

2
また、user_agentは、ユーザーがブラウザーをアップグレードするたびに変更できます。
スコット2009

3
@scotts IPの部分に同意しますが、ブラウザのアップグレードでは、ログイン時にセッションを設定するため、再度ログインしたときに新しいセッションを作成せずにブラウザをアップグレードする方法がわかりません。
JasonDavis

IE8で互換モードを切り替えるときに、user_agentも変更できると思います。偽造も非常に簡単です。

はい、しかし、静的IP eq GSMを持ち、30分ごとに変更されるユーザーはどうですか。したがって、セッション+ホスト名にIPを保存し、WHEN IP!= REMOTE_ADDRがホストをチェックしてhostanmes eqを比較します。12.12.12.holand.nl->がholand.nl == trueの場合。しかし、一部のホストにはIPベースのホスト名がありました。比較マスク88.99.XX.XXが必要です
user956584

2

session_set_save_handler()を使用すると、独自のセッションハンドラーを設定できます。たとえば、データベースにセッションを保存できます。データベースセッションハンドラの例については、php.netのコメントを参照してください。

複数のサーバーがある場合はDBセッションも有効です。それ以外の場合、ファイルベースのセッションを使用している場合は、各Webサーバーが同じファイルシステムにアクセスしてセッションを読み書きできることを確認する必要があります。


2

セッションデータが安全であることを確認する必要があります。php.iniを確認するか、phpinfo()を使用して、セッション設定を確認できます。_session.save_path_は、それらが保存されている場所を示します。

フォルダとその親の権限を確認してください。パブリック(/ tmp)にしたり、共有サーバー上の他のWebサイトからアクセスしたりしないでください。

phpセッションを引き続き使用する場合は、_session.save_path_を変更して他のフォルダーを使用するようにphpを設定するか、_session.save_handler_を変更してデータベースにデータを保存できます。

php.ini(一部のプロバイダーでは許可されています)またはapache + mod_phpの場合、サイトのルートフォルダーにある.htaccessファイルに_session.save_path_を設定できる場合があります php_value session.save_path "/home/example.com/html/session"。実行時に_session_save_path()_を使用して設定することもできます。

Chris ShiflettのチュートリアルまたはZend_Session_SaveHandler_DbTableをチェックして、代替のセッションハンドラーを設定してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.