본문 바로가기

# Tech/ChromeExtension

크롬 익스텐션의 각종 개념들


개념

구글 크롬 익스텐션이란 크롬 브라우저를 조작할 수 있는 권한을 가진 막강한 프로그램을 의미합니다. HTML, JavaScript, CSS와 같은 웹 기술을 기반으로 두고있기 때문에, 프론트엔드를 다뤘던 경험이 있다면 쉽게 익힐 수 있습니다.


핵심 파일

익스텐션을 만드는데 필요한 핵심 파일들은 다음과 같습니다.
각각의 파일에 대해 짤막하게 설명하겠습니다.

📦 chrome-extension
 ┣ 📜 manifest.json
 ┣ 📜 icon.png
 ┣ 📜 popup.html
 ┗ 📜 background.js

manifest.json

안드로이드AndroidManifest.xml와 매우 비슷합니다.
익스텐션의 각종 메타정보와 필요한 권한목록을 명시적으로 적어야 합니다.


만약, 권한목록에 없는 기능을 사용한다면 익스텐션은 에러를 뿜으면서 죽어버립니다.

  • 기본정보 (제목, 설명, 버전...)
  • 권한목록 (스토리지 접근, 페이지 접근 허용, ...)
  • 파일경로 (아이콘 경로, 팝업 파일 경로, ...)

popup.html

크롬 익스텐션을 클릭하면 보여줄 html 파일입니다. 필요하다면 추가적인 .js파일과 .css파일도 사용할 수 있습니다.


단, 팝업에서 실행중인 자바스크립트는 팝업이 닫힐 때 함께 종료된다는 것을 반드시 염두해야 합니다.

background.js

팝업에 관계없이 익스텐션의 뒷부분에서 항상 동작중인 파일입니다. 여러개의 .js파일을 백그라운드로 등록할 수 있습니다.


익스텐션에서 바라본 영역들

여기서 말하는 영역이란 자바 스크립트가 실행될 수 있는 공간이란 의미로 쓰였으며, Javascript Context와 같은 말입니다. 익스텐션을 기준으로 얼마나 많은 영역들이 있고, 그 영역들을 부르는 명칭에 대해 알아보겠습니다. 먼저 크게 구분하면 둘 중 하나입니다.

  • 외부 영역 : 익스텐션에 포함되지 않는 영역
  • 내부 영역 : 익스텐션에 포함되는 영역

외부 영역

모든 컨텐트 영역

브라우저는 여러개의 탭으로 구성되어 있습니다. 여기서 하나하나의 탭을 컨텐트content라고 부르는데, 익스텐션의 입장에서는 모든 컨텐트가 외부의 존재입니다.

타 익스텐션 영역

익스텐션은 자기 하나만 있는 것이 아닙니다. 다른 익스텐션의 내부 영역은 자기 입장에서 외부의 존재입니다.


내부 영역

팝업 영역

팝업은 결국 HTML를 통해 만들어지니까, 팝업 그 자체가 하나의 컨텐트라는 것을 알 수 있습니다. 즉, 익스텐션이 가지는 컨텐트 영역팝업 영역이라고 부릅니다. 단, 팝업이 열리면 생성되고, 닫히면 소멸됩니다.


백그라운드 영역

백그라운드 로직이 실행되는 영역입니다. 팝업이 닫히더라도 소멸되지 않으며, 사용자가 익스텐션을 삭제하거나 차단하지 않는한 소멸되지 않습니다.


영역간 메세지 전달

각 영역들은 자신만의 문맥을 가지고 있기 때문에 서로 다른 영역간의 데이터 공유는 차단되어 있습니다. 같은 내부 영역이라 할지라도 팝업 영역백그라운드 영역도 근본적으로는 다른 영역이므로 같은 문맥을 공유할 수 없습니다.


하지만 같은 문맥을 공유할 수 없다는 것이지, 데이터를 주고받는 것까지 불가능한 것은 아닙니다. 크롬 브라우저의 대부분의 영역은 chrome이라는 글로벌 객체를 제공하는데, 이 객체에 존재하는 메소드를 사용하면 타 영역으로 메세지를 전달할 수 있습니다.


chrome 객체를 통해 메세지를 전달하는 방식에 대해 알아보자면, 크게 3가지로 나눌 수 있습니다.

  • 일회성 연결을 사용하여 메세지를 전달하는 방식. (Simple One-Time Requests)
  • 커넥션 연결을 사용하여 메세지를 전달하는 방식. (Long Lived Connections)
  • 네이티브 연결을 사용하여 메세지를 전달하는 방식. (Native Messaging)

간단하게 특징만 짚고 넘어가겠습니다.


일회성 연결

일회성 연결방식은 단 한번만 사용할 수 있는 연결을 생성한 뒤, 메세지를 한 번만 주고받고 연결을 끊습니다. 주고받다란 말에서 눈치챌 수 있듯이 메세지를 전달받은 수신측은 응답 데이터를 반환할 수 있습니다. 단, 송신측이 언제까지나 응답 데이터를 기다릴 수는 없기 때문에, 굉장히 짧은 시간동안만 응답 데이터를 기다립니다.


다회성 연결

다회성 연결방식양방향 전달이 가능한 포트를 생성하여 메세지를 지속적으로 주고받습니다. 포트가 너무 오래되면 크롬이 강제로 해당 포트를 종료시키는 경우가 있습니다. 포트가 죽으면 더 이상 메세지를 주고받을 수 없지만, 포트 종료감지 콜백을 정의하면 이를 감지하고, 다시 새로운 포트가 생성되도록 구현할 수 있습니다.


네이티브 연결방식

네이티브 연결방식크롬 브라우저의 외부, 즉 운영체제에서 메세지를 전달받으며, 각 운영체제별로 구현하는 방식이 다릅니다.


알아두면 좋은 것

CORS 제약이 없음

백그라운드 영역교차 출처 리소스 제약CORS이 적용되지 않는다는 것을 이용하면 타 서버의 API를 호출하거나, 클라이언트 측에서 타 사이트의 HTML코드를 얻어오도록 할 수 있습니다.


해당 익스텐션이 있는지 검사하기

익스텐션이 존재하는지 검사하는 방법에는 여러가지 방법이 있습니다만, 아래 2가지를 사용합니다.

요소를 감지하고 버전 주입

익스텐션이 컨텐트 영역에서 특정 id를 갖는 요소를 발견하면 그 요소에 데이터를 주입합니다.
컨텐트 영역은 그 요소에 데이터가 주입되었는지를 검사합니다.


직접 메세지 날려보기

컨텐트 영역이 직접 chrome객체를 통해 메세지를 전송해보고, 응답이 돌아오는지 검사합니다.


보안

교차 스크립트 공격 취약점

컨텐트 접근 권한이 부여된다면 익스텐션에서 컨텐트 영역을 문맥으로하는 스크립트를 실행시킬 수 있습니다. 이것으로 해당 컨텐트 영역의 DOM의 내부요소를 조회하고 뜯어고칠 수 있습니다. 이것은 생각보다 엄청난 권한인데, 올바르게 사용하지 않는다면 교차 스크립트 공격 취약점을 발생시킬 수 있기 때문에 주의해야 합니다.


교차 스크립트 공격 취약점을 발생시킬 수 있는 행동들은 다음과 같으며,

  • innerHTML 또는 outerHTML을 사용하여 DOM을 수정.
  • 문자열로 된 JSON을 파싱하기 위해 eval함수 사용.

아래처럼 문제를 해결할 수 있는 다른 방법을 사용해야 합니다.

  • 적어도 이스케이프한 뒤에 DOM을 수정
  • 문자열로 된 JSON을 파싱하기 위해 JSON.parse함수 사용.

지정된 출처에서만 동작하도록 하기

위의 내용들을 살펴보면 익스텐션이 가지는 권한은 상당히 강력하기 때문에, manifest 수준에서 지정된 도메인에서만 익스텐션이 동작하도록 강제할 수 있습니다. 예를 들면, 출처를 naver.com/*로 정해놨다면 네이버 사이트를 보고있는 컨텐트 영역만 익스텐션에 메세지를 날릴 수 있습니다.