简体   繁体   English

如何防止在不同的apache vhost之间共享PHP会话?

[英]How to prevent PHP sessions being shared between different apache vhosts?

How to prevent PHP sessions from being shared between different Apache vhosts? 如何防止PHP会话在不同的Apache虚拟主机之间共享?

I've set up different vhosts on an Apache 2.2 and everything works perfectly, until I realized that the PHP sessions are shared by default. 我在Apache 2.2上设置了不同的虚拟主机,一切运行正常,直到我意识到默认情况下共享PHP会话。

Edit is also the reason why you ALWAYS should set your session_save_path ( http://php.net/manual/en/function.session-save-path.php ) or use database session handling ( http://php.net/manual/en/class.sessionhandler.php ) if you are on an shared webhosting. 编辑也是你总是应该设置session_save_path( http://php.net/manual/en/function.session-save-path.php )或使用数据库会话处理的原因( http://php.net/manual /en/class.sessionhandler.php )如果您使用的是共享虚拟主机。 Somebody can create an session id on there site and chmod it to 777 and use that session id on your site to bypass logins/or get more privileges. 有人可以在那里创建会话ID并将其chmod到777并在您的站点上使用该会话ID来绕过登录/或获得更多权限。 It can also be used for SQL injections. 它也可以用于SQL注入。

This works because PHP doesn't enforce what session IDs belongs to what site. 这是有效的,因为PHP不强制哪些会话ID属于哪个站点。 I know this because I've analysed the C/C++ source code behind sessions in PHP, and because I wondered how this could be possible. 我知道这是因为我已经在PHP中分析了会话背后的C / C ++源代码,因为我想知道这是如何实现的。 So never put too much trust that the $_SESSION array is safe on shared web hosting and you can't safely use this value in a SQL query. 因此,永远不要太信任$_SESSION数组在共享Web主机上是安全的,并且您无法在SQL查询中安全地使用此值。

Some code (file session.c) in PHP from C function php_session_start() ; PHP中的一些代码(文件session.c)来自C函数php_session_start() ; yes, this function is called when you call session_start() from PHP (and the only check I saw was in these lines of code): 是的,当你从PHP调用session_start()时调用这个函数(我看到的唯一的检查是在这些代码行中):

/* Check whether the current request was referred to by
 * an external site which invalidates the previously found id. */

if (PS(id) &&
        PS(extern_referer_chk)[0] != '\0' &&
        PG(http_globals)[TRACK_VARS_SERVER] &&
        zend_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_REFERER", sizeof("HTTP_REFERER"), (void **) &data) == SUCCESS &&
        Z_TYPE_PP(data) == IS_STRING &&
        Z_STRLEN_PP(data) != 0 &&
        strstr(Z_STRVAL_PP(data), PS(extern_referer_chk)) == NULL
) {
    efree(PS(id));
    PS(id) = NULL;
    PS(send_cookie) = 1;
    if (PS(use_trans_sid) && !PS(use_only_cookies)) {
        PS(apply_trans_sid) = 1;
    }
}

The only check is the HTTP Header "HTTP_REFERER", but we all know it can be faked, so this is "security through obscurity". 唯一的检查是HTTP标头“HTTP_REFERER”,但我们都知道它可以伪造,因此这是“通过默默无闻的安全性”。 The only safe method is to use session_save_path or use a database session handler. 唯一安全的方法是使用session_save_path或使用数据库会话处理程序。

To set session_save_path in the php.ini, you should find more information here http://php.net/manual/en/session.configuration.php . 要在php.ini中设置session_save_path,您可以在http://php.net/manual/en/session.configuration.php找到更多信息。

Or, if PHP is running as an Apache module, you can configure it in the htaccess file of vhost container: 或者,如果PHP作为Apache模块运行,您可以在vhost容器的htaccess文件中配置它:

php_value session.save_path "path"

Or even better a PHPINIDir per vhost: 甚至更好的是每个vhost的PHPINIDir:

<VirtualHost ip>
[...]
PHPINIDir /var/www/...
[...]
</VirtualHost>

UPDATE [Panique]: 更新[Panique]:

I'm just adding the full solution to this answer, as this might help other people too. 我只是在这个答案中添加完整的解决方案,因为这也可以帮助其他人。 A sample full vhost setup: 示例完整vhost设置:

<VirtualHost *:81>
    DocumentRoot /var/www/xxx1
    <Directory "/var/www/xxx1">
        AllowOverride All
        php_value session.save_path "/var/mysessionforproject_1"
   </Directory>
</VirtualHost>

<VirtualHost *:82>
    DocumentRoot /var/www/xxx2
    <Directory "/var/www/xxx2">
        AllowOverride All
        php_value session.save_path "/var/mysessionforproject_2"
   </Directory>
</VirtualHost>

Something is very wrong with your browser if it's sending cookies across domains. 如果它是跨多个域发送Cookie中的某些是非常错误的与您的浏览器。

Certainly both vhosts using the default session handler will write their session files to the same directory - just override it in the Apache vhost config: 当然,使用默认会话处理程序的两个vhost都会将其会话文件写入同一目录 - 只需在Apache vhost配置中覆盖它:

<VirtualHost a.example.com>
    ...
    php_value session.save_path "2;/var/www/a.example.com/data"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM