如何防止PHP会话在不同的Apache虚拟主机之间共享?
我在Apache 2.2上设置了不同的虚拟主机,并且一切运行正常,直到我意识到默认情况下共享PHP会话。
编辑也是您始终应设置session_save_path(http://php.net/manual/en/function.session-save- path.php)或使用数据库会话处理(http://php.net/manual)的原因/en/class.sessionhandler.php)(如果您位于共享的虚拟主机上)。有人可以在该站点上创建会话ID,并将其chmod更改为777,然后在您的站点上使用该会话ID绕过登录名或获得更多特权。它也可以用于SQL注入。
之所以可行,是因为PHP不会强制执行哪个会话ID属于哪个站点。我知道这一点是因为我已经分析了PHP会话背后的C / C ++源代码,并且因为我想知道这怎么可能。因此,永远不要过分相信$_SESSION阵列在共享虚拟主机上是安全的,并且您不能在SQL查询中安全地使用此值。
$_SESSION
来自C函数的PHP中的一些代码(文件session.c)php_session_start();是的,session_start()从PHP 调用时会调用此函数(并且我看到的唯一检查是在以下代码行中):
php_session_start()
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; } }
唯一的检查是HTTP标头“ HTTP_REFERER”,但是我们都知道它可以被伪造,因此这就是“通过隐蔽性实现的安全性”。唯一安全的方法是使用session_save_path或使用数据库会话处理程序。
session_save_path
要在php.ini中设置session_save_path,您应该在http://php.net/manual/en/session.configuration.php上找到更多信息。
或者,如果PHP作为Apache模块运行,则可以在vhost容器的htaccess文件中对其进行配置:
php_value session.save_path "path"
甚至更好的是每个虚拟主机一个PHPINIDir:
<VirtualHost ip> [...] PHPINIDir /var/www/... [...] </VirtualHost>
更新[Panique]:
我只是将完整的解决方案添加到此答案中,因为这可能也会对其他人有所帮助。完整的虚拟主机设置示例:
<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>