JS

CSP (Content Security Policy) 란?

728x90

# CSP ?

웹 개발을 하다보면 이런 식의 오류를 마주할때가 있다

 

"refused to execute inline script because it violates the following content security policy directive ~ "

 

이런 류의 오류들의 원인은 CSP 를 위반했기 때문이다.

CSP (Content Security Policy) 에 대한 MDN 의 정의 문서를 보면 아래와 같이 서술되어 있다.

 

"Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft to site defacement to distribution of malware."

 

XSS 같은 Injection attack 으로 부터 사이트를 보호하기 위해 브라우저에서 정의하는 

일종의 "보안 정책" 같은 것이다.

어떤 웹 리소스만 허용할지를 정의해놓은 보안 정책인 것.

(XSS 에 대한 더 자세한 설명은 https://kevinthegrey.tistory.com/36 를 보기 바란다)

 

# 해결책

그러면 웹 개발을 하는 도중에 이런 오류가 발생하면 어떻게 처리 해야 될까

방법은 개발하는 웹 서버에 CSP 를 정의해주면 된다.

 

아래는 Express.js 를 기준으로 예시를 들었다.

 

Express 에서 제공하는 Middleware 중 helmet 이란 middleware 가 있다.

 

이 middleware 는 주로 Express 서버의 보안을 담당하며,

여러가지 HTTP header 를 설정함에 있어서 도움을 준다

 

그 중 helmet-csp 를 사용하면 아주 손쉽게 csp 에 대한 설정이 가능하다

 

예를 들면 아래와 같은 index.js 코드를 보면

 

- index.js

import dotenv from "dotenv";
dotenv.config();
import express from "express";
import helmet from "helmet";
import csp from "helmet-csp";
 
const PORT = process.env.PORT;
 
const app = express();
app.use(helmet());
app.use(
  csp({
    directives: {
      defaultSrc: ["'self'"],
      styleSrc: ["'self'"],
      scriptSrc: ["'self'"],
    },
  })
);
 
app.listen(PORT, () => {console.log(`Server is Listening on : http://localhost:${PORT}`)});
 
cs

 

helmet-csp 를 이용해서 

express 서버에 직접 csp 를 설정하는 것을 볼 수 있다.

(helmet-csp 에 대한 자세한 설명은 https://github.com/helmetjs/helmet/tree/master/middlewares/content-security-policy 를 보기 바란다)

 

그러면 csp 에 들어가는 directives 값들은 어떤 것이 있고,

defaultSrc, styleSrc 등의 의미는 무엇인지 알아보자.

 

# Directives 

csp 를 정의할 때, Directive 를 웹서버에 직접 지정해줘야 하는데,

Directives 는 어떤 도메인에서 어떤 웹 Resource 를 가져오는 것을 허용할지를 정의하는 것이다.

 

기본 적으로는 아래 같은 구문 형식 을 가지며, 

Content-Security-Policy: <policy-directive><policy-directive>
cs

 

예를 들면 이렇게 쓸 수 있다.

Content-Security-Policy: default-src <source>;
cs

 

default-src 대신에 font-src, style-src, script-src, img-src 등 매우 다양한 종류가 있다.

 

주된 몇가지만 살펴보면

 

-1) default-src : 다른 directive 값이 설정되지 않았거나, 잘못 설정되었을 때 사용되는 기본 값

 

-2) style-src : stylesheet 와 관련된 값을 설정한다 (css)

 

-3) script-src : Javascript 관련 설정을 한다

 

-4) img-src : image, favicon 과 관련된 설정을 한다.

 

이 외에도 여러종류가 있으며 더 많은 종류를 보고 싶으면 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy 를 보기 바란다.

 

 

이 각각의 directive 에 대한 값 설정은 11가지가 있으며,

대표적인것만 몇개 살펴보면

 

-1) 'self' : 현재 웹 서버를 실행하고 있는 URL scheme 과 동일한 값을 포함한 URL 만 허용한다. (기본 값으로 single quotation (') 가 반드시 붙어서 설정되야 한다)

 

-2) 'unsafe-inline' : 예를들면 html 에서 <script> 태그 내에 쓰이는 구문 이나, <style> 태그 내에 쓰이는 스타일 등을 허용할지를 정의한다. (이 값도 self 처럼 반드시 single quotation 이 있어야한다)

 

-3) <host-source> :  특정한 도메인을 직접 지정하는 방식이다.

예를 들면, fonts.googleapis.com, &  *.example.com, https://store.example.com 등 이 있다.  

이 값에 대한 더 다양한 종류와 자세한 내용을 보고 싶으면 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src 를 보기 바란다.

 

 

 

예를 들어서, 이렇게 구문을 썼다고 하면

Content-Security-Policy: img-src 'self';
cs

 

현재 운영하고 있는 웹서버의 동일한 도메인만 이미지를 가져오는 것이 허용된다.

라는 의미가 되고

 

 

또다른 예시로 아래 같이 쓰면

Content-Security-Policy: script-src 'self' 'unsafe-inline';
cs

inline script (<script>alert('good')</script> 같은) 를 허용하면서, 현재 운영하는 웹서버와 동일한 도메인에서만 JS 를 허용한다 라는 의미가 된다.

 

 

이런식으로 허용할 도메인 또는 범위에 대해서 직접 설정을 해주면

CSP 오류를 해결할 수 있게 된다.

 

 

 

 

 

 

- Reference

1. https://kevinthegrey.tistory.com/36

2. https://github.com/helmetjs/helmet/tree/master/middlewares/content-security-policy

3. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy

4. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src

5. https://developer.squareup.com/blog/content-security-policy-for-single-page-web-apps/

6. https://github.blog/2016-04-12-githubs-csp-journey/

 

728x90

'JS' 카테고리의 다른 글

Prisma Migration 관련 오류  (0) 2020.09.03
Prisma 란?  (0) 2020.08.30
#33 가지 Javascript 필수 개념 - 5. Equals  (0) 2020.08.22
CORS (Cross Origin Resource Sharing)  (0) 2020.08.19
Axios 와 Fetch  (0) 2020.08.06