本文主要讲一下session fixation attacks以及spring security对它的防范。

session fixation attacks

会话固定攻击,是利用那些登录前和登录之后sessionId没有变化的漏洞来获取登录态,进而获取用户的相关信息等。

servlet3.1规范

servlet3.1规范中,HttpServletRequest.java明确规定了一个changeSessionId的方法

tomcat-embed-core-8.5.23-sources.jar!/javax/servlet/http/HttpServletRequest.java

/**

* Changes the session ID of the session associated with this request. This

* method does not create a new session object it only changes the ID of the

* current session.

*

* @return the new session ID allocated to the session

* @see HttpSessionIdListener

* @since Servlet 3.1

*/

public String changeSessionId();

SessionAuthenticationStrategy

spring-security-web-4.2.3.RELEASE-sources.jar!/org/springframework/security/web/authentication/session/SessionAuthenticationStrategy.java

/**

* Allows pluggable support for HttpSession-related behaviour when an authentication

* occurs.

*

* Typical use would be to make sure a session exists or to change the session Id to guard

* against session-fixation attacks.

*

* @author Luke Taylor

* @since

*/

public interface SessionAuthenticationStrategy {

/**

* Performs Http session-related functionality when a new authentication occurs.

*

* @throws SessionAuthenticationException if it is decided that the authentication is

* not allowed for the session. This will typically be because the user has too many

* sessions open at once.

*/

void onAuthentication(Authentication authentication, HttpServletRequest request,

HttpServletResponse response) throws SessionAuthenticationException;

}

spring security 提供了SessionAuthenticationStrategy接口,用来在登陆成功之后的处理session相关逻辑,它有个抽象类AbstractSessionFixationProtectionStrategy

AbstractSessionFixationProtectionStrategy

spring-security-web-4.2.3.RELEASE-sources.jar!/org/springframework/security/web/authentication/session/AbstractSessionFixationProtectionStrategy.java

/**

* Called when a user is newly authenticated.

*

* If a session already exists, and matches the session Id from the client, a new

* session will be created, and the session attributes copied to it (if

* {@code migrateSessionAttributes} is set). If the client's requested session Id is

* invalid, nothing will be done, since there is no need to change the session Id if

* it doesn't match the current session.

*

* If there is no session, no action is taken unless the {@code alwaysCreateSession}

* property is set, in which case a session will be created if one doesn't already

* exist.

*/

public void onAuthentication(Authentication authentication,

HttpServletRequest request, HttpServletResponse response) {

boolean hadSessionAlready = request.getSession(false) != null;

if (!hadSessionAlready && !alwaysCreateSession) {

// Session fixation isn't a problem if there's no session

return;

}

// Create new session if necessary

HttpSession session = request.getSession();

if (hadSessionAlready && request.isRequestedSessionIdValid()) {

String originalSessionId;

String newSessionId;

Object mutex = WebUtils.getSessionMutex(session);

synchronized (mutex) {

// We need to migrate to a new session

originalSessionId = session.getId();

session = applySessionFixation(request);

newSessionId = session.getId();

}

if (originalSessionId.equals(newSessionId)) {

logger.warn("Your servlet container did not change the session ID when a new session was created. You will"

+ " not be adequately protected against session-fixation attacks");

}

onSessionChange(originalSessionId, session, authentication);

}

}

如果是servlet3.1的话,则spring security默认的SessionAuthenticationStrategy就是ChangeSessionIdAuthenticationStrategy

SessionManagementConfigurer

spring-security-config-4.2.3.RELEASE-sources.jar!/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java

/**

* Creates the default {@link SessionAuthenticationStrategy} for session fixation

* @return the default {@link SessionAuthenticationStrategy} for session fixation

*/

private static SessionAuthenticationStrategy createDefaultSessionFixationProtectionStrategy() {

try {

return new ChangeSessionIdAuthenticationStrategy();

}

catch (IllegalStateException e) {

return new SessionFixationProtectionStrategy();

}

}

ChangeSessionIdAuthenticationStrategy

spring-security-web-4.2.3.RELEASE-sources.jar!/org/springframework/security/web/authentication/session/ChangeSessionIdAuthenticationStrategy.java

/**

* Uses {@code HttpServletRequest.changeSessionId()} to protect against session fixation

* attacks. This is the default implementation for Servlet 3.1+.

*

* @author Rob Winch

* @since 3.2

*/

public final class ChangeSessionIdAuthenticationStrategy

extends AbstractSessionFixationProtectionStrategy {

private final Method changeSessionIdMethod;

public ChangeSessionIdAuthenticationStrategy() {

Method changeSessionIdMethod = ReflectionUtils

.findMethod(HttpServletRequest.class, "changeSessionId");

if (changeSessionIdMethod == null) {

throw new IllegalStateException(

"HttpServletRequest.changeSessionId is undefined. Are you using a Servlet 3.1+ environment?");

}

this.changeSessionIdMethod = changeSessionIdMethod;

}

/*

* (non-Javadoc)

*

* @see org.springframework.security.web.authentication.session.

* AbstractSessionFixationProtectionStrategy

* #applySessionFixation(javax.servlet.http.HttpServletRequest)

*/

@Override

HttpSession applySessionFixation(HttpServletRequest request) {

ReflectionUtils.invokeMethod(this.changeSessionIdMethod, request);

return request.getSession();

}

}

通过反射调用changeSessionId方法,具体是调用Request#changeSessionId

Request#changeSessionId

tomcat-embed-core-8.5.23-sources.jar!/org/apache/catalina/connector/Request.java

/**

* Changes the session ID of the session associated with this request.

*

* @return the old session ID before it was changed

* @see javax.servlet.http.HttpSessionIdListener

* @since Servlet 3.1

*/

@Override

public String changeSessionId() {

Session session = this.getSessionInternal(false);

if (session == null) {

throw new IllegalStateException(

sm.getString("coyoteRequest.changeSessionId"));

}

Manager manager = this.getContext().getManager();

manager.changeSessionId(session);

String newSessionId = session.getId();

this.changeSessionId(newSessionId);

return newSessionId;

}

这里调用了manager.changeSessionId(session)

ManagerBase#changeSessionId(session)

tomcat-embed-core-8.5.23-sources.jar!/org/apache/catalina/session/ManagerBase.java

@Override

public void changeSessionId(Session session) {

String newId = generateSessionId();

changeSessionId(session, newId, true, true);

}

protected void changeSessionId(Session session, String newId,

boolean notifySessionListeners, boolean notifyContainerListeners) {

String oldId = session.getIdInternal();

session.setId(newId, false);

session.tellChangedSessionId(newId, oldId,

notifySessionListeners, notifyContainerListeners);

}

/**

* Generate and return a new session identifier.

* @return a new session id

*/

protected String generateSessionId() {

String result = null;

do {

if (result != null) {

// Not thread-safe but if one of multiple increments is lost

// that is not a big deal since the fact that there was any

// duplicate is a much bigger issue.

duplicates++;

}

result = sessionIdGenerator.generateSessionId();

} while (sessions.containsKey(result));

return result;

}

StandardSessionIdGenerator#generateSessionId

tomcat-embed-core-8.5.23-sources.jar!/org/apache/catalina/util/StandardSessionIdGenerator.java

public class StandardSessionIdGenerator extends SessionIdGeneratorBase {

@Override

public String generateSessionId(String route) {

byte random[] = new byte[16];

int sessionIdLength = getSessionIdLength();

// Render the result as a String of hexadecimal digits

// Start with enough space for sessionIdLength and medium route size

StringBuilder buffer = new StringBuilder(2 * sessionIdLength + 20);

int resultLenBytes = 0;

while (resultLenBytes < sessionIdLength) {

getRandomBytes(random);

for (int j = 0;

j < random.length && resultLenBytes < sessionIdLength;

j++) {

byte b1 = (byte) ((random[j] & 0xf0) >> 4);

byte b2 = (byte) (random[j] & 0x0f);

if (b1 < 10)

buffer.append((char) ('0' + b1));

else

buffer.append((char) ('A' + (b1 - 10)));

if (b2 < 10)

buffer.append((char) ('0' + b2));

else

buffer.append((char) ('A' + (b2 - 10)));

resultLenBytes++;

}

}

if (route != null && route.length() > 0) {

buffer.append('.').append(route);

} else {

String jvmRoute = getJvmRoute();

if (jvmRoute != null && jvmRoute.length() > 0) {

buffer.append('.').append(jvmRoute);

}

}

return buffer.toString();

}

}

这段是tomcat生成sessionId的逻辑

小结

spring security通过SessionAuthenticationStrategy,在登录成功之后进行相关session处理,如果servlet3.1+,则使用ChangeSessionIdAuthenticationStrategy来更换sessionId,以防范session fixation attacks。

doc

php session fixation,聊聊session fixation attacks相关推荐

  1. Tomcat的SessionID引起的Session Fixation和Session Hijacking问题

    上一篇说到<Spring MVC防御CSRF.XSS和SQL注入攻击>,今天说说SessionID带来的漏洞攻击问题.首先,什么是Session Fixation攻击和Session Hi ...

  2. Spring Session - Cookie VS Session VS Token 以及 Session不一致问题的N种解决方案

    文章目录 Cookie VS Session VS Token History Cookie Session Token Session不一致问题 Session不一致解决方案 nginx sessi ...

  3. session传递参数_分布式 Session 之 Spring Session 架构与设计

    作者 | 李增光 杏仁后端工程师.「只有变秃,才能变强!」 ​前言 开始进行 Web 开发时,我们可能会遇到这样的情况,当服务器重启之后,之前的登录状态会失效需要重新登录.又或者你的应用程序部署了不止 ...

  4. Session分布式共享 = Session + Redis + Nginx

    一.Session 1.Session 介绍 我相信,搞Web开发的对Session一定再熟悉不过了,所以我就简单的介绍一下. Session:在计算机中,尤其是在网络应用中,称为"会话控制 ...

  5. php session 域,PHP session 跨子域问题总结

    今天,做项目时候遇到个问题.之前做东西的时候session一般就直接存在数据库中这样就能解决跨域 不仅仅是跨子域,但是今天遇到这个问题是,自己要在别人现有的东西上面做修改.由于仅仅是子域 当时就行肯定 ...

  6. session、flask session知识的相关收集

    1.打开两个浏览器窗口访问应用程序会使用同一个session还是不同的session session cookie是不能跨窗口使用的,当你新开了一个浏览器窗口进入相同页面时,系统会赋予你一个新的ses ...

  7. 利用spring session解决共享Session问题

    https://blog.csdn.net/patrickyoung6625/article/details/45694157 1.共享Session问题 HttpSession是通过Servlet容 ...

  8. 深度实现session【包括session入库、session机制和session和cookie的使用方法,完善会话机制(在分布式机器中也能使用)】、无限分类的实现...

    1.session的注意点: @session_start();//这个配置需要注意,session开启中会有影响,所以使用错误抑制符进行限制[并且使用php.ini对session进行自动开启] s ...

  9. 单点登录实现(spring session+redis完成session共享)

    一.前言 项目中用到的SSO,使用开源框架cas做的.简单的了解了一下cas,并学习了一下 单点登录的原理,有兴趣的同学也可以学习一下,写个demo玩一玩. 二.工程结构 我模拟了 sso的客户端和s ...

  10. 将登录等信息保存到session中和退出session

    做项目时,可能会将某些信息保存在session中,如登录等信息,这样方便在某些页面使用这些保存的信息. 要想保存这些信息,需要创建一个类,该类里面定义需要保存的变量等信息,当登录后就通过new一个该类 ...

最新文章

  1. 数字电路中时钟抖动 Jitter 和 偏移 Skew
  2. 《MANAGING THE DEVELOPMENT OF LARGE SOFTWARE SYSTEMS》总结
  3. 你的微博也被盗赞?试试HSTS强制HTTPS加密
  4. 李宏毅的可解释模型——三个任务
  5. 循环链表:拉丁方阵问题
  6. 我与Python | 从Hacker到探索Deep Learning
  7. pandas 数据集的端到端处理
  8. 说说大型高并发高负载网站的系统架构
  9. ErrorPageRegistrar根据不同的错误类型显示网页
  10. 免费不加密:C++基础教程完整版视频(黑马程序员)
  11. php 2037时间问题
  12. Spring Cloud 微服务速成
  13. Simulink Resolver 旋转变压器解码仿真
  14. Ubuntu20.04设置静态IP
  15. CSDN 重新开放付费资源的上传了,但要求如下
  16. mysql有to char函数吗_mysql 类似to_char() to_date()函数
  17. Javascript显示隐藏DIV
  18. 十二、Vue项目 - 详情页动态路由、banner布局和公用图片画廊组件拆分
  19. 这款Shadertoy转换器,太牛逼了!
  20. 竞赛图强连通分量大小幂和计数 - 组合计数 - 多项式

热门文章

  1. 如何使用纯CSS将页面转换为繁体字
  2. 云计算时代:PC会消亡吗?
  3. dcdc低压升压直流稳压高压负电压输出12v24v转-50V100V110V150V200V250V300V350V400V500V
  4. 最简单容易的四格漫画制作软件 Comic Strip Factory for Mac
  5. 测试应该知道的知识-python检查死链
  6. Using ‘UTF-8‘ encoding to copy filtered resources. skip non existing resourceDirectory
  7. 谷歌Mediapipe运行环境配置
  8. 利用SHA-1算法和RSA秘钥进行签名验签(带注释)
  9. mac 端口被占用 解决方案
  10. 迅捷路由器设置找不到服务器,迅捷(FAST)路由器第一次怎么设置? | 192路由网