복붙노트

[SPRING] Spring Security 잘못된 remember-me 토큰 (시리즈 / 토큰) 불일치. 이전의 쿠키 도용 공격을 암시합니다.

SPRING

Spring Security 잘못된 remember-me 토큰 (시리즈 / 토큰) 불일치. 이전의 쿠키 도용 공격을 암시합니다.

나는 Spring Security3.1.2를 사용하는 GWT 애플리케이션을 가지고있다. UsernamePasswordAuthenticationFilter와 PersistentTokenBasedRememberMeServices를 사용하여 DB에 로그인을 유지하고있다. 또한, 나는 Tomcat PersistentManager를 사용하여 DB에 세션도 저장합니다. 이제 내 문제는 내가 로그인하려고 할 때마다 잘못된 remember-me 토큰 (시리즈 / 토큰) 불일치 CookieTheftException (아래 스택 추가)이 표시된다는 것입니다. tomcat_sessions 테이블에서 다음과 같이 세션을 삭제하려고했습니다.

나는 심지어 tomcat_sessions 테이블의 모든 레코드를 삭제하고 tomcat을 다시 시작할 때 tomcat_sessions가 이전에 삭제 한 모든 세션으로 채워지는 것을 발견했습니다.

또한 Spring persistent_logins 테이블의 모든 레코드를 삭제하고 PerscatentManager를 비활성화했지만 여전히 동일한 문제가 발생했습니다 ...

어떤 생각이 문제 일 수 있습니까? 고맙습니다

SEVERE: Servlet.service() for servlet [springMvcServlet] in context with path [/brate] threw exception
org.springframework.security.web.authentication.rememberme.CookieTheftException: Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack.
    at org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices.processAutoLoginCookie(PersistentTokenBasedRememberMeServices.java:102)
    at org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices.autoLogin(AbstractRememberMeServices.java:115)
    at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:97)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at com.brate.admin.server.servlet.crawler.GoogleBotFilter.doFilter(GoogleBotFilter.java:202)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:695)

해결법

  1. ==============================

    1.우리가 같은 페이지에 올랐 으면 먼저이 영구 토큰 메커니즘이 어떻게 작동하는지 이해하는 방법을 설명하기 위해 잠깐 시간을 갖습니다.

    우리가 같은 페이지에 올랐 으면 먼저이 영구 토큰 메커니즘이 어떻게 작동하는지 이해하는 방법을 설명하기 위해 잠깐 시간을 갖습니다.

    처음부터 시작 (persistent_logins 테이블의 항목 없음) :

    로그인 성공시 : 일부 임의 해시가있는 사용자에 대해 영구 토큰이 생성됩니다. 토큰 세부 사항이있는 사용자의 쿠키가 작성됩니다. 사용자에 대한 세션이 생성됩니다.

    사용자가 여전히 활성 세션을 가지고있는 한, 인증시 기억 기능이 호출되지 않습니다.

    사용자의 세션이 만료 된 후 : Remember me 기능이 시작되어 쿠키를 사용하여 데이터베이스에서 영구 토큰을 가져옵니다. 지속 된 토큰이 쿠키의 토큰과 일치하면 사용자가 인증되면 모두가 만족하며 새 임의의 해시가 생성되고 영구 토큰이 업데이트되고 이후의 요청에 대해 사용자의 쿠키가 업데이트됩니다.

    그러나 쿠키의 토큰이 지속 된 토큰의 토큰과 일치하지 않으면 CookieTheftException이 발생합니다. 토큰이 일치하지 않는 가장 일반적인 이유는 두 개 이상의 요청이 빠르게 연속해서 시작되었다는 것입니다. 첫 번째 요청이 통과하여 다음 요청에 대한 새 해시가 생성되지만 두 번째 요청에는 여전히 이전 토큰이 사용됩니다 따라서 예외가 발생합니다.

    CookieTheftException을 크게 피하려면 웹 응용 프로그램의 콘텐츠 (예 : 이미지, 글꼴, 스크립트 등)에 대한 요청이 스프링 인증 필터를 통과하지 않아야합니다. 이렇게하려면 일반 보안 구성 위에 다른 구성을 추가하고 리소스에 대한 요청에 대한 보안을 원하지 않도록 지정하십시오 (/ resources / ** 대신 관련 경로 사용).

    <http pattern="/resources/**" security="none"/>
    <http ... (normal config) ... 
    

    (Java Config의 경우 : JavaConfig에서 http "security = 'none'을 정의하려면 어떻게합니까?)

    데이터베이스에서 사용자의 토큰을 삭제하고 세션이 만료 된 경우 사용자는 다음 요청시 로그 아웃됩니다. 따라서 persistent_logins 테이블에있는 영구 토큰 (persistent_logins 테이블)이 자동으로 재생성되는 것에 대해 말하는 것은 거의 의미가 없으므로 필자는 이것이 사실이라고 의심합니다. PersistentTokenRepository의 createNewToken (PersistentRememberMeToken 토큰) 메소드는 로그인 성공시에만 호출됩니다.

    마지막으로 여전히 예외가 발생하는 경우 PersistentTokenBasedRememberMeServices에 대한 소스를 연결하고 processAutoLoginCookie 메소드에 중단 점을 넣어서 어떤 요청이 CookieTheftException의 원인인지 확인하는 데 도움이됩니다.

    이게 도움이 되길 바란다.

  2. ==============================

    2.나는 동일한 오류가 있었고 보안 체인이 무시되는 모든 요청에 ​​자동 로그인을 시도한다는 것을 알았습니다. 하고있는 것을 볼 수 있습니다.

    나는 동일한 오류가 있었고 보안 체인이 무시되는 모든 요청에 ​​자동 로그인을 시도한다는 것을 알았습니다. 하고있는 것을 볼 수 있습니다.

    public void configure(WebSecurity web) throws Exception {
        web
            .debug(true)
            .ignoring()
            .antMatchers("/css/**", "/js/**", "/img/**");
    }
    

    이 후 js 파일과 css 파일이 보안 체인을 건너 뛰는 것을 확인한 후에 필자는 이러한 매핑을 제거하고 필자가 생각한대로 작업을 시작했음을 기억합니다.

    public void configure(WebSecurity web) throws Exception {
        web
            .debug(true)
            .ignoring()
            .antMatchers("/img/**");
    }
    
  3. ==============================

    3.내 구성에 누락 된 부분은 RememberMeAuthenticationProvider입니다. (http://docs.spring.io/spring-security/site/docs/3.2.2.RELEASE/reference/htmlsingle/#remember-me-impls)

    내 구성에 누락 된 부분은 RememberMeAuthenticationProvider입니다. (http://docs.spring.io/spring-security/site/docs/3.2.2.RELEASE/reference/htmlsingle/#remember-me-impls)

    RememberMeAuthenticationProvider 패키지가 변경되었으며 문서와 동일하지 않습니다.

    PersistentTokenBasedRememberMeServices 및 RememberMeAuthenticationProvider에 대해 동일한 키를 정의하는 것을 잊지 마십시오.

    이것은 내 구성입니다.

    <s:http auto-config="false"
                use-expressions="true"
                create-session="ifRequired">
            <s:remember-me services-ref="rememberMeServices"
                           authentication-success-handler-ref="rememberMeAuthenticationSuccessHandler"/>
    ...
    </s:http>
    
     <bean id="rememberMeServices"
              class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
         <constructor-arg index="0" value="${remember.me.key}" />
    ...
    </bean>
    
    <bean id="rememberMeAuthenticationProvider" class=
            "org.springframework.security.authentication.RememberMeAuthenticationProvider">
            <property name="key" value="${remember.me.key}"/>
        </bean>
    
    <s:authentication-manager alias="authenticationManager">
            <s:authentication-provider ref="rememberMeAuthenticationProvider" />
    ...
        </s:authentication-manager>
    

    마커스 코치 (Markus Coetzee)는 정말로 나를 해결해 주었다. 감사!

  4. from https://stackoverflow.com/questions/20053107/spring-security-invalid-remember-me-token-series-token-mismatch-implies-previ by cc-by-sa and MIT license