사이트 격리
고친 사람 github-actions[bot]
사이트 격리는 브라우저가 사이트마다 페이지를 처리하는 프로세스를 따로 떼어 놓습니다. 한 사이트의 코드가 프로세스를 통째로 손에 넣어도 다른 사이트의 내용은 그 안에 없어서 가져갈 것이 없습니다. 같은 창에 열어 둔 메일함과 광고 페이지가 서로 다른 프로세스에서 돌아갑니다.
쉽고 빠른 이해
브라우저는 사이트마다 페이지를 그리고 스크립트를 돌리는 프로세스를 따로 씁니다. 메일함 탭과 광고 페이지는 한 창에 있어도 서로 다른 프로세스에 들어갑니다.
한 프로세스에 여러 사이트를 같이 담으면, 그 프로세스가 공격자 손에 넘어갈 때 안에 있던 모든 사이트의 내용이 함께 새어 나갑니다.
어떻게 도나:
- 주소에서 통신 방식과 등록된 도메인만 뽑아 「사이트」 이름을 만듭니다
- 사이트가 다른 문서는 다른 프로세스에 넣습니다. 한 탭 안에 낀 광고 틀도 마찬가지입니다
- 서버가 보낸 응답은 그 프로세스가 가져도 되는 것인지 확인한 뒤에 넘깁니다
대가는 프로세스 수입니다. 프로세스마다 자기 메모리를 씁니다. 갈라진 문서끼리 값을 주고받을 때는 운영체제를 거칩니다. 그래서 메모리가 빠듯한 기기에서는 여러 사이트를 한 프로세스에 묶어 경계를 성기게 쓰기도 합니다.
상세
한 사무실을 여러 회사가 칸막이 없이 나눠 쓴다고 해 봅니다. 옆 책상 서류를 보지 말라는 규칙이 있어도, 어길 마음이 있는 사람 하나면 서류는 새어 나갑니다. 회사마다 방을 따로 주고 문을 잠그면 규칙을 어기려 해도 옆 서류가 그 방에 없습니다.
사이트 격리는 브라우저가 페이지를 처리하는 프로세스를 사이트 단위로 가르는 방식입니다. 한 사이트의 문서와 스크립트는 그 사이트만을 위한 프로세스 안에서 돕니다. 다른 사이트의 문서는 다른 프로세스로 갑니다.
브라우저는 감독하는 프로세스 하나와 화면을 그리는 프로세스 여럿으로 갈라 돕니다. 감독하는 것을 브라우저 본체, 화면을 그리고 스크립트를 돌리는 것을 렌더러 프로세스라고 부릅니다. 브라우저 본체는 렌더러 프로세스를 띄워 감독합니다.
렌더러 프로세스는 파일과 장치에 손댈 권한을 크게 깎은 샌드박스 안에서 돕니다. 남이 보낸 코드를 직접 다뤄서 가장 먼저 뚫리기 때문입니다.
동일 출처 정책과 가르는 점은 칸막이를 누가 지키느냐입니다. 동일 출처 정책은 브라우저가 코드로 검사해서 지킵니다. 사이트 격리는 운영체제가 프로세스 경계로 지킵니다. 검사는 버그 하나로 지나칠 수 있지만 프로세스 경계는 그렇지 않습니다.
출처보다 굵게 잡는 사이트 경계
브라우저 보안에서 출처는 주소의 통신 방식·호스트 이름·포트 번호를 묶은 이름표입니다. 하나라도 다르면 다른 출처입니다.
사이트는 그보다 굵습니다. 통신 방식과 등록된 도메인 이름만 봅니다. 앞에 붙은 하위 도메인과 포트 번호는 무시합니다.
등록된 도메인이란 한 사람이 값을 치르고 빌리는 이름을 말합니다. 주소를 점으로 끊은 칸을 뒤에서부터 세어 봅니다. example.com 에서는 com 을 누구나 빌려 갑니다. 그 앞 example 부터가 한 사람의 몫입니다.
example.co.kr 은 co.kr 까지가 남에게 빌려주는 구간이라 example.co.kr 전체가 한 사람의 몫입니다. 어디까지가 빌려주는 구간인지는 주소 모양만 봐서는 알 수 없습니다. 그 구간을 모아 적어 둔 목록을 공개 접미사 목록이라고 부릅니다.
| 주소 | 출처 | 사이트 |
|---|---|---|
https://mail.example.com |
https://mail.example.com |
https://example.com |
https://chat.example.com:8443 |
https://chat.example.com:8443 |
https://example.com |
https://example.co.kr |
https://example.co.kr |
https://example.co.kr |
표의 위 두 줄은 출처가 다른데 사이트는 같습니다. 그래서 이 둘은 같은 프로세스에 들어갑니다.
굵게 잡는 까닭이 있습니다. 같은 사이트 안의 문서끼리는 쿠키를 나눠 갖습니다. 서로의 화면을 스크립트로 들여다볼 길도 열려 있습니다. 프로세스만 떼어 놓아도 그 길이 살아 있으면 떼어 놓은 척에 그칩니다.
탭 하나 안에서 갈리는 여러 프로세스
페이지 안에 다른 페이지를 끼워 넣는 틀을 iframe이라고 합니다. 광고와 결제 화면이 흔히 이 틀로 들어옵니다.
틀 안이 다른 사이트면 그 틀만 따로 프로세스를 받습니다. 쇼핑몰 장바구니 페이지가 광고 회사의 틀을 하나 물고 있으면, 장바구니를 그리는 프로세스와 광고를 그리는 프로세스가 갈립니다.
화면에는 한 장으로 보이지만 그리는 프로세스는 둘입니다. 각자 그린 조각을 한 장으로 합치는 일은 브라우저 본체가 맡습니다.
flowchart TD
B["브라우저 본체 · 조각을 합친다"]
subgraph P1["렌더러 프로세스 1"]
D1["shop.example 문서"]
end
subgraph P2["렌더러 프로세스 2"]
D2["ads.example 광고 틀"]
end
B -- 띄운다 --> P1
B -- 띄운다 --> P2
P1 -- 그린 조각 --> B
P2 -- 그린 조각 --> B
그림의 두 프로세스는 서로의 메모리를 볼 수 없습니다. 광고 틀이 공격자 손에 넘어가도 바깥 페이지의 장바구니 내용은 다른 프로세스에 있습니다.
프로세스에 들어오기 전에 남의 자료를 거르는 검사
프로세스를 떼어 놓아도 그 프로세스가 남의 사이트 자료를 네트워크로 받아다 자기 메모리에 쌓으면 떼어 놓은 뜻이 없습니다. 그래서 응답을 렌더러 프로세스에 넘기기 전에 브라우저 본체가 한 번 봅니다.
기준은 그 자료가 읽히면 내용이 새는 종류인가입니다. 그림과 스크립트 파일처럼 원래 남의 사이트에서 불러다 쓰는 것은 그대로 넘깁니다.
내용 자체가 값인 것은 사이트가 다르면 넘기지 않습니다. 페이지를 이루는 HTML(HyperText Markup Language, 하이퍼텍스트 마크업 언어) 문서가 그렇습니다. 서버가 응답으로 돌려주는 JSON(JavaScript Object Notation, 자바스크립트 객체 표기법)·XML(eXtensible Markup Language, 확장 가능 마크업 언어) 자료도 그렇습니다. 이 검사를 교차 출처 읽기 차단이라고 부릅니다.
sequenceDiagram
participant R as 렌더러 프로세스
participant B as 브라우저 본체
participant S as 남의 사이트 서버
R->>B: 이 주소의 자료를 받아 달라
B->>S: 요청을 보낸다
S-->>B: 응답을 돌려준다
Note over B: 이 프로세스가 가져도 되는 자료인가
B-->>R: 걸러진 응답만 넘긴다
렌더러 프로세스가 직접 서버에 붙지 않는다는 것이 이 그림의 뜻입니다. 남의 자료를 달라고 우겨도 넘겨줄지는 브라우저 본체가 정합니다.
막는 공격과 그대로 남는 공격
먼저 막는 공격을 봅니다. 사이트 격리는 렌더러 프로세스가 공격자에게 통째로 넘어간 상태를 전제로 깔고 짭니다. 그렇게 되어도 그 프로세스 안에 다른 사이트의 로그인 정보와 문서가 없어서 한 사이트의 피해로 끝납니다.
부채널 공격은 같은 프로세스 안의 메모리를 몰래 읽어 내는 공격입니다. 이 공격도 프로세스 경계에 걸립니다.
Spectre는 프로세서가 앞질러 실행해 보는 버릇(투기 실행)을 이용해 남의 메모리 내용을 짐작합니다. 애초에 그 메모리에 남의 사이트 자료가 없으면 알아낼 것이 없습니다.
못 막는 공격도 또렷합니다. 교차 사이트 스크립팅은 남이 심은 스크립트가 그 사이트의 페이지 안에서 그 사이트 코드인 척 도는 공격입니다. 공격이 피해자 사이트 자신의 프로세스 안에서 일어나서, 경계 안쪽의 일이라 프로세스를 갈라도 소용이 없습니다.
사용자가 스스로 가짜 화면에 정보를 넣는 일도 그대로 남습니다. 브라우저 본체나 운영체제 자체가 뚫리는 경우도 마찬가지입니다. 모든 프로세스를 감독하는 브라우저 본체가 무너지면 갈라 놓은 경계도 함께 무너집니다.
프로세스 수로 치르는 대가
프로세스는 공짜가 아닙니다. 프로세스마다 자기 메모리를 들고 있어야 합니다. 한 창 안의 문서끼리도 프로세스가 다르면 값을 주고받을 때 운영체제를 거칩니다.
그래서 메모리가 빠듯한 기기에서는 브라우저가 프로세스 수를 줄여 여러 사이트를 한 프로세스에 묶기도 합니다. 경계가 성긴 대신 기기가 감당할 수 있는 만큼만 씁니다.
웹을 만드는 쪽에도 영향이 있습니다. 한 창이 다른 창의 내용을 바로 들여다보던 방식은 프로세스 경계를 넘게 되어, postMessage처럼 메시지를 보내고 답을 기다리는 방식으로 옮겨 갑니다.
관련 항목
사이트를 가르는 기준이 되는 주소 조각
URL · 스킴 · 도메인 · 서브도메인 · 포트 · 공개 접미사 · 출처
이 격리를 떠받치는 운영체제 수단
프로세스 · 샌드박스 · 프로세스 간 통신 · 가상 메모리 · 최소 권한 · 권한 분리
격리를 나눠 맡는 브라우저 구성 요소
브라우저 · 렌더러 프로세스 · 렌더링 엔진 · 자바스크립트 엔진 · iframe · 교차 출처 읽기 차단
브라우저를 함께 지키는 다른 보안 장치
동일 출처 정책 · CORS · 콘텐츠 보안 정책 · SameSite 쿠키 · HttpOnly · HTTPS
이 격리가 겨냥하는 공격
Spectre · 부채널 공격 · 투기 실행 · 메모리 안전 취약점 · 임의 코드 실행 · 샌드박스 탈출
이 격리 바깥에 그대로 남는 공격
교차 사이트 스크립팅 · 크로스 사이트 요청 위조 · 클릭재킹 · 피싱
사이트 단위로 칸이 갈리는 브라우저 저장소
쿠키 · 웹 스토리지 · IndexedDB · 캐시 스토리지 · 서비스 워커
같은 뿌리에서 갈라져 나온 격리 방식
다른 이름: site isolation · Site Isolation · 사이트 단위 격리