본문 바로가기

보안/Web

[ 보안 ] Content-Security-Policy - 보안 설정하기

반응형

브라우저 설정에서 Content-Security-Policy(CSP)를 설정하지 않았을 때의 보안 위험

Content-Security-Policy를 설정하지 않으면 웹 애플리케이션이 다양한 보안 위협에 노출될 수 있습니다. 주요 보안 위험은 다음과 같습니다.

  1. Cross-Site Scripting (XSS) 공격: 악성 스크립트가 사용자 브라우저에서 실행되어 세션 하이재킹, 피싱, 민감한 데이터 도용 등을 유발할 수 있습니다.
  2. 데이터 인젝션 공격: 공격자가 악성 데이터를 삽입해 권한 없는 접근이나 데이터 누출을 시도할 수 있습니다.
  3. 악성 콘텐츠 주입: 외부에서 삽입된 악성 자바스크립트, 스타일, 이미지 등이 허용되어 사용자에게 유해한 영향을 줄 수 있습니다.
  4. Clickjacking: 사용자가 클릭할 의도가 없는 링크를 클릭하게 유도하여 데이터 도용이나 악성 활동에 이용될 수 있습니다.

서버 환경별 Content-Security-Policy 설정 방법

각 서버 환경에서 Content-Security-Policy를 설정하는 방법은 다음과 같습니다.

1. Apache (httpd)

Apache에서 Content-Security-Policy를 설정하려면 .htaccess 파일 또는 메인 설정 파일에 헤더를 추가합니다.

# .htaccess 또는 apache2.conf, httpd.conf 파일에 추가
<IfModule mod_headers.c>
    Header set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self'"
</IfModule>

2. Apache Tomcat

Tomcat에서는 Filter를 작성하여 설정에 필요한 기능을 추가합니다.
Filter는 java로 작성됩니다.

작성된 Java code는 build 후 class 파일로 변환해서 참조 됩니다.
build 된 class 파일은 Web.xml과 같은 디렉터리인 'webapps/app/WEB-INF'에 '/classes/filters/' 경로에 위치 시키면 참조 됩니다.

예제

package filters;


import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.GenericFilter;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Cookie;


/**
 * Example filter that can be attached to either an individual servlet
 * or to a URL pattern.  This filter performs the following functions:
 * <ul>
 * <li>Attaches itself as a request attribute, under the attribute name
 *     defined by the value of the <code>attribute</code> initialization
 *     parameter.</li>
 * <li>Calculates the number of milliseconds required to perform the
 *     servlet processing required by this request, including any
 *     subsequently defined filters, and logs the result to the servlet
 *     context log for this application.
 * </ul>
 *
 * @author Craig McClanahan
 */
public final class ExampleFilter extends GenericFilter {


    private static final long serialVersionUID = 1L;


    /**
     * The request attribute name under which we store a reference to ourself.
     */
    private String attribute = null;


    /**
     * Time the processing that is performed by all subsequent filters in the
     * current filter stack, including the ultimately invoked servlet.
     *
     * @param request The servlet request we are processing
     * @param response The servlet response we are creating
     * @param chain The filter chain we are processing
     *
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet error occurs
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        // Store ourselves as a request attribute (if requested)
        if (attribute != null) {
            request.setAttribute(attribute, this);
        }

        //설정 코드
        if (response instanceof HttpServletResponse) {
            HttpServletResponse httpServletResponse = (HttpServletResponse) response;

            httpServletResponse.setHeader("Content-Security-Policy", "script-src 'self'; object-src 'self'; frame-ancesters 'self'");

        }

        // Time and log the subsequent processing
        long startTime = System.currentTimeMillis();
        chain.doFilter(request, response);
        long stopTime = System.currentTimeMillis();
        getServletContext().log(this.toString() + ": " + (stopTime - startTime) +
             " milliseconds");
    }


    @Override
    public void init() throws ServletException {
        this.attribute = getInitParameter("attribute");
    }


    /**
     * Return a String representation of this object.
     */
    @Override
    public String toString() {
        return "ExampleFilter(" + getFilterConfig() + ")";
    }
}

build 명령어는 servlet-api.jar를 참조하여 빌드합니다.

cd tomcat/webapps/app/WEB-INF

javac -classpath /home/user/apache-tomcat-9.0.97/lib/servlet-api.jar -d classes /home/user/apache-tomcat-9.0.97/webapps/examples/WEB-INF/classes/filters/ExampleFilter.java

Tomcat에서는 class 생성 후 web.xml에 필터를 추가해 설정할 수 있습니다.
'web.xml' 파일은 conf/, webapps/app/WEB-INF/ 에 위치해 있습니다.

conf/ : 모든 app에 적용됩니다.
webapps/app/WEB-INF : 개별 app에만 적용됩니다.


<filter>
    <filter-name>Example Filter</filter-name>
    <filter-class>filters.ExampleFilter</filter-class>
    <init-param>
        <param-name>attribute</param-name>
        <param-value>filters.ExampleFilter</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>Example Filter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

3. Nginx

Nginx에서는 nginx.conf 파일에 add_header 지시어를 사용하여 헤더를 설정합니다.

# nginx.conf 또는 server 블록에 추가
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self'";

이렇게 설정하여 웹 애플리케이션의 보안을 강화하고, XSS와 같은 다양한 공격을 예방할 수 있습니다.

반응형

'보안 > Web' 카테고리의 다른 글

[ 보안 ] Cookie - SameSite - 보안 설정하기  (0) 2024.11.11