PHP会话修复/劫持 [英] PHP Session Fixation / Hijacking

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

问题描述

我想进一步了解PHP 会话修复&劫持以及如何预防这些问题.我一直在Chris Shiflett的网站上阅读以下两篇文章:

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

  • Session Fixation
  • Session Hijacking

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

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 & store it in an 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 their a good way of preventing hijacking without having to pass a value along in the urls? this would be alot easier.

推荐答案

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

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

这是攻击者在此处为用户明确设置会话的会话标识符的地方.通常在PHP中,是通过给它们提供http://www.example.com/index...?session_name=sessionid之类的网址来完成的.一旦攻击者将网址提供给客户端,攻击就与会话劫持攻击相同.

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.

  • 使用强会话哈希标识符: session.hash_function php.ini中.如果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中的c10> .将此设置为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_file php.ini文件中的 session.entropy_length .将前者设置为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天全站免登陆