PHP会话固定/劫持

me2*_*me2 145 php security session session-cookies

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

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

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

他还讨论了通过$ _GET使用在URL中传递的令牌来防止会话劫持.怎么会完全这样做?我猜测当有人登录时你生成他们的令牌并将其存储在会话变量中,然后在每个页面上你将该会话变量与$ _GET变量的值进行比较?

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

他们是一个防止劫持而不必在网址中传递值的好方法吗?这会更容易.

irc*_*ell 217

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

会话固定

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

有几种方法可以防止会话固定(完成所有这些操作):

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

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

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

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

会话劫持

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

您不能直接阻止会话劫持.但是,您可以采取措施使其变得非常困难和难以使用.

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

  • 发送一个强大的哈希:session.hash_bits_per_characterin php.ini.将此设置为session.hash_bits_per_character = 5.虽然这并没有让它更难破解,但是当攻击者试图猜测会话标识符时,它确实会有所不同.ID将更短,但使用更多字符.

  • 在文件中使用session.entropy_file和设置其他熵.例如,将前者设置为后者,将后者设置为将从熵文件读取的字节数.session.entropy_lengthphp.inisession.entropy_file = /dev/urandomsession.entropy_length = 256

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

  • 如果你真的是偏执狂,你也可以旋转会话名称,但要注意,如果你改变它,所有会话将自动失效(例如,如果你依赖于时间).但根据您的使用情况,它可能是一个选项......

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

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

  • 在会话中包含用户的IP地址$_SERVER['REMOTE_ADDR'].基本上,当会话开始时,将其存储在类似的东西中$_SESSION['remote_ip'].对于一些为其用户使用多个IP地址的ISP(例如AOL曾经这样做),这可能会有问题.但如果你使用它,它会更安全.攻击者伪造IP地址的唯一方法是在真实用户和您之间的某个时刻危及网络.如果他们妥协网络,他们可能会比劫持(比如MITM攻击等)更糟糕.

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

关于这两个的说明

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

会话ID重新生成

每当您使用session_regenerate_id旧会话重新生成会话标识符时都应删除.这与核心会话处理程序透明地发生.但是,一些使用的自定义会话处理程序session_set_save_handler()不会执行此操作,并且可以对旧会话标识符进行攻击.如果您使用自定义会话处理程序,请确保跟踪您打开的标识符,如果它与您保存的标识符不同,则明确删除(或更改)旧标识符上的标识符.

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

销毁会话

如果您要销毁会话(例如注销时),请确保彻底销毁它.这包括取消设置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();
}
Run Code Online (Sandbox Code Playgroud)

  • 每次更改会话变量时,我都不同意会话重新生成,只应在登录/注销时完成.检查用户代理也没有意义,检查REMOTE_ADDR是有问题的.我想补充的一点是`session.entropy_file =/dev/urandom`.PHP的内部熵生成被证明是非常弱的,并且/ dev/random或/ dev/uranom提供的熵池是没有硬件rng的Web服务器上最好的. (6认同)
  • 每个字符使用5而不是4位不会以任何方式改变"强度"(在这种情况下"强度"意味着什么).但是,虽然你的观点一般是可取的,但它们缺乏一些重要的细节.例如,与旧会话ID关联的会话会发生什么,或者在无效之后应如何处理具有旧会话ID的会话. (4认同)
  • 你还应该添加`session.cookie_httponly`和`session.cookie_secure`.第一个有助于阻止xss(但它并不完美).第二是阻止OWASP A9的最好方法...... (4认同)
  • 不理解这么好的答案,但缺少最重要的部分:使用SSL/HTTPS.计数器增量是一个问题的来源,多个请求相互之后快速,用户刷新页面两次或按两次提交按钮.现在,IP地址解决方案是所有移动用户和不断变化的IP的问题.您可以查看第一组IP,但它仍然在寻找麻烦.Best是阻止首先发现会话ID并使用SSL/HTTPS. (4认同)
  • @battal:不,那就是重点.`session_regenerate_id`不会使仍与旧ID相关联的会话无效; 仅当*delete\_old\_session*参数设置为true时,会话才会被销毁.但是如果攻击者发起了这个ID再生呢? (2认同)

Gum*_*mbo 37

两种会话攻击都有相同的目标:获得对另一个用户的合法会话的访问权限.但是攻击媒介是不同的:

在这两种攻击中,会话ID都是这些攻击所关注的敏感数据.因此,对于读访问(会话劫持)和写访问(会话固定),需要保护会话ID.

在这种情况下,使用HTTPS保护敏感数据的一般规则也适用.此外,您应该执行以下操作:

要防止会话固定攻击,请确保:

要防止会话劫持攻击,请确保:

要防止两种会话攻击,请确保:

  • 仅接受应用程序已启动的会话.您可以通过使用客户端特定信息对启动时的会话进行指纹识别来完成此操作.您可以使用用户代理 ID,但不要使用远程IP地址或可能在请求之间更改的任何其他信息.
  • session_regenerate_id(true)在身份验证尝试后(true仅在成功时)或更改权限时更改会话ID 并销毁旧会话.(确保存储的任何更改$_SESSION使用session_write_close 之前,如果你想保留相关的老ID的会话再生的ID;否则,只能使用新标识的会议将由这些变化的影响)
  • 使用正确的会话到期实现(请参阅如何在30分钟后使PHP会话到期?).


Mar*_*c B 6

你提到的令牌是"nonce" - 一次使用的号码.它们不一定只能使用一次,但是它们使用的时间越长,可以捕获和用于劫持会话的几率就越高.

nonce的另一个缺点是很难构建一个使用它们的系统,并允许在同一个窗体上有多个并行窗口.例如,用户在论坛上打开两个窗口,并开始处理两个帖子:

window 'A' loads first and gets nonce 'P'
window 'B' loads second and gets nonce 'Q'
Run Code Online (Sandbox Code Playgroud)

如果你无法跟踪多个窗口,你只能存储一个nonce - 窗口B/Q的nonce.当用户然后从窗口A提交他们的帖子并传入随机数'P'时,系统将拒绝该帖子为P != Q.

  • 他有一个有效的观点,特别是在同时使用许多AJAX请求的领域. (2认同)