资讯专栏INFORMATION COLUMN

聊聊session fixation attacks

fuchenxuan / 2638人阅读

摘要:序本文主要讲一下以及对它的防范。会话固定攻击,是利用那些登录前和登录之后没有变化的漏洞来获取登录态,进而获取用户的相关信息等。

本文主要讲一下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

Session fixation

会话固定攻击

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/11322.html

相关文章

  • odoo远程部署命令

    摘要:前提条件在源码中可以看到,部署命令的操作是将模块文件上传在运行中的执行安装操作。从帮助上看,部署命令的使用为模块路径网站用户名密码使用示例注意点阅读源码可以发现该命令只是安装或者升级模块的文件,并不会更新已经在运行的代码。阅读源码的cli模块发现一个远程部署模块的命令,在官方文档并没有说,发现隐藏功能! 解决的问题 在odoo里面写界面是很烦人的,每次写完需要重启服务器并且到app界面点击升...

    Youngdze 评论0 收藏0
  • token与sessionId的区别——学习笔记

    摘要:学开发半年多,之前一直有个疑问为什么要用,好好的用不好吗其实就是新技术与老技术,但是还是想弄懂这个问题之前一直疑惑,今天搞懂了,整合了一下学习过程,先对比一下与一简述的生成方式与的生成方式的生成方式浏览器第一次访问服务器时,服务器创建一个, 学开发半年多,之前一直有个疑问:为什么要用token,好好的用sessionID不好吗(其实就是新技术与老技术,但是还是想弄懂)这个问题之前一直疑...

    liaosilzu2007 评论0 收藏0
  • Python反序列化安全问题

    摘要:反序列化安全问题一这一段时间使用做开发,使用了存储,阅读了源码,发现在存储到过程中,利用了模块进行序列化以及反序列化正好根据该样例学习一波反序列化相关的安全问题,不足之处请各位表哥指出。 Python 反序列化安全问题(一) 这一段时间使用flask做web开发,使用了redis存储session,阅读了flask_session源码,发现在存储session到redis过程中,利用了...

    Amos 评论0 收藏0
  • CSRF攻击是什么并且如何防止

    摘要:,意为跨网站请求伪造,也有写为。攻击者伪造目标用户的请求,然后此请求发送到有漏洞的网站,网站执行此请求后,引发跨站请求伪造攻击。 CSRF(Cross Site Request Forgeries),意为跨网站请求伪造,也有写为XSRF。攻击者伪造目标用户的HTTP请求,然后此请求发送到有CSRF漏洞的网站,网站执行此请 求后,引发跨站请求伪造攻击。攻击者利用隐蔽的HTTP连接,让目标...

    Flands 评论0 收藏0

发表评论

0条评论

fuchenxuan

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<