簡體   English   中英

檢查regenerate_session_id()函數是否確實有效/其他安全問題

[英]Check if regenerate_session_id() function actually works / Other security questions

我正在建立一個網站,我想保護它免受會話劫持 為此,我遇到一個人說:

一般的經驗法則是,每當用戶更改訪問級別時,都會生成會話ID。

1.當用戶登錄時2.當用戶注銷時3.當用戶獲得管理訪問權限時

物有所值,我的網站將訪問級別分為登錄 用戶注銷用戶 所有表格都是使用POST方法提交的。

的index.php

<?php
session_start();

//Setting the variable initialy to false
$_SESSION['LOGGED_IN'] = FALSE;

//to use SSL

$serverport = $_SERVER['SERVER_PORT'];

$server_http_host = $_SERVER['HTTP_HOST'];

$server_request_uri = $_SERVER['REQUEST_URI'];


if (headers_sent()) 
{
    die("HTTP headers have already been sent ");
}
else
{
if($serverport != '443')
{
ob_start();
exit(header('Location: https://'.$server_http_host.$server_request_uri));
}

}

if(isset($_POST['SUBMIT']))

{
if(isset($_POST['TOKEN']) && $_POST['TOKEN'] == $_SESSION['TOKEN'])
{
//Open database connection
require_once('connect_db.php');

//Calling functions.php that includes all custom functions
//ErrorHandler()
require_once('functions.php');        

$email = $_POST['EMAIL'];
$password = $_POST['PASSWORD'];



$statement = $DBH->prepare("SELECT * FROM user_details WHERE email=:email AND pwd=:password ");
$statement->bindParam(':email',$email);
$statement->bindParam(':password',$password);
$statement->setFetchMode(PDO::FETCH_ASSOC);
try{

$result = $statement->execute();
$rows = $statement->rowCount(); // shows how many times the user is available in the user_details table
$data = $statement->fetch(); //fetches the data related to that user from user_details table


}
catch(PDOException $e)
{
//this is custom function   
echo ErrorHandler($e);
}


if($rows == 1)
{
//this means that the user has inserted the correct credentials 
//regenerate session_id each time there is a change in the level of privilege to mitigate SESSION FIXATION  
session_regenerate_id(true);

//turning logged in variable to true as soon as it finds a match
$_SESSION['LOGGED_IN'] = TRUE;

//saves the email into a session so it can be used in mainpage.php
$_SESSION['EMAIL'] = $email;

//redirect to main page
header('Location:https://www.example.com/mainpage.php');

}
else
{
echo "<br />Wrong username or password!<br />";
}
}//closing *if(isset($_POST['TOKEN']) && $_POST['TOKEN'] == $_SESSION['TOKEN'])*
}//closing *if($_POST['SUBMIT'])*

//creating a random token to inject in our HTML form
$token = base64_encode(openssl_random_pseudo_bytes(32));

//store the random token in the session variable so we can later compare it to the one in the HTML form
$_SESSION['TOKEN'] = $token;
?>

<form action="index.php" method="POST" accept-charset="UTF-8">
<p>Email: <input type="email" name="EMAIL" /> </p>
<p><input type="hidden" name="TOKEN" value="<?php echo $token; ?>" /></p>
<p>Password <input type="password" name="PASSWORD" /> </p>
<p><input type="submit" name="SUBMIT" value="Submit" /></p>
</form>

該腳本接受來自用戶的輸入電子郵件和密碼,檢查數據庫,如果找到匹配的內容,則會將用戶重定向到mainpage.php。

mainpage.php

<?php
ob_start();
//the code to set the header must be called before output begins
session_start();


$serverport = $_SERVER['SERVER_PORT'];

$server_http_host = $_SERVER['HTTP_HOST'];

$server_request_uri = $_SERVER['REQUEST_URI'];

if (headers_sent())
{
die("HTTP headers have already been sent ");
}    
else
{
if($serverport != '443')
{
ob_start();
exit(header('Location: https://'.$server_http_host.$server_request_uri));
}
}



if(($_SESSION['LOGGED_IN'] == TRUE) && isset($_SESSION['LOGGED_IN']))
{
$email = $_SESSION['EMAIL'];
echo $email;

//Calling functions.php that includes all custom functions
//LogOut()
require_once('functions.php');

if(isset($_POST['LOGOUT']))
{
//its a custom function that is used for logging out    
LogOut();
}


echo '
<form method="POST" action="mainpage.php">
<p><input type="submit" name="LOGOUT" value="Log Out" /></p>
</form>

';

}
else
{
echo "Please login in order to use example.com";
}


?>

有沒有辦法讓我檢查我構建這兩個腳本的方式是否真的重新生成了會話ID? 我正在使用Firefox的擴展LIVE HTTP標頭,但不確定我是否正確閱讀它。

另外,我找不到使用我的瀏覽器(Chrome或Firefox甚至IE11)來跟蹤和讀取存儲的COOKIES內容的方法。 我怎樣才能做到這一點?

與安全性相關的另一個問題:實施反CSRF令牌:我是否需要為網站中的每種表單實施反CSRF令牌[我想答案是肯定的,但我想確認]? 每個令牌都應該與先前形式中使用的令牌不同嗎? 例如,如果index.php中的令牌也具有某種形式,則它與mainpage.php中使用的令牌也不同。

令牌技術是否可以防止任何其他類型的攻擊?

如果您在上面的代碼中指出了錯誤的編程,我將非常高興,因此我可以更正並同時學習。

謝謝!

我將重點關注您的問題,而不必進行全面的code review ,因為我認為您的問題是發布的主要原因。

檢查您當前會話ID或PHPSESSID一種簡單方法是在Chrome的Developer Tools > Resources > Cookies下進行檢查。 您將看到(初始生成的)會話ID。 您可以用戶登錄之前和之后檢查該值。如果該value更改,則實際上已重新生成了會話ID。

您還可以通過右鍵單擊當前頁面,轉到“ View Page Info並使用“ Cookies選項卡來View Page Info Firefox中的Cookies

對於CSRF(預防)令牌,答案有所不同。 人們使用不同的方法來解決它們。 我想說,大多數網站在regenerate會話ID時都會在$_SESSION設置一個令牌。 因此,在當前會話的持續時間內,CSRF令牌將保持不變,並對照 CSRF令牌的隱藏輸入進行檢查。 另一方面,我還聽說過為面向客戶的每個表單都重新生成CSRF令牌。 您的操作方式取決於您。 沒有什么是100%防彈的,但要盡可能接近100%是一個主意。

花幾分鍾閱讀一下CSRF令牌和同步器令牌模式

祝你好運!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM