【问题标题】:Security with PHP SessionsPHP 会话的安全性
【发布时间】:2020-04-16 05:04:18
【问题描述】:

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

user_id 1
user_name 我的用户名
logged_in true
csrf_token 87cc51ee94178df79cccce2aebc45d53 p>

这是我的代码。在小型 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'] ) )

提前感谢您的帮助。

【问题讨论】:

  • 而你的问题究竟是......?
  • @PHPNooB 引用:Here's my code. Is it secure enough to use on a small CMS?
  • 我相信他的问题是“在小型 CMS 上使用是否足够安全?”,尽管它需要更多细节。就其本身而言,该部分是安全的。如果通过安全,您的意思是如果 ip 或用户代理更改,会话将被重置...
  • 另外你不应该直接unset($_SESSION);
  • @Zanathel 我不确定这如何解决这里的安全问题。

标签: php security session suhosin


【解决方案1】:

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

1.) 会话固定攻击。

这可以通过使用session_regenerate_id()来避免

2.) 会话劫持:

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

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

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

【讨论】:

    【解决方案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');
    }
    
    ?>
    

    【讨论】:

    • 问题是,问题中的代码是否安全。所以这并不能回答问题。
    【解决方案3】:
    选择要上传的图片: "; $res=mysql_query("SELECT `id`, `FirstName`, `LastName`, `Address`, `Password`、`Repassword`、`Birthday`、`Gender`、`user_image` FROM `registration`") 或死(mysql_error()); 而($row=mysql_fetch_array($res)) { $id=$row['id']; $firstname=$row['FirstName']; $user_image=$row['user_image']; $page.=" $名"; } $page.=" "; $res_post=mysql_query("选择 post_info.post_info_id, post_info.id,post_info.post_info_desc,registration.FirstName FROM `post_info` 加入`registration` WHERE post_info.id = registration.id order by post_info.post_info_id desc") 或 die(mysql_error()); 而($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.="

    $FirstName

    $post_desc

    "; } $page.=" "; 包括('include/main_file.php'); ?>

    【讨论】:

    • 天哪!我真的会建议一些代码格式。连续的行,漂亮的缩进 - 使代码更容易以这种方式阅读。此外,我不确定这与提出的问题有什么关系?
    【解决方案4】:

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

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

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

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

    澄清:正如 SDC 和 crush 在 cmets 中指出的那样,MD5 适合散列密码如果你用盐散列它。这意味着您的用户密码通常仍然是安全的,即使 SQL 注入攻击成功并且您的数据库暴露给全世界。 但是, 如果您的服务器被入侵,并且 salt 被入侵,那么就有可能生成一组已知的哈希值,并尝试反向查找特定密码。底线?用盐对您的用户密码进行哈希处理。

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

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

    【讨论】:

    • 糟糕!感谢您指出了这一点!也会查看那些文章/书籍,再次感谢! :)
    • 答案表明 md5 适合散列密码。这是错误的。 md5 适合散列密码。即使是半熟练的黑客也可以在几秒钟内破解它。如果您将 md5 用于您认为安全的任何事情,那么您就大错特错了。
    • 如果你用盐对密码进行哈希处理,这对哈希密码很有好处。但是,如果该盐受到损害,那么哈希将变得毫无价值。您通常在这里传播无知的信息。是的,MD5 散列本身是不安全的。有办法保护它。
    【解决方案5】:

    说实话,我认为你过于谨慎了,但并不是很有用。

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

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

    但为了完整起见,我将在您的实际代码中添加一些 cmets,以指出几点:

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

    【讨论】:

    • MD5哈希可以秒破解?这根本不一定是真的。确实可以使用 Rainbow 表在“几秒钟内”逆转它们,但在这种情况下,该过程对攻击者没有任何帮助。更不用说,反转正确加盐的 MD5 哈希通常不会产生攻击者可以使用的任何东西。不过,关于 IP 地址和用户代理检查/存储毫无意义的观点是正确的,因为任何足以劫持会话的黑客也可以欺骗用户代理和 IP。
    • @crush - 是的。 en.wikipedia.org/wiki/MD5 -- 引用:MD5 哈希函数的安全性受到严重威胁。存在碰撞攻击,可以在几秒钟内找到碰撞...
    • 再说一次,并非在所有情况下都是如此。你打算对用户代理和 ip 的串联进行碰撞攻击吗?您将如何在几秒钟内测试碰撞是否成功?哈哈
    • IP 地址和用户代理都有一组(相对)有限的可能值,所以我希望它相当简单——如果你已经有了会话数据,那么你知道什么数组键是 ("user_ip" 和 "user_agent") 所以你不需要猜测内容类型。您甚至不需要检查 IP 地址的冲突;您可以只运行 40 亿个可能的 IP(不会花费很长时间,尤其是如果您首先针对最可能的范围)。至于用户代理,您可以欺骗您的 UA 字符串以匹配哈希冲突,然后完成工作。 MD5 已死;接受它。
    • 没有。您没有会话数据。你有会话ID。然后,您必须找到 IP 地址和用户代理的正确组合以匹配该会话 ID。当然,有成千上万的碰撞。但是您还必须为每种可能性提交一个 HTTP 请求,以便确定它是否匹配。你了解盐的概念吗?盐是针对 MD5 的碰撞攻击的直接对策。他们用体面的盐完全消除了它。
    【解决方案6】:

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

    • 预测
    • 捕获
    • 固定

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

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

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

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


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

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

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

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

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

    【讨论】:

    • 一种常见的方法是存储会话 ID(例如在数据库中),并在同一用户登录另一个经过身份验证的会话时使其无效 - 因此劫持者只有在会话的原始创建者不会创建新会话。
    • 好答案+1!然而,主要的巨大风险是凭据被盗,这使得关于会话的讨论完全无用,除非您仅使用 SSL 进行身份验证,然后通过会话身份验证继续。
    • 完全正确@gd1,在我看来,在他的阶段担心会话安全是微不足道的。真正的安全风险并非如此。
    • @crush 我不确定该选项是否好用,有时我的台式计算机和笔记本电脑可能会登录到同一台计算机。一次仅启用一次登录可能仅适用于某些特定应用程序
    • 使用随机生成的 30 多个字符的盐存储不可逆的散列密码,并使用托管在远程服务器上的私钥进行加密,这似乎是保证用户数据安全的普遍接受的方式服务器端数据泄露事件。
    【解决方案7】:

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

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

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

    【讨论】:

    • 感谢您的回答!不幸的是,我不得不将Chevi's标记为最好的,但它提供的信息要多得多。不过,我很感激你!
    猜你喜欢
    • 2012-04-27
    • 2012-04-12
    • 1970-01-01
    • 2017-10-09
    • 2012-07-22
    • 1970-01-01
    相关资源
    最近更新 更多