PHP 会话固定/劫持 [英] PHP Session Fixation / Hijacking

查看:18
本文介绍了PHP 会话固定/劫持的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to understand more about PHP Session Fixation and hijacking and how to prevent these problems. I've been reading the following two articles on Chris Shiflett's website:

但是,我不确定我是否理解正确.

However, I'm not sure I'm understanding things correctly.

为了帮助防止会话固定,在成功登录后调用 session_regenerate_id(true); 是否足够?我想我理解正确.

To help prevent session fixation, is it enough to call session_regenerate_id(true); after successfully logging someone in? I think I understand that correctly.

他还谈到了使用通过 $_GET 在 url 中传递的令牌来防止会话劫持.这将如何完成?我猜当有人登录时,您会生成他们的令牌并将其存储在会话变量中,然后在每个页面上将该会话变量与 $_GET 变量的值进行比较?

He also talks about using tokens passed along in urls via $_GET to prevent session hijacking. How would this be done exactly? I'm guessing when someone logs in you generate their token and store it in a session variable, then on each page you'd compare that session variable with the value of the $_GET variable?

这个令牌是否需要在每次会话或每次页面加载时更改一次?

Would this token need to be changed only once per session or on each page load?

还有一种无需在 URL 中传递值就可以防止劫持的好方法吗?这会容易很多.

Also is there a good way of preventing hijacking without having to pass a value along in the URLs? This would be a lot easier.

推荐答案

好吧,有两个独立但相关的问题,每个问题的处理方式都不一样.

Ok, there are two separate but related problems, and each is handled differently.

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

This is where an attacker explicitly sets the session identifier of a session for a user. Typically in PHP it's done by giving them a url like http://www.example.com/index...?session_name=sessionid. Once the attacker gives the url to the client, the attack is the same as a session hijacking attack.

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

There are a few ways to prevent session fixation (do all of them):

  • 设置session.use_trans_sid =0 在您的 php.ini 文件中.这将告诉 PHP 不要在 URL 中包含标识符,并且不要读取标识符的 URL.

  • Set session.use_trans_sid = 0 in your php.ini file. This will tell PHP not to include the identifier in the URL, and not to read the URL for identifiers.

设置session.use_only_cookies =1 在您的 php.ini 文件中.这将告诉 PHP 永远不要使用带有会话标识符的 URL.

Set session.use_only_cookies = 1 in your php.ini file. This will tell PHP to never use URLs with session identifiers.

在会话状态发生变化时重新生成会话 ID.这意味着以下任何一项:

Regenerate the session ID anytime the session's status changes. That means any of the following:

  • 用户认证
  • 在会话中存储敏感信息
  • 更改有关会话的任何内容
  • 等等...

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

This is where an attacker gets a hold of a session identifier and is able to send requests as if they were that user. That means that since the attacker has the identifier, they are all but indistinguishable from the valid user with respect to the server.

您无法直接阻止会话劫持.但是,您可以添加一些步骤,使其变得非常难以使用.

You cannot directly prevent session hijacking. You can however put steps in to make it very difficult and harder to use.

  • 使用强会话哈希标识符:php.ini 中的 session.hash_function.如果 PHP <5.3、SHA1设置为session.hash_function = 1.如果 PHP >= 5.3,设置为 session.hash_function = sha256session.hash_function = sha512.

  • Use a strong session hash identifier: session.hash_function in php.ini. If PHP < 5.3, set it to session.hash_function = 1 for SHA1. If PHP >= 5.3, set it to session.hash_function = sha256 or session.hash_function = sha512.

发送强哈希:<php.ini 中的 code>session.hash_bits_per_character.将此设置为 session.hash_bits_per_character = 5.虽然这不会使破解更难,但当攻击者试图猜测会话标识符时,它确实会有所作为.ID 会更短,但会使用更多字符.

Send a strong hash: session.hash_bits_per_character in php.ini. Set this to session.hash_bits_per_character = 5. While this doesn't make it any harder to crack, it does make a difference when the attacker tries to guess the session identifier. The ID will be shorter, but uses more characters.

使用 session 设置额外的熵.entropy_filesession.entropy_length 在您的 php.ini 文件中.将前者设置为session.entropy_file =/dev/urandom,后者设置为将从熵文件中读取的字节数,例如session.entropy_length = 256.

Set an additional entropy with session.entropy_file and session.entropy_length in your php.ini file. Set the former to session.entropy_file = /dev/urandom and the latter to the number of bytes that will be read from the entropy file, for example session.entropy_length = 256.

从默认的 PHPSESSID 更改会话的名称.这是通过使用您自己的调用 session_name() 来实现的标识符名称作为调用 session_start 之前的第一个参数.

Change the name of the session from the default PHPSESSID. This is accomplished by calling session_name() with your own identifier name as the first parameter prior to calling session_start.

如果您真的偏执,您也可以轮换会话名称,但请注意,如果您更改此名称(例如,如果您使其依赖于时间).但根据您的用例,它可能是一个选项...

If you're really paranoid you could rotate the session name too, but beware that all sessions will automatically be invalidated if you change this (for example, if you make it dependent on the time). But depending on your use-case, it may be an option...

经常轮换您的会话标识符.我不会在每个请求中都这样做(除非您真的需要那种安全级别),而是在随机的时间间隔内这样做.您希望经常更改此设置,因为如果攻击者确实劫持了会话,您不希望他们使用它太长时间.

Rotate your session identifier often. I wouldn't do this every request (unless you really need that level of security), but at a random interval. You want to change this often since if an attacker does hijack a session you don't want them to be able to use it for too long.

包括来自 $_SERVER['HTTP_USER_AGENT'] 的 用户代理 在会话中.基本上,当会话开始时,将其存储在类似 $_SESSION['user_agent'] 的地方.然后,在每个后续请求中检查它是否匹配.请注意,这可能是伪造的,因此不是 100% 可靠,但总比没有好.

Include the user agent from $_SERVER['HTTP_USER_AGENT'] in the session. Basically, when the session starts, store it in something like $_SESSION['user_agent']. Then, on each subsequent request check that it matches. Note that this can be faked so it's not 100% reliable, but it's better than not.

包括 来自 $_SERVER['REMOTE_ADDR'] 的用户 IP 地址 在会话中.基本上,当会话开始时,将它存储在类似 $_SESSION['remote_ip'] 的地方.某些为其用户使用多个 IP 地址的 ISP(例如 AOL 曾经这样做)可能会导致此问题.但是如果你使用它,它会更安全.攻击者伪造 IP 地址的唯一方法是在真实用户和您之间的某个时间点破坏网络.如果他们破坏了网络,他们的行为可能比劫持(例如 MITM 攻击等)糟糕得多.

Include the user's IP address from $_SERVER['REMOTE_ADDR'] in the session. Basically, when the session starts, store it in something like $_SESSION['remote_ip']. This may be problematic from some ISPs that use multiple IP addresses for their users (such as AOL used to do). But if you use it, it will be much more secure. The only way for an attacker to fake the IP address is to compromise the network at some point between the real user and you. And if they compromise the network, they can do far worse than a hijacking (such as MITM attacks, etc).

在会话中和浏览器端包含一个令牌,您可以经常增加和比较它.基本上,对于每个请求,在服务器端执行 $_SESSION['counter']++ .也在浏览器端的 JS 中做一些事情来做同样的事情(使用本地存储).然后,当您发送请求时,只需获取令牌的随机数,并验证该随机数在服务器上是否相同.通过这样做,您应该能够检测到被劫持的会话,因为攻击者不会有确切的计数器,或者如果他们有,您将有 2 个系统传输相同的计数并可以判断一个是伪造的.这不适用于所有应用程序,但它是解决问题的一种方法.

Include a token in the session and on the browsers side that you increment and compare often. Basically, for each request do $_SESSION['counter']++ on the server side. Also do something in JS on the browsers side to do the same (using a local storage). Then, when you send a request, simply take a nonce of a token, and verify that the nonce is the same on the server. By doing this, you should be able to detect a hijacked session since the attacker won't have the exact counter, or if they do you'll have 2 systems transmitting the same count and can tell one is forged. This won't work for all applications, but is one way of combating the problem.

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

The difference between Session Fixation and Hijacking is only about how the session identifier is compromised. In fixation, the identifier is set to a value that the attacker knows before hand. In Hijacking it's either guessed or stolen from the user. Otherwise the effects of the two are the same once the identifier is compromised.

每当您使用 session_regenerate_id 应删除旧会话.这与核心会话处理程序透明地发生.但是一些使用session_set_save_handler()的自定义会话处理程序 不要这样做,并且容易攻击旧的会话标识符.确保如果您使用自定义会话处理程序,请跟踪您打开的标识符,如果它与您保存的标识符不同,则明确删除(或更改)旧标识符上的标识符.

Whenever you regenerate the session identifier using session_regenerate_id the old session should be deleted. This happens transparently with the core session handler. However some custom session handlers using session_set_save_handler() do not do this and are open to attack on old session identifiers. Make sure that if you are using a custom session handler, that you keep track of the identifier that you open, and if it's not the same one that you save that you explicitly delete (or change) the identifier on the old one.

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

Using the default session handler, you're fine with just calling session_regenerate_id(true). That will remove the old session information for you. The old ID is no longer valid and will cause a new session to be created if the attacker (or anyone else for that matter) tries to use it. Be careful with custom session handlers though....

如果您要销毁会话(例如在注销时),请确保彻底销毁它.这包括取消设置 cookie.使用 session_destroy:

If you're going to destroy a session (on logout for example), make sure you destroy it thoroughly. This includes unsetting the cookie. Using 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 会话固定/劫持的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆