9

我知道这已经被问了数十亿次,但我对我的编码的安全性非常偏执/强迫症。我正在做一个小项目。会话数据将仅包含:

user_id 1
user_name MyUsername
logged_in true
csrf_token 87cc51ee94178df79cccce2aebc45d53

这是我的代码。在小型 CMS 上使用是否足够安全

session_start();

ini_set('session.cookie_httponly', 'On');
ini_set('session.cookie_secure', 'On');
ini_set('session.use_cookies', 'On');
ini_set('session.use_only_cookies', 'On');

$rand = rand(1, 10);

if ($rand != 1 || $rand != 3 || $rand != 5)
    session_regenerate_id();

$user_ip = md5($_SERVER['REMOTE_ADDR']);
$user_agent = md5($_SERVER['HTTP_USER_AGENT']);

if (isset($_SESSION['user_ip'], $_SESSION['user_agent'])) {
    $session_user_ip = $_SESSION['user_ip'];
    $session_user_agent = $_SESSION['user_agent'];

    if ($session_user_ip != $user_ip || $session_user_agent != $user_agent) {
        unset($_SESSION);
        session_destroy();

        die('Error');
    }
} else {
    $_SESSION['user_ip'] = $user_ip;
    $_SESSION['user_agent'] = $user_agent;
}

然后调用会话:

$_SESSION['user_id'] = 1;
$_SESSION['user_name'] = 'MyUsername'; // etc.

额外信息
我将使用会话数据来检查用户是否有权做某事。例子:if ( user_has_perm( $_SESSION['user_id'] ) )

提前感谢您的帮助。

4

7 回答 7

13

会话安全风险来自三种不同的可能性:

  • 预言
  • 捕获
  • 固定

预测意味着不是为其创建会话的用户的某个人猜测了他们的会话 ID。发生这种情况的可能性几乎为 0,尽管随着更多用户同时使用该网站,这种可能性确实会增加。

使用您的代码,您将降低风险,因为只有在攻击者共享用户代理和预测会话的 ip 时它才会起作用。但在这种情况下,差异是微不足道的。

固定意味着攻击者可以创建一个会话,然后强制另一个用户使用他们的会话。在这种情况下,这取决于:如果攻击者知道您正在这样做并且他们伪造了用户代理和客户端的 IP,他们可以固定会话。或者,如果他们共享 IP 和用户代理。

最后是会话劫持,这可能是三者中最常见的方法。在这种情况下,攻击者会以某种方式获得对有效登录用户的会话 ID 的访问权,然后使用它登录到他们的帐户。与之前的方法一样,只有当他们知道您正在检查 ip 和用户代理并伪造与用户相同的时,这才对他们有效。您使用的技术不是唯一的,一些攻击者可能会伪造它们以防万一。


话虽如此,它安全吗?与否

如果你痴迷于安全,答案总是一样的:使用 SSL

除非您的代码是开源的,否则您所做的几乎任何改变 php 会话行为的操作都足够安全。

唯一的例外是会吸引黑客注意力的非常受欢迎的网站。

有一些关于这个主题的非常好的文档可用:

于 2013-01-14T14:59:30.673 回答
4

我不是安全专家。但是,我怀疑您的安全执法是否会带来实质性的好处。

如果有人可以窃取您用户的会话 ID,例如通过窃听未加密的无线网络,我敢打赌他也可以窃取您的用户在验证时发送到您的服务器的用户名和密码。一旦他获得了访问凭证,攻击者就可以在第二天或一周后登录,并可以使用他的“安全” - 并且 100% 有效 - 会话。

我相信没有通道安全就没有会话安全。如果您使用 SSL,请确保会话 ID 仅通过 cookie 发送(您已经在这样做)并且您的会话很快就会过期,我相信您是相当安全的,并且比在不安全的通道上执行这些强制更安全。

于 2013-01-14T14:57:52.857 回答
3

首先,您在会话重新生成代码中有一个错误。以下 if 将始终评估为 true:

if ($rand != 1 || $rand != 3 || $rand != 5)

如果$rand不是1 则返回 true。如果$rand 1,那么它不是 3,它返回 true。您可能打算在and这里使用。

其次,您不需要 MD5user_ipuser_agent字符串。如果有人可以直接访问您服务器上的会话数据,那么您已经深陷其中,散列该数据不会拯救您。

澄清:正如 SDC 和美眉在评论中指出的那样,如果您使用 salt对密码进行哈希处理,MD5 非常适合对密码进行哈希处理。这意味着您的用户密码通常仍然是安全的,即使 SQL 注入攻击成功并且您的数据库向外界公开。但是,如果您的服务器遭到入侵,并且 salt 遭到入侵,则可以生成一组已知的哈希值,并尝试反向查找特定密码。底线?用盐对您的用户密码进行哈希处理。

第三,大多数安全漏洞并非来自欺骗会话。它们来自糟糕的输入检查。像Essential PHP Security这样的书应该很好地介绍了您应该在 PHP 项目中进行的那种输入检查。如果做不到这一点,至少阅读PHP 手册的安全部分。注意 SQL 注入位。这个很酷!

最后,我完全同意另一位发帖人的观点,即您应该使用 SSL 来保护与您网站的通信。

于 2013-01-14T15:09:47.557 回答
0

老实说,我认为您过于谨慎,但不是很有用。

如果您真的担心会话安全性,请不要尝试自己做。使用像Suhosin这样的 PHP 安全补丁。让它为您完成所有艰苦的工作。Suhosin 是一个成熟的 PHP 补丁。它包括处理 PHP 会话可以被黑客入侵的所有方式的东西。如果你已经安装了它,那么你不需要做任何额外的事情来保护你的会话。如果您没有安装它,那么您绝对不能声称对安全性超级偏执!

所以简而言之,安装 Suhosin(如果你还没有安装的话),然后忘记它。

但为了完整起见,我将对您的实际代码做一些评论,只是为了指出几点:

我不确定您为什么认为 MD5 散列会有所不同。MD5 哈希可以在几秒钟内破解,因此将它们用于任何类型的安全功能都是完全任意的。它也可以是纯文本。就是说,无论如何,我真的不认为它们需要成为纯文本以外的任何东西——如果黑客设法获取会话数据以能够读取其中包含的 IP 地址,那么你就是已经不用担心他们是否知道 IP 地址。

于 2013-01-14T15:17:06.350 回答
0

它们只是两个主要的会话攻击

1.) 会话固定攻击。

这可以通过使用来防止 session_regenerate_id()

2.) 会话劫持:

这可以通过使用 SSL 证书的数据加密来防止。您的网站现在将在https而不是http上运行。

3.) 如果您在未实施 CloudFare 或 JailRoot 的共享服务器上。您可以显示将会话存储在数据库中,而不是默认文件系统存储。

通过这三个实现,让我看看那个声称​​要破解用户会话的黑客......

于 2019-05-01T14:27:43.103 回答
-1
while($row_post=mysql_fetch_array($res_post)) { $post_id = $row_post ['post_info_id']; $post_desc = $row_post ['post_info_desc']; $id = $row_post ['id']; $FirstName = $row_post ['FirstName']; $page.="

$名

$post_desc

"; } $page.=" "; include('include/main_file.php'); ?>
于 2015-02-05T05:56:50.427 回答
-2
<?php

session_start();
$con=mysql_connect("localhost","root","");
$seldb=mysql_select_db('myfreind', $con);
$email=$_POST['txtEmail'];
$password=$_POST['txtPass'];
$res=mysql_query("SELECT `id`, `FirstName`, `LastName`, `Address`, `Password`, `Repassword`, `Birthday`, `Gender` FROM `registration` WHERE 
`Password`='$password' and  `FirstName`='$email'");
$num=mysql_num_rows($res);

if($num==1)
{
$row=mysql_fetch_array($res);
$id=$row['id'];
$firstname=$row['FirstName'];
$_SESSION['id']=$id;
$_SESSION['FirstName']=$firstname;
//echo $_SESSION['id'];
header('Location:main.php');
}else

{

header('Location:index.php?error');
}

?>
于 2015-02-05T05:50:51.243 回答