๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๊ฐœ๋ฐœ ์ผ์ง€ ๐Ÿ‘ฉ‍๐Ÿ’ป

CSP(Content Security Policy)์— ๋Œ€ํ•˜์—ฌ

by chuyj15 2025. 5. 12.
728x90
๋ฐ˜์‘ํ˜•
SMALL

 

* java ์ฝ”๋“œ ์ค‘ filter์—๋‹ค๊ฐ€ csp๋ฅผ self๋กœ ์„ค์ •ํ•ด๋†“์•˜๋‹ค.

(springboot ํ”„๋กœ์ ํŠธ)

package .....;

import java.io.IOException;

import org.springframework.stereotype.Component;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletResponse;

@Component
public class CspHeaderFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        httpResponse.setHeader("Content-Security-Policy",
        "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'");

        chain.doFilter(request, response);
    }
}

 

๊ทธ๋žฌ๋”๋‹ˆ ๊ฐœ๋ฐœ์ž๋„๊ตฌ์—์„œ ์•„๋ž˜์™€ ๊ฐ™์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒ.

Refused to execute inline event handler because it violates 
the following Content Security Policy directive: 
"script-src 'self'". Either the 'unsafe-inline' keyword, 
a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution. 
Note that hashes do not apply to event handlers, style attributes and javascript: 
navigations unless the 'unsafe-hashes' keyword is present.

 

์œ„ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋Š” Content Security Policy(CSP) ์œ„๋ฐ˜์œผ๋กœ ์ธํ•ด ๋ฐœ์ƒํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฆ‰, ๋‚œ๋…ํ™” ํ›„์˜ JS ์ฝ”๋“œ์—์„œ onclick ๊ฐ™์€ inline ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋‚˜ <script> ํƒœ๊ทธ์— ์ง์ ‘ ์‚ฝ์ž…๋œ JS๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์–ด์„œ

๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ณด์•ˆ์„ ์œ„ํ•ด ์ด๋ฅผ ๊ฑฐ๋ถ€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๐Ÿ” ์›์ธ ์š”์•ฝ

CSP ์ •์ฑ…์ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค์ •๋˜์–ด ์žˆ์„ ๊ฒฝ์šฐ:

Content-Security-Policy: script-src 'self'

์ด ๊ฒฝ์šฐ์—๋Š”:

  • <button onclick="doSomething()"> โŒ ํ—ˆ์šฉ๋˜์ง€ ์•Š์Œ
  • <script>alert('hi')</script> โŒ ํ—ˆ์šฉ๋˜์ง€ ์•Š์Œ
  • <script src="/js/app.js"></script> โœ… ์™ธ๋ถ€ ํŒŒ์ผ์—์„œ๋งŒ ์‹คํ–‰ ๊ฐ€๋Šฅ

๐Ÿ›  ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

โœ… 1. Inline ์ด๋ฒคํŠธ ์ œ๊ฑฐ

๋ชจ๋“  inline ์ด๋ฒคํŠธ(onclick, onload, onmouseover ๋“ฑ)๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  JS ์ฝ”๋“œ๋กœ ๋ถ„๋ฆฌํ•˜์„ธ์š”.

๋ณ€๊ฒฝ ์ „:

html
<button onclick="doSomething()">Click</button>
 

๋ณ€๊ฒฝ ํ›„:

html
<button id="myBtn">Click</button> <script src="/js-dist/app.js"></script> <!-- ๋‚œ๋…ํ™”๋œ ์™ธ๋ถ€ ํŒŒ์ผ -->

 

js
// app.js ๋‚ด๋ถ€ document.getElementById('myBtn').addEventListener('click', doSomething);

โœ… 2. CSP ์ •์ฑ… ์™„ํ™” (๊ถŒ์žฅํ•˜์ง€ ์•Š์Œ)

์ •๋ง ๋ถˆ๊ฐ€ํ”ผํ•œ ๊ฒฝ์šฐ, CSP๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•˜๋ฉด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ๋ณด์•ˆ์ƒ ๊ถŒ์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค:

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

 

๋˜๋Š” ๋” ์•ˆ์ „ํ•˜๊ฒŒ nonce ๋ฐฉ์‹์„ ์‚ฌ์šฉ:

Content-Security-Policy: script-src 'self' 'nonce-abc123'
 

๊ทธ๋ฆฌ๊ณ  <script nonce="abc123">...</script> ๊ฐ™์ด ์ ์šฉ.

 

 




โœ… 1. CSP ์ •์ฑ…์ด๋ž€?

**CSP(Content Security Policy)**๋Š” ์›น์‚ฌ์ดํŠธ์˜ ์Šคํฌ๋ฆฝํŠธ, ์ด๋ฏธ์ง€, ์Šคํƒ€์ผ ๋“ฑ์˜ ์ถœ์ฒ˜๋ฅผ ์ œ์–ดํ•˜๋Š” ๋ณด์•ˆ ์ •์ฑ…์ž…๋‹ˆ๋‹ค.
XSS ๊ณต๊ฒฉ(์Šคํฌ๋ฆฝํŠธ ์‚ฝ์ž… ๊ณต๊ฒฉ) ๋“ฑ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ CSP:

Content-Security-Policy: script-src 'self'

์ด ๋ง์€:

  • ์˜ค์ง **๊ฐ™์€ ์ถœ์ฒ˜(origin)**์˜ JS ํŒŒ์ผ๋งŒ ์‹คํ–‰ ๊ฐ€๋Šฅ
  • onclick="..." ๊ฐ™์€ inline JS ์ฝ”๋“œ๋Š” ์‹คํ–‰ ๋ถˆ๊ฐ€
  • <script>alert('hi')</script> ๋„ ์‹คํ–‰ ๋ถˆ๊ฐ€

๋‚˜๊ฐ™์€ ๊ฒฝ์šฐ  onclick ์†์„ฑ์„ ๋งŽ์ด ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— filter ์ž์ฒด๋ฅผ ๋นผ๋ฒ„๋ฆผ ~!

 

 

728x90
๋ฐ˜์‘ํ˜•
LIST