引言

承接上一篇《Web应用安全————账号冻结与 Session 实时失效》关于 session 的学习,本篇博客聚焦如何通过 shiro 解决会话固定导致的漏洞问题。

首先,没怎么接触过应用安全方面的小伙伴可能会发起疑问 - 什么是会话固定?

简单来说,系统在登录前和登录后使用同一个 session id,就是会话固定,默认的session 管理机制都是会话固定的。会话固定可能会造成“会话固定攻击”(Session Fixation Attack)。这种攻击形式简单来说,有几种:

1、黑客先访问一个目标网站,在未登录的情况下,获得了一个 session id,然后将这个 session id 以钓鱼邮件的形式发给某个该网站的用户,用户缺乏信息安全意识,点击邮件中带有 session id 的连接并登录成功后,根据“会话固定”的登录前和登录后 session id 保持不变的原理,黑客可以在一定时间内使用 这个 session id 绕过登录验证,操作该用户的个人账户。

2、黑客通过某种形式的网络抓包,在某个用户登录时,劫持到了 session id,待该用户登录成功后,根据“会话固定”的原理,黑客可以在一定时间内通过这个 session id 随意操作该用户的个人账户。

一、会话固定攻击演示

固定会话攻击实际上就是黑客通过某种方式获得了正常用户登录时的 session id,然后利用用户的登录操作,使 session id 生效,并绕过登录验证。由于在登录前,session id 会通过 cookie 保存到浏览器中,因此很容易被黑客窃取。

1、首先,普通用户打开登录页面,会获得一个由服务器响应携带而来的 session id cookie:

在浏览器的控制台,我们可以轻而易举的得到这个 session id,此时,由于还未登录,session id 是无法正常使用的,黑客通过某种方式,比如脚本,或者桌面监控等,获取到了这个 session id ,放入自己准备登录的工具中。这里我使用post man 来演示黑客端的登录操作。

2、黑客输入目标网站的首页地址,这时,应用会拦截请求并弹出登录页面,此时黑客同样会收到服务器返回的 session id,不过他不会使用这个 session id,而是将窃取来的 session id 拷贝到 cookie 中,等待用户的登录操作

3、紧接着,用户不知道自己的 session id 已经被窃取,依然执行了登录操作,并成功登录:

4、此时,黑客使用这个已经完成登录操作的 session id 再次执行首页的访问:

可以看到上面的 GIF,黑客仅仅是使用了一个 session id 就完成了对用户首页的访问,轻而易举地绕过了登录验证。如果这个用户是超级管理员,那么就可能对系统造成不小的伤害。

因此,为了解决这个会话固定的问题,必须在登录前和登录后刷新 session id ,并使登录前生成 的session 失效,这样,才不会让黑客利用会话固定绕过登录验证。

二、Shiro 防止会话固定

如果说上一篇文章可以是框架无关的操作,那么解决会话固定,就完全依赖于安全框架自身的一些封装方式。

在Shiro 中, session 的生成和保存是这样的:

1、shiro 检测到用户的请求,并生成 session,保存到缓存中 ,并将 session id 绑定在 response 的 cookie 中,响应回浏览器 。

2、用户携带 session id,完成登录操作后,服务器端就会更新 session 的状态,并将其 绑定到 Subject 中。

在登录前的 session 生成时,session 还不知道它要绑定到哪个用户上,仅仅是生成了一个标记了主机地址的SimpleSession 对象。当用户调用 shiro 的登录验证方法 login()的时候,完成正常的验证操作,Shiro 就会将这个 session 绑定到当前用户 Subject 中。

public void login(AuthenticationToken token) throws AuthenticationException {Subject subject = securityManager.login(this, token);......Session session = subject.getSession(false);if (session != null) {this.session = decorate(session);} else {this.session = null;}
}

因此,我的解决思路就是,在完成 login 方法后,注销掉当前的 session ,并重新获得一个 新的session ,绑定到 Subject 中。

/**
* 点击登录执行的动作
*/
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String loginVali() {// ...... 从request 中获取 username 和 passwordSubject currentUser = ShiroKit.getSubject();UsernamePasswordToken token = new UsernamePasswordToken(username, password.toCharArray());......currentUser.login(token);// 创建新的session 会话,并管理 shiro session idsessionProcessor.shiroSessionIdIntoPool();// Session 重置后,重新调用login()方法,其内部自动捆绑新的 session 到当前SubjectcurrentUser.login(token);return REDIRECT + "/";
}

这里我单独提取了一个方法,来完成这一操作:

注意,getSession() 方法需要我们传入一个参数,默认是 true,意思是,如果这个用户还没有session ,就为其创建一个新的 session,如果是false,那么就不为其创建。上图的红框内,我们首先获得了当前登录用户的 session 对象,并调用了 stop 方法,将其注销,再为用户生成 一个 新的 session 对象。其他的部分,主要是为了维护一个 session id 池,将用户名与 session id的对应关系保存在 一个 map 中,方便管理员用户找到其他用户的 session id,并执行相关操作。

注意,在生成新的 session 后,必须重复调用一下 login 方法,将其再次绑定到当前用户中

三、测试结果演示

用户打开登录界面,依然会获得一个服务端返回的 session id :

黑客窃取到这个 session id ,并拷贝到自己的登陆工具中(演示使用的是Post Man):

用户输入用户名和密码,登录到首页后,可以看到,虽然地址栏中使用了旧的 session id 完成登录操作,但是cookie 中的已经变成了新的 session id ,并为接下来的请求提供了新的 session :

此时,如果黑客使用旧的 session id 再次执行登录,就无法成功(请对比修改前的效果):

由此可见,我们在代码中刷新了 session 的操作已经成功。

总结

解决会话固定实际上就是在登录后,通过代码实现 session 的刷新(重新生成),保证登录前后使用不同的 session id 即可。虽然新的 session id 依然有可能被黑客窃取,但相对于固定的 session id ,也算在一定程度上提升了系统的安全性

在解决会话固定的时候,我考虑了很多问题。

最初并不了解会话固定需要解决的最关键问题是什么,误以为只需要将用户过去的 session 注销即可,实则不然。导致这个想法的原因是由于我发现,当用户没有安全退出,而是直接关闭浏览器后,服务器端的 session 无法主动注销,需要等待到超时时间后,再执行注销操作。因此在 session 的处理方法中,我在用户 登录之后,先根据用户名 找到他上次没有注销,且未超时的 session ,并将其注销。但这还不是“会话固定”。

后来我了解到了会话固定实际上是登录前后拥有相同的 session id ,才意识到,注销以前使用过的 session 并没有真正解决了 session 会话固定的问题。

于是我开始思考在 Shiro 中如何创建新的 session,我本以为需要继承 DefaultSessionManager 或其子类并重写doCreateSession(SessionContext context) 方法,然后代替DefaultWebSessionManager 装载到 SecurityManager 中,但我发现 SessionContext 好像很难从请求中 手动构造出来(需要重写好几层继承关系的逻辑链),把整个 session 的创建过程和保存过程梳理了好几遍,都没找到很好的切入点,最后,还是通过 Subject 的 getSession 方法 发现了可执行的方案。

注销掉原来的 session 并通过 getSession(true) 方法成功刷新了 session 之后,我又发现,在重定向的时候,会导致系统找不到用户请求中的 session id,也就是说,我新生成的 session ,用户并没有成功接收到它的 session id。于是我又开始思考如何将 session id 放入 cookie 中返回给浏览器。但实际上,并不是如此,在生成session 的时候,SessionManager就已经将 session id 放入到了 response 的 cookie 中

其实是用户和新生成的 session 并没有形成绑定,于是我又开始研究 Shiro 的 login()方法究竟做了哪些工作,这才发现,login 实际上在验证完成用户之后,会把已经生成的 session 绑定 到当前 Subject 上,于是,这才有了两次调用 login() 的操作。

 currentUser.login(token);// 创建新的session 会话,并管理 shiro session idsessionProcessor.shiroSessionIdIntoPool();// Session 重置后,重新调用login()方法,其内部自动捆绑新的 session 到当前SubjectcurrentUser.login(token);

虽然实际修改的代码就只有两三行,但不得不说,会话固定的修改过程真是充满了挑战,前后一刻不停整整花了2大天时间。不过,通过自己的思考和努力解决一个问题真的非常有成就感。

综上,就是通过 Shiro 解决会话固定问题的全过程,欢迎大家文末留言。

Web应用安全————Shiro 解决会话固定漏洞相关推荐

  1. 如何修复会话固定漏洞_PHP安全漏洞:会话劫持,跨站点脚本,SQL注入以及如何修复它们...

    如何修复会话固定漏洞 PHP中的安全性 (Security in PHP) When writing PHP code it is very important to keep the followi ...

  2. 会话固定漏洞详解与YXcms会话固定漏洞复现

    在日常的渗透测试工作中经常发现会话固定漏洞,但是由于实际危害较小,多数情况下并没有把该漏洞写进报告中 一.漏洞原理 漏洞的本质用一句话来说是把一个无效的或者说低权限的令牌提升为高权限的令牌,而这个令牌 ...

  3. 任意文件上传mysql_[代码审计]XiaoCms(后台任意文件上传至getshell,任意目录删除,会话固定漏洞)...

    0x00 前言 这段时间就一直在搞代码审计了.针对自己的审计方法做一下总结,记录一下步骤. 审计没他,基础要牢,思路要清晰,姿势要多且正. 下面是自己审计的步骤,正在逐步调整,寻求效率最高. 0x01 ...

  4. java会话固定漏洞_会话劫持和会话固定

    我们的asp.net应用程序有Session劫持和Session固定问题 . 我们也实施了SSL . 1 ..我在web.config文件中添加了以下代码 . protection="All ...

  5. Web安全-HTTP响应拆分(CRLF注入)漏洞

    文章目录 漏洞简介 漏洞利用 会话固定 XSS攻击 实战案例 挖掘技巧 漏洞防御 漏洞简介 CRLF 是 CR 和 LF 两个字符的拼接,它们分别代表 "回车+换行"(\r\n), ...

  6. 漏洞:会话固定攻击(session fixation attack)

    什么是会话固定攻击? 会话固定攻击(session fixation attack)是利用应用系统在服务器的会话ID固定不变机制,借助他人用相同的会话ID获取认证和授权,然后利用该会话ID劫持他人的会 ...

  7. web漏洞--会话管理漏洞

    目录 1.会话劫持 2.会话固定 1.会话劫持 1.概念 会话劫持(Session hijacking),这是一种通过获取用户Session ID后,使用该Session ID登录目标账号的攻击方法, ...

  8. 如何防范 PHP安全的方式-session会话劫持与会话固定 ?

    一.概述 对于Web应用程序来说,加强安全性的第一条原则就是--不要信任来自客户端的数据,一定要进行数据验证以及过滤才能在程序中使用,进而保存到数据层.然而,由于Http的无状态性,为了维持来自同一个 ...

  9. Web 应用程序的十大安全漏洞

    应用程序的安全性非常重要,解决安全问题的方法有很多,但一个有效的入门方法是解决 OWASP(开放 Web 应用程序安全项目)确定的十大安全问题.在本文中,我们将介绍当前应用程序的十大安全漏洞. OWA ...

最新文章

  1. CTO让我研究中台(一):阿里的“数据+业务”双中台架构
  2. expression tree to string
  3. elasticsearch 通过curl的操作
  4. stm32 输入捕获 测量脉宽
  5. creating server tcp listening socket 127.0.0.1:6379: bind No error
  6. Unity3D基础33:物理射线
  7. Linux格式化为物理卷,使用linux的pvs命令格式化输出物理卷信息报表
  8. 大学生计算机考试系统软件,我爱C”《大学计算机基础》考试系统学生端软件使用说明.doc...
  9. codeblock快捷键大全
  10. oracle连续周数,oracle周数计算
  11. 办公自动化工具-Excel文件、sheet合并工具
  12. 1946年第一台计算机在哪个国家面试,面试问题 计算机
  13. 移动端web和PC端web的区别汇总笔记
  14. 随身Q代理服务器大升级
  15. 数据库系统概论-第三章 关系数据库标准语言 SQL
  16. 小问题--电脑开机一连上网就总是会安装各种软件的问题及解决
  17. python 7-33 修理牧场 (25 分) PTA
  18. 华擎主板的网络唤醒设置。
  19. 参加计算机社团的英语作文,参加社团的英语作文短文欣赏
  20. 拓展:示波器使用_波形分析

热门文章

  1. 人工智能ai 学习_人工智能中学习代理的要素
  2. 硬核|定时任务的10种实现方案,满足你的不同需求!
  3. 面试官:你说说互斥锁、自旋锁、读写锁、悲观锁、乐观锁的应用场景?
  4. 算法复习第五章贪心法
  5. Lambda表达式及应用
  6. c语言程序设计基础1千克,c语言学习知识编程经典编辑题汇总整编.doc
  7. 字符串格式化成时间格式_JAVA | 常用的日期/时间格式化方式
  8. 华为硬件工程师社招机考题库_中级会计机考你了解吗?机考操作常见八大问题速看...
  9. linux命令history作用,Linux命令:history命令历史的管理及用法
  10. java 自旋方法_JAVA循环使用CAS实现自旋操作