목차

Spring Security

http

Session 폭증 문제

Spring Security는 로그인시 예외를 비롯해 많은 정보를 세션(HttpSession)에 저장한다.

이 경우 로그인이 공격 대상이 될 때 로그인 URL에서 세션을 폭발적으로 생성하게 되고 이로인해 메모리 폭증이 발생한다. 이는 결과적으로 다시 매우 잦은 Full GC를 유발하게 된다.

따라서 공격에 노출될 가능성이 있는 사이트는 최소한 로그인의 경우에 세션을 생성하지 않도록 다양한 처리가 필요하다. 혹은 세션을 생성하더라도 공격시도는 Spring Security를 타기전에 다른 방법으로 차단할 수 있어야 한다.

로그인시에 세션에 저장하는 값들은 WebAttributes의 상수들 참조.

설정에서 세션 생성하지 않도록

설정에서 create-session=“never” 를 준다

  <http ... create-session="never">

이렇게 하면 UsernamePasswordAuthenticationFilterallowSessionCreation 값 등이 false로 변경된다.

Expression Handler

global-method-security에 핸들러 지정

<global-method-security>
  <expression-handler ref="myMethodSecurityExpressionHandler"/>
</global-method-security>

http에 핸들러 지정

<!-- This must go before the http element in order to be used by security:authorize tags using the access attribute -->
<bean id="expressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
  <property name="roleHierarchy" ref="roleHierarchy" /> <!-- 꼭 필요한지는 의문 -->
</bean>
 
<security:http auto-config="true" use-expressions="true" access-decision-manager-ref="accessDecisionManager">
  ...
</security:http>
 
<!-- security:authorize tags using the url attribute will delegate to this accessDecisionManager -->
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
  <property name="decisionVoters">
    <list>
      <ref bean="webExpressionVoter" />
    </list>
  </property>
</bean>
 
<bean id="webExpressionVoter" class="org.springframework.security.web.access.expression.WebExpressionVoter">
  <property name="expressionHandler" ref="expressionHandler" />
</bean>
 
<!-- 꼭 필요한지는 의문 -->
<bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
  <property name="hierarchy">
    <value>
      ROLE_A > ROLE_B
      ROLE_B > ROLE_AUTHENTICATED
      ROLE_AUTHENTICATED >
      ROLE_UNAUTHENTICATED
    </value>
  </property>
</bean>

Access Denied Handler

Session에 예외 객체 저장현상

SpringSecurity는 로그인 혹은 권한 관련예외가 발생할 경우 세션에 해당 예외를 저장한다. (SimpleUrlAuthenticationFailureHandler의 saveException() 참조)

해당 예외는 WebAttributes.AUTHENTICATION_EXCEPTION의 값인 SPRING_SECURITY_LAST_EXCEPTION으로 저장된다.

문제는 기계화된 로그인 공격이 들어올 경우 모든 리퀘스트는 새로운 세션으로 간주되며 로그인 실패 예외들이 모두 세션에 저장되어 메모리 고갈을 일으킨다는 점이다. 이 때문에 AuthenticationFailureHandlerSimpleUrlAuthenticationFailureHandler를 상속하여 구현하면서 saveException()을 호출하지 않도록 하는 것이 좋다.

혹은 설정에서 create-session=“never” 를 준다

  <http ... create-session="never">

아예 세션에 로그인 실패 예외를 저장하지 않도록

saveException()을 호출하지 않도록 처리한 구현체를 다음과 같이 설정해 준다.

<form-login ... authentication-failure-handler-ref="AuthenticationFailureHandler구현체" />

이는 로그인 실패에 대한 것이며 권한 없음에 대한 예외는 다른 문제이다.

JSP에서 삭제

JSP에서 저장된 예외를 메시지 출력에 사용하는 경우가 있을 수 있는데, 이때는 JSP에서도 삭제하도록 해야 한다.

<c:remove var="SPRING_SECURITY_LAST_EXCEPTION" scope="session"/>

Session 직접 구현

@AuthenticationPrincipal

참고