我想更多地了解 PHP Session Fixation和劫持以及如何防止这些问题。我一直在 Chris Shiflett 的网站上阅读以下两篇文章:
但是,我不确定我是否正确理解了事情。
为了帮助防止 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 标识符并能够发送请求的地方,就好像他们是该用户一样。这意味着,由于攻击者拥有标识符,因此就服务器而言,他们与有效用户几乎无法区分。
您无法直接阻止 session 劫持。但是,您可以采取步骤使其变得非常难以使用。
session.hash_function
在 php.ini
.如果 PHP < 5.3,设置为 session.hash_function = 1
对于 SHA1。如果 PHP >= 5.3,设置为 session.hash_function = sha256
或 session.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_name()
来完成的。在调用 session_start
之前使用您自己的标识符名称作为第一个参数. $_SERVER['HTTP_USER_AGENT']
在 session 中。基本上,当 session 开始时,将它存储在类似 $_SESSION['user_agent']
的地方。 .然后,在每个后续请求中检查它是否匹配。请注意,这可以伪造,因此它不是 100% 可靠,但总比没有好。 $_SERVER['REMOTE_ADDR']
在 session 中。基本上,当 session 开始时,将它存储在类似 $_SESSION['remote_ip']
的地方。 .某些为其用户使用多个 IP 地址的 ISP(例如 AOL 曾经这样做)可能会导致此问题。但是如果你使用它,它会更安全。攻击者伪造 IP 地址的唯一方法是在真实用户和您之间的某个时间点破坏网络。如果他们破坏了网络,他们的行为可能比劫持(例如 MITM 攻击等)更糟糕。 $_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/