[java] Apache Shiro와 CSRF 공격 방어

목차

CSRF 공격이란?

CSRF(Cross-Site Request Forgery) 공격은 인터넷 사용자의 웹 브라우저를 통해 악의적인 요청을 실행하는 공격입니다. 이 공격은 사용자가 로그인한 상태에서 사이트를 방문할 때, 공격자가 생성한 피싱 사이트를 통해 악성 스크립트가 실행되면서 사용자의 권한으로 요청을 보내는 것입니다. 이러한 CSRF 공격으로부터 웹 애플리케이션을 보호하기 위해서는 적절한 방어 메커니즘을 구현해야 합니다.

Apache Shiro란?

Apache Shiro는 자바 기반의 오픈 소스 보안 프레임워크로, 인증, 권한 부여, 세션 관리 등의 보안 기능을 제공합니다. Shiro를 사용하면 애플리케이션의 보안 요구 사항을 간단하게 구현할 수 있습니다.

Apache Shiro를 이용한 CSRF 방어

Apache Shiro를 사용하여 CSRF 공격으로부터 애플리케이션을 보호하는 방법은 다음과 같습니다.

1. CSRF 토큰 사용

CSRF 토큰은 웹 페이지의 폼을 생성할 때 동적으로 생성되는 고유한 토큰입니다. 이 토큰은 사용자의 세션에 저장되고, 폼의 서브밋 요청에 포함되어 전송됩니다. 서버는 이 토큰을 검증하여 요청의 유효성을 확인합니다.

2. Shiro의 FormAuthenticationFilter 구성

Apache Shiro는 FormAuthenticationFilter를 사용하여 사용자 인증 요청을 처리합니다. 이 필터를 설정하여 CSRF 토큰을 생성하고, 요청마다 토큰을 검증하는 기능을 구현할 수 있습니다.

예를 들어, 다음과 같이 FormAuthenticationFilter의 서브 클래스를 작성하여 CSRF 토큰 검증을 수행할 수 있습니다.

public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {
    
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        if (isLoginSubmission(request, response)) {
            String csrfToken = request.getParameter("csrfToken");
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            HttpSession session = httpRequest.getSession(false);
            
            if (csrfToken != null && session != null) {
                String sessionToken = (String) session.getAttribute("csrfToken");
                
                if (csrfToken.equals(sessionToken)) {
                    return super.onAccessDenied(request, response);
                }
            }
            
            return false;
        }
        
        return super.onAccessDenied(request, response);
    }
}

3. Shiro 필터 체인 설정

Shiro는 servlet 필터 기반의 보안 메커니즘을 사용합니다. 따라서 웹 애플리케이션의 web.xml 파일에 Shiro 필터를 등록하여 보안 체인을 설정해야 합니다. CSRF 토큰 검증을 수행하는 커스텀 필터를 추가하고, 해당 필터를 필터 체인에 등록합니다.

<filter>
    <filter-name>customFormAuthenticationFilter</filter-name>
    <filter-class>com.example.CustomFormAuthenticationFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>customFormAuthenticationFilter</filter-name>
    <url-pattern>/login</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

결론

Apache Shiro를 이용하여 CSRF 공격으로부터 애플리케이션을 보호할 수 있습니다. 애플리케이션에 Shiro를 사용하여 보안 인증과 권한 부여 기능을 구현하면서 동시에 CSRF 방어도 간편하게 구현할 수 있습니다.