[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)
- ํด๋ผ์ด์ธํธ์์ showUser ์์ฒญ
<script src="https://api.example.com/user?id=123&callback=showUser"></script>- ์๋ฒ์์ ์๋ต
showUser({ "name": "Alice", "age": 25 });showUser()ํจ์๊ฐ ํด๋ผ์ด์ธํธ์ ์ ์๋ผ ์๋ค๋ฉด ์๋ฒ์์ ๋๊ธด ๋ฐ์ดํฐ ์คํ
- EX)
-
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 ๊ฐ๋ฅ
- ๋์ ํ๋ฆ
index.php๋ ๋์ ์ผ๋ก ํ์ด์ง๋ฅผ ์์ฑํ๋ ์๋ฒ์ PHP ์ฝ๋. ์๋ต์ ๋งค๋ฒ ๋ค๋ฅธ CSPnonce๊ฐ์ ๋ฃ์ด์ค- /index.php/style.css ๋ก URL ๋ณ์กฐ : ์ ์ ํ์ผ .css ์ฒ๋ผ ๋ณด์ด๊ฒ ์กฐ์.
- ๋ค์ ์๋ URL์์
/index.php๋ง ๋ณด๊ณindex.php๋ฅผ ์คํ./style.css๋ PHP ์ฝ๋ ๋ด๋ถ์์ ๋ฌด์๋๊ฑฐ๋ ์ถ๊ฐ ์ ๋ณด๋ก ์ ๋ฌ
- ๋ค์ ์๋ URL์์
- ์์ฒญ์
.cssํ์ฅ์๋ฅผ ๋ณธ ๋ธ๋ผ์ฐ์ ๋ ์๋ต ์บ์ฑ - ์บ์ฑ ๋ง๋ฃ ์ ๊น์ง๋ ๊ฐ์
nonce๊ฐ ๊ณ์ ์ฌ์ฉ- ํด๋น CSS URL์ ์์ฒญํ๋ฉด ๊ฐ์
nonce๊ฐ์ ๋ฐ์. ์ด ๊ฐ์ script์ ๋ฃ์ผ๋ฉด CSP ์ฐํ ๊ฐ๋ฅ
- ํด๋น CSS URL์ ์์ฒญํ๋ฉด ๊ฐ์
-
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ํ์ฌ ์ฌ์ฉ
- ๋ ๋ถ๋ถ์ด
- PHP, CGI ๊ณ์ด ์คํฌ๋ฆฝํ
์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
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'
Leave a comment