【问题标题】:PHP - Is $_SESSION[] a reliable way to secure php content?PHP - $_SESSION[] 是保护 php 内容的可靠方法吗?
【发布时间】:2018-02-04 10:42:19
【问题描述】:

我试图尽可能具体,但很抱歉我的问题可能涉及广泛。

我习惯了使用 $_GET['variable'] 发送变量的习惯,例如,假设我使用 ajax 从数据库中获取一些信息,我可能会这样做:

xmlhttp.open("GET","read.php?option=someoption",true);

然后我会根据它收到的$_GET['option'] 以不同的方式设置 PHP 页面。 然后我意识到任何 登录 用户都可以键入 URL 并直接修改数据库,因此我在每次重定向之前设置了一些额外的 $_SESSION['redirect'] 变量,以帮助防止从 URL 访问 php 页面。通过对“prevent.php”页面进行快速 ajax 调用,该页面会执行以下操作:

$_SESSION['redirect'] = "true";
header("Location: page.php");

然后在 page.php 中以这种方式设置,例如:

if ($_SESSION['redirect']==true) {
    // access the database
}
else {
   // deny access
} 

这是一种可靠的做事方式,还是有更专业的方式来解决?

【问题讨论】:

  • 一般情况下GET用于检索信息,POST用于修改。
  • 不,这不安全。
  • 您可以做两件事:1.) 当用户登录时保存会话中的权限或 2.) 当用户想要从数据库或文件执行操作时获取权限。当然,对于第二种方法,您必须事先在会话中保存用户 ID/用户名
  • 你可以这样做 如果用户已登录 && 具有管理员级别,应该从数据库中设置。然后blabla..!
  • 使用各种 RBAC,http://phprbac.net/ 很容易添加:s

标签: php


【解决方案1】:

不,这不是一种安全的方式。

以下是如何以最简单的形式实现安全用户系统的示例:

登录.php

<?php
session_start();

$user = isset($_POST['username']) ? $_POST['username'] : false;
$pass = isset($_POST['password']) ? $_POST['password'] : false; 

# Check credentials
if (validCredentials($user, $pass)) {
    # Credentials are valid

    # Set isAdmin session for the user 'admin'
    # This is hardcoded for simplicity but 
    # you could read a value from a database
    # and set this session dynamically.
    if ($user === 'admin') {
        $_SESSION['isAdmin'] = true;
    }

    # Generate CSRF token (see appendix)
    # heads up: random_bytes() is a PHP7 function.
    $_SESSION['token'] = bin2hex(random_bytes(32));

    # Set logged in session for every user
    $_SESSION['user'] = $user;

    echo 'Successfully logged in!<br />';
    echo '<a href="user-page.php">Go to the user page.</a>';
}

管理页面.php:

<?php
session_start();

if (isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true) {
    echo 'Only the admin can see this.';
} else {
    echo 'You are either not logged in or you don\'t have the permission to view this page.';
}

用户页面.php:

<?php
session_start();

if (isset($_SESSION['user'])) {
    $token = $_SESSION['token'];

    echo 'Only logged in users can see this. <br />';
    echo '<a href="safe-logout.php?token='.$token.'">Log me out</a>.';
} else {
    echo 'You are not logged in.';
}

附录

确保您保护自己免受CSRF attacks

例如,一种不安全的用户注销方式是:

注销.php:

<?php
session_start();

if (isset($_SESSION['user'])) {
    session_destroy();
}

也许您会问自己为什么这不安全。

原因是每个用户的注销链接都是相同的 (example.com/logout.php)。

所以猜测注销链接一点也不难(好吧,我们甚至不必猜测,我们已经确定了)。

攻击者可以伪装注销链接,一旦您单击它,您就会被注销。

了解注销只是一个示例,这一点非常重要。

考虑更严重的操作,例如删除用户等。

所以这个概念适用于经过身份验证的用户可以执行的每个操作

为安全起见,您可以在用户登录后立即生成令牌。

对于所采取的每一项操作,然后检查请求中的令牌是否与您生成的令牌匹配。

这样,每个用户 (example.com/loogut.php?token=random_token_generated_at_login) 的注销链接都是唯一的,攻击者很难猜到。

安全注销.php:

<?php
session_start();

if (isset($_SESSION['user'])) {
    # Check if the user specified token matches ours
    $token = isset($_GET['token']) ? $_GET['token'] : false;

    if ($_SESSION['token'] === $token) {
        session_destroy();

        echo 'Successfully logged out!';
    } else {
        # We dont logout because the token was not valid
    }
}

NOPOST 请求与 GET 请求一样容易受到影响。

因此,无论使用哪种 HTTP 方法,请务必检查每个操作的令牌。

【讨论】:

  • 否... 为什么要使用 unique 来生成随机会话令牌,以及为什么要散列它,尤其是使用 md5。只需使用 random_bytes() 即可生成安全的加密字节,甚至不需要散列,而且很难预测。让我们做一些数学运算,一个 32 字节的令牌可以代表 1E77 种组合。如果我们假设散列可以用每秒 100Giga 的散列来计算,我们仍然可以预期 1.8E58 年才能找到散列,一个 59 位的数字!当然,这只适用于真正随机的令牌。
  • 哈,我知道我会得到这样的评论。随时改进我的答案。
  • 添加了 random_bytes 是一个 PHP7 函数的注释——直到现在我才知道它存在 :) 谢谢!
  • 欢迎您,希望您的网站现在是安全的,无论如何,对于密码,您应该使用 password_hash,对于 random_tokens 使用 random_bytes(),对于其他内容,例如 persistent_login cookie 或密码重置链接您通过令牌客户端,您需要对这个 random_bytes 进行散列,例如,使用 hash('sha256'...) 来验证它,以防用户编辑。祝你好运!
  • 其中一位 cmets 说,“我认为在 GET 请求中使用 CSRF-token 的主要缺点之一是不称职的用户可能通过复制带有令牌的链接轻松地泄露他的令牌并将其粘贴到一些公共内容中,例如评论/帖子/等......此外,GET 查询参数包括通常由 HTTP 服务器/代理记录的 CSRF 令牌,它会带来另一个风险。”链接可以在这里找到stackoverflow.com/questions/23966927/…
猜你喜欢
  • 2016-03-01
  • 2011-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-19
相关资源
最近更新 更多