PHP session 固定/劫持

标签 php security session session-cookies

我想更多地了解 PHP Session Fixation和劫持以及如何防止这些问题。我一直在 Chris Shiflett 的网站上阅读以下两篇文章:

  • Session Fixation
  • Session Hijacking

  • 但是,我不确定我是否正确理解了事情。
    为了帮助防止 session 固定,拨打 session_regenerate_id(true); 是否足够?成功登录后?我想我理解正确。
    他还谈到了使用通过 $_GET 在 URL 中传递的 token 。以防止 session 劫持。这将如何完成?我猜当有人登录时,您会生成他们的 token 并将其存储在 session 变量中,然后在每个页面上将该 session 变量与 $_GET 的值进行比较。变量?
    每次 session 或每次加载页面时,此 token 是否只需要更改一次?
    还有一种防止劫持的好方法,而不必在 URL 中传递值吗?这会容易很多。

    最佳答案

    好的,有两个独立但相关的问题,每个问题的处理方式都不同。

    session 固定

    这是攻击者为用户显式设置 session 的 session 标识符的地方。通常在 PHP 中,它是通过给它们一个像 http://www.example.com/index...?session_name=sessionid 这样的 url 来完成的。 .一旦攻击者将 url 提供给客户端,则该攻击与 session 劫持攻击相同。

    有几种方法可以防止 session 固定(全部执行):

  • 套装 session.use_trans_sid = 0 在您的 php.ini文件。这将告诉 PHP 不要在 URL 中包含标识符,并且不要读取标识符的 URL。
  • 套装 session.use_only_cookies = 1 在您的 php.ini文件。这将告诉 PHP 永远不要使用带有 session 标识符的 URL。
  • 每当 session 状态发生变化时重新生成 session ID。这意味着以下任何一项:
  • 用户认证
  • 在 session 中存储敏感信息
  • 更改有关 session 的任何内容
  • 等等...

  • session 劫持

    这是攻击者获得 session 标识符并能够发送请求的地方,就好像他们是该用户一样。这意味着,由于攻击者拥有标识符,因此就服务器而言,他们与有效用户几乎无法区分。

    您无法直接阻止 session 劫持。但是,您可以采取步骤使其变得非常难以使用。
  • 使用强 session 哈希标识符: session.hash_function php.ini .如果 PHP < 5.3,设置为 session.hash_function = 1对于 SHA1。如果 PHP >= 5.3,设置为 session.hash_function = sha256session.hash_function = sha512 .
  • 发送强哈希: session.hash_bits_per_character php.ini .将此设置为 session.hash_bits_per_character = 5 .虽然这不会使破解变得更加困难,但当攻击者试图猜测 session 标识符时,它确实会有所作为。 ID 会更短,但会使用更多字符。
  • 使用 session.entropy_file 设置额外的熵和 session.entropy_length 在您的 php.ini文件。将前者设置为 session.entropy_file = /dev/urandom后者是将从熵文件中读取的字节数,例如 session.entropy_length = 256 .
  • 将 session 的名称从默认的 PHPSESSID 更改。这是通过拨打 session_name() 来完成的。在调用 session_start 之前使用您自己的标识符名称作为第一个参数.
  • 如果您是 真的偏执,您也可以轮换 session 名称,但请注意,如果您更改此名称(例如,如果您使其依赖于时间),所有 session 都将自动失效。但根据您的用例,它可能是一个选项...
  • 经常轮换您的 session 标识符。我不会每次请求都这样做(除非你 真的 需要那个级别的安全性),而是在随机的时间间隔。您希望经常更改此设置,因为如果攻击者确实劫持了 session ,您不希望他们能够使用它太长时间。
  • 包括 user agent from $_SERVER['HTTP_USER_AGENT'] 在 session 中。基本上,当 session 开始时,将它存储在类似 $_SESSION['user_agent'] 的地方。 .然后,在每个后续请求中检查它是否匹配。请注意,这可以伪造,因此它不是 100% 可靠,但总比没有好。
  • 包括 user's IP address from $_SERVER['REMOTE_ADDR'] 在 session 中。基本上,当 session 开始时,将它存储在类似 $_SESSION['remote_ip'] 的地方。 .某些为其用户使用多个 IP 地址的 ISP(例如 AOL 曾经这样做)可能会导致此问题。但是如果你使用它,它会更安全。攻击者伪造 IP 地址的唯一方法是在真实用户和您之间的某个时间点破坏网络。如果他们破坏了网络,他们的行为可能比劫持(例如 MITM 攻击等)更糟糕。
  • 在 session 中和浏览器端包含一个 token ,您经常增加和比较。基本上,对于每个请求做 $_SESSION['counter']++在服务器端。也在浏览器端的 JS 中做一些事情来做同样的事情(使用本地存储)。然后,当您发送请求时,只需获取 token 的随机数,并验证该随机数在服务器上是否相同。通过这样做,您应该能够检测到被劫持的 session ,因为攻击者不会有确切的计数器,或者如果他们有,您将有 2 个系统传输相同的计数并可以判断一个是伪造的。这不适用于所有应用程序,但它是解决问题的一种方法。

  • 关于两者的说明

    session 固定和劫持之间的区别仅在于 session 标识符如何被破坏。在固定中,标识符被设置为攻击者事先知道的值。在劫持中,它要么是从用户那里猜到的,要么是从用户那里窃取的。否则,一旦标识符被泄露,两者的影响是相同的。

    session ID 重新生成

    每当您使用 session_regenerate_id 重新生成 session 标识符时应该删除旧 session 。这与核心 session 处理程序透明地发生。然而有些custom session handlers using session_set_save_handler() 不要这样做,并且很容易攻击旧的 session 标识符。确保如果您使用自定义 session 处理程序,请跟踪您打开的标识符,如果它与您保存的标识符不同,则明确删除(或更改)旧标识符上的标识符。

    使用默认 session 处理程序,只需调用 session_regenerate_id(true) 就可以了。 .这将为您删除旧的 session 信息。旧 ID 不再有效,如果攻击者(或其他任何人)尝试使用它,则会导致创建新 session 。但是要小心自定义 session 处理程序......

    销毁 session

    如果您要销毁 session (例如在注销时),请确保彻底销毁它。这包括取消设置 cookie。使用 session_destroy :
    function destroySession() {
        $params = session_get_cookie_params();
        setcookie(session_name(), '', time() - 42000,
            $params["path"], $params["domain"],
            $params["secure"], $params["httponly"]
        );
        session_destroy();
    }
    

    关于PHP session 固定/劫持,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5081025/

    相关文章:

    php - 更改 WooCommerce 中的添加到购物车库存错误通知

    javascript - 使用 session Javascript 存储数据

    security - 如何进行最安全的Websocket认证

    security - 来自 S3 或其他地方的共享内容

    javascript - meteor 在 Session.set 之后触发一个事件

    javascript - PHP 订单 - 固定/可变小计行?

    php - 如何在 DSN 中指定用户名和密码?

    php - 制作链接提示 'save as'的简单方法

    database - 如何为 Django 应用程序配置数据库权限?

    php - 可能被盗的本地网络服务器上的双向加密