2013-03-19 6 views
16

これは私のウェブサイトでの認証を制御するコードです。私の論理が正しいかどうかは分かりません。ユーザー名とパスワードは、以下の正しい場合に起こる:PHPでのログインセッションの安全な作成と破棄

if(session_start()) 
{ 
     session_regenerate_id(true);//without this the session ID will always be the same 
     $_SESSION['loggedInUser'] = $uName; 
     echo 'You are now logged in'; 
} 
else echo 'Right password/username but session failed to start'; 

以降のページは、ユーザーがログアウトしたとき、私は

session_start();//if I don't have this the next line produces an error 
session_unset();//destroys session variables 
session_destroy();//ends session 

を持って

session_start(); 
if(isset($_SESSION['loggedInUser']) 
{ 
//rest of page 
} 
else echo 'you must log in'; 

でログインしている場合、私はどうかを確認ログアウト時にsession_start()を呼び出さないように赤色にしてください。しかし、私がそれを持っていなければ、Trying to destroy uninitialized sessionというメッセージが出ます。これをどうすれば解決できますか?

IPアドレスとユーザエージェントに基づいて指紋を作成することをお勧めしますか?私はそれが悪いのは複数のコンピュータが同じIPアドレスを共有することができるためです。たとえば、コンピュータラボであれば、すべてのトラフィックはプロキシを経由し、同じコンピュータであれば動的であればIPアドレスを変更できます。一方、これはどのくらい頻繁に起こりますか?すべてのセッションハイジャックを防止するために、ブロックされた有効な利用方法はほんのわずかな価値があります。

あなたが評判の良い記事を推薦できる場合でも、このトピックについて学ぶために読んでください。

5/6の回答が0未満の票を持っている:(でしダウン有権者はので、私はしっかりと私は、次のコードを使用するセッションを破棄するに

+0

[php.net](http://php.net/manual/en/functionsession- destroy_php) '$ _SESSION'を使わない古い推奨されていないコードに対してのみsession_unset()を使用してください – bitWorking

+0

可能な限り、既存の認証フレームワークを再利用するべきです。例えば、https://github.com/delight-im/PHP-Authを見てください – caw

答えて

24

まず、Mozilla WebAppSec Security Coding Guideline - Session ManagementOWASP A3-Broken Authentication and Session Managementを読んでください。これらの要件を満たすには、configure PHP's session handlerがあります。

防止すべき最初の瑕はA9-Insufficient Transport Layer Protectionです。要するに、誰かがa tool like Firesheepを使ってセッションをハイジャックしないようにします。この攻撃は、HTTPSを介してセッションIDを送信するには、ブラウザを強制することにより防ぐことができます。

session.cookie_secure=1 

あなたはhttponly flagを設定することでXSSを使用してセッションIDを取得する攻撃者を防ぐことができます。

session.cookie_httponly=1 

あなたは常にあなたのセッションIDを保存するためにクッキーを使用します。 GETまたはPOST変数を使用してセッションIDを渡すことができる場合、攻撃者はSession Fixation attackを使用してセッションを乗っ取ることができます。

session.use_cookies=1 
session.use_only_cookies=1 

次はあなたがCSPRNGからエントロピーの少なくとも128ビットを持っていることを確認したい:この攻撃について考えるのもう一つの方法は、あなたが攻撃者が別のユーザーのセッションを作成したくないということです。 * nixシステムの下には、/dev/urandomを使用することができます。

session.entropy_file="/dev/urandom" 
session.entropy_length=16 

セッションハンドラがすべてではありません。 Cross-Site Request Forgery attacks(別名CSRFまたは「セッションライディング」)、クロスサイトスクリプティング(XSS)についても心配する必要があります。 XSSは、(たとえhttp_onlyクッキーであっても)CSRF保護を守るために使用できます。 Clickjackingは、攻撃者が不正な操作を実行するために使用することもできます。

これらの設定オプションを設定したら、session_start()を呼び出してください。ユーザーがログアウトしたときにセッションコールsession_destroy()を破壊すると、それは簡単です!

+0

クロスサイトリクエスト偽造はセッションに依存しません。これは、「セッションライディング」が提案する可能性があるためです。しかし、認証されたセッションを持つユーザは、「匿名」ユーザよりも貴重な犠牲者です。 Clickjackingにも同じことが適用されます。 – Gumbo

+0

@Rook:あなたの最後の段落を強調したい! PHPのセッションは簡単に始めることができます。セッションクッキーが既に存在し、セッションデータが保存されていると常に仮定します。セッションを開始するだけです。次に、$ _SESSIONを調べ、成功したログインの痕跡があるかどうかを確認します。セッションを持つことは、セキュリティレベルでは何も意味しません。ユーザーがログインしていることを証明するものではありません。保存されたセッションデータだけがこれを行うことができます。 – Sven

+0

@ Gumbo:メソッドはセッションに依存しませんが、この認証メソッドが実装されている場合、CSRFはセッションに依存します。すでに述べたように、特定のURLを使用してリクエスト/アクションを実行するには、認証されたユーザーが必要です。 (ちょうどTSのためにそれを明確にしようとしている)。 –

0

のために外を見るために知っているコメント:?

session_start(); 
// Unset all session values 
$_SESSION = array(); 
// get session parameters 
$params = session_get_cookie_params(); 
// Delete the actual cookie. 
setcookie(session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"]); 
// Destroy session 
session_destroy(); 

セッションを破棄するには、まずsession_start();を含めないと動作しないことがわかったので、最初に起動する必要があります

session_regenerate_id();関数は、 true(session_regenerate_id(true);)で使用された場合、t古いセッションIDは新しいセッションIDを生成するときにサーバーから削除されます。すべてのページで新しいセッションIDを生成する理由は、ユーザーがセッションIDを絶えず変更しているためにセッションハイジャックを実行するのがずっと難しくなります(ほとんど不可能です)。

session_regenerate_id();上に表示PHP.netマニュアル)

あなたは常にIPアドレスやブラウザのようなものをチェックする必要があり、ユーザーを認証する場合、これらは変化しないサーバへのリクエストで送信された一定のものですあなたのセッションの生涯、そしてもしそうなら、あなたは何か起きていることを知っています。私は常にユーザーIDを格納する2つのセッション変数1を作成して、データベースのデータベースを照会でき、ユーザーのパスワード、IPアドレス、ブラウザーストリングをすべて1つのハッシュ(sha512)に保管します。

$user_id = $_SESSION['user_id']; 
$login_string = $_SESSION['login_string']; 

// Query Database and get hashed password 

$login_check = hash('sha512', $password.$ip_address.$user_browser); 

if($login_check == $login_string) { 
    // Logged In!!!! 
    return true; 
} else { 
    // Not logged in 
    return false; 
} 

パスワードはセッションに保存されていても安全です。これは、パスワードがハッシュされているため(この場合は2回)、セッションデータがユーザーのコンピュータに保存されていないため(クッキーなど)、セッションファイルに保存されるためです。

私は安全なログインと認証についてwikihow.comの記事を書いていますが、hereが見つかりました。

0

あなただけ書くことができます:あなたはメンバーログインのユーザーIDを割り当てることができます

session_start(); // session should be started before it can be used. 

。このために、ユーザー入力からユーザー名とパスワードを取得し、dbと戻りユーザーIDでそれをチェックすることができます。より多くのセキュリティのために、例えば文字列を持つことができます。 "demo"と "test"は単にmd5の両方であり、以下のようにuseridと混合します。

$userid=md5("demo").$userid.md5("test");// you can set any string instead of demo and test. 

$_SESSION['userid']=$userid; 

ちょうどそれと一致し、それから正確なユーザIDを見つけて、あなたのコードでそれを使用使用しているときに、文字列を知っているように、他のページに

session_start(); // If you are have not started it or included above code file in it. 

を、それを使用している間。それだけで使用破壊する

session_unset($_SESSION['userid']); // It will only unset the session userid completely. 

は、任意のセッションを使用する前に、あなたがそれを起動する必要があることを確認してください。より良い方法では、セッションを1つのファイル、つまりinit.phpという名前で起動し、セッションを使用する場所ごとに含めることができます。

+2

なぜセッションデータの中にmd5のものがありますか?これはハードディスクとの間で移動するデータを膨らませるだけですが、セッションの内容が外部に公開されることはないため、セキュリティがまったく向上しません。それは物事を複雑にするだけです。 – Sven

0

最初にsession_id()を使用して、ユーザーがすでにセッションを取得しているかどうかを判断し、そうでない場合はsession_start()を使用できます。リチウムframewrokから

例コード:

/** 
* Starts the session. 
* 
* @return boolean True if session successfully started (or has already been started), 
*   false otherwise. 
*/ 
protected static function _start() { 
    if (session_id()) { 
     return true; 
    } 
    ... 
    return session_start(); 
} 

コール_start()した後、あなたが安全に最初のアクティブなセッションがあるかどうかを確認し、「start_sessionを()」使用せずにセッションを破棄するにsession_destroy()

+1

ようこそ。この質問にはセキュリティタグがあり、答えはセキュリティに固有のものでなければなりません。 – rook

0

を呼び出すことができます以下のようなものではない

$existingSessionId = session_id(); 
if ($existingSessionId != "") 
{ 
    // Initialize the session. 
    session_start(); 

    // Unset all of the session variables. 
    $_SESSION = array(); 

    // If it's desired to kill the session, also delete the session cookie. 
    // Note: This will destroy the session, and not just the session data! 
    if (ini_get("session.use_cookies")) { 
     $params = session_get_cookie_params(); 
     setcookie(session_name(), '', time() - 42000, 
      $params["path"], $params["domain"], 
      $params["secure"], $params["httponly"] 
     ); 
    } 

    // Finally, destroy the session. 
    session_destroy(); 
} 
else 
{ 
    // No Active sessions 
} 

session_regenerate_id(true)、古いセッションIDを新しいものに置き換えます古いセッションIDを設定解除しません。このためには、session_destroyとセッションクッキーを削除する必要があります。

ブラウザは、セッションCookieをサーバーに送信します。これまでのセッションは破棄されました。 PHPはこのセッションIDを取得し、start_session()を実行すると、ブラウザが送信したセッションIDを使用します。セッションCookieを削除すると、session_startは新しいセッションIDを生成し、session_regenerate_id()を呼び出す必要はありません。

+0

あなたのコードはセッションを破壊するために使用されますか?それは目的ですか?セッションを破棄しようとしている場合にセッションが存在するかどうかをチェックするのはどうですか? – Celeritas

+1

session_destroy()を使用するには、最初にsession_start()を発行する必要があります。それ以外の場合は、エラーがスローされます。 session_destroyドキュメントごとに "session_destroy()は、現在のセッションに関連するすべてのデータを破棄します。セッションに関連するグローバル変数の設定を解除したり、セッションクッキーの設定を解除したりしません。 セッションを完全に終了するにはユーザーをログアウトするには、セッションIDも設定解除する必要があります。セッションIDを伝播するためにCookieを使用する場合は、セッションCookieを削除する必要があります。 – Amit

+0

説明をありがとう。もう1つの質問ですが、 'time() - 42000'はどうしますか? – Celeritas

関連する問題