How to Hack Browser Extension

Introduction

Browser Extension은 웹 브라우저를 커스터마이징하고 더 확장하여 사용할 수 있도록 제공되는 기능입니다. Chrome, Safari, Firefox, Edge 등 메이저 브라우저에선 모두 지원하고 있으며 Chrome을 기반으로한 브라우저(Brave, Whale 등) 또한 동일하게 Extension을 지원합니다.

이 문서는 이러한 Browser Extension에 대해 테스팅하고 보안적인 문제를 찾는 방법에 대해 정리합니다.

Structure

Chrome/Firefox Extension

Chrome과 Firefox는 기본적으로 동일한 Extension 구조를 가집니다. 그래서 상호 호환 가능한 Extension들이 존재합니다. 다만 점점 버전이 올라감에 따라 현재는 약간 상이한 처리 구조를 가져서 호환되지 않는 경우가 많습니다.

Safari App Extension

Safari app extension은 Chrome, Firefox에서 사용하는 Web Extension과 다르게 Swift 코드로 빌드되는 어플리케이션입니다. 실제 내부 구성은 많이 다르지만 결과적으로 동일하게 DOM 내부에서 일부 Javascript와 HTML로 컨트롤하기 때문에 아래 테스팅 방법쪽에선 동일하게 확인해보실 수 있습니다.

Safari Web Extension

Safari Web Extension은 Chrome/Firefox에서 사용하는 Web Extension 과 동일한 형태의 Extension입니다. App Extension과 Web Extension을 구별하는 방법은 설치 방법에 있습니다.

  • App Extension: AppStore를 통해서만 설치
  • Web Extension: Chrome과 동일하게 파일 기반 설치

API Documents

Hack Mechanism

각 브라우저마다 내부적인 동작 방식은 다르지만, 결과적으로 수행하는 범위는 비슷하기 때문에 유사한 형태로 모든 브라우저 익스텐션을 테스트하고 보안적인 문제를 찾을 수 있습니다.

Code audit

브라우저 익스텐션은 ZIP 파일이 때문에 다운로드 후 압축을 풀어 소스코드와 리소스 등을 확인할 수 있습니다. 다만 각 Store에서는 직접 파일을 제공해주지 않기 때문에 약간의 트릭으로 파일을 찾아야합니다.

Find source code

크롬 익스텐션은 설치 시 아래 경로에 저장됩니다.

  • MacOS: ~/Library/Application\ Support/Google/Chrome/Default/Extensions
  • Linux: ~/.config/google-chrome/Default/Extensions/
  • Windows: C:\Users\<Your_User_Name>\AppData\Local\Google\Chrome\User Data\Default\Extensions

해당 디렉토리에서 확인해보면 extension의 키 값으로 폴더가 존재합니다.

ll ~/Library/Application\ Support/Google/Chrome/Default/Extensions

# drwx------@ 2 hahwul  staff    64B 12 24 00:37 Temp
# drwx------@ 3 hahwul  staff    96B  9 29  2019 aapocclcgogkmnckokdopfmhonfmgoek
# drwx------@ 3 hahwul  staff    96B  9 29  2019 aohghmighlieiainnegkcijnfilokake
# drwx------@ 3 hahwul  staff    96B 11 14 18:39 apdfllckaahabafndbhieahigkjlhalf
# drwx------@ 3 hahwul  staff    96B  7 12 00:48 baacjfeencnlcclennchejfnbcplfmbb
# drwx------@ 3 hahwul  staff    96B  7  9 00:53 phbjaiacjbplfmapmlljdoacomhbpfoe

extension의 키 값은 크롬의 확장 프로그램 페이지에서 확인하실 수 있습니다.

https://user-images.githubusercontent.com/13212227/103444356-fd22ce00-4caa-11eb-8a0c-a2d4df5dd9ba.png

파일을 찾았다면 분석할 디렉토리로 복사해와서 작업을 진행하면 됩니다.

cp -r ~/Library/Application\ Support/Google/Chrome/Default/Extensions/phbjaiacjbplfmapmlljdoacomhbpfoe .

Manifest

Browser extension은 대부분의 policy와 permission을 manifest.json 파일에 명시합니다. 해당 파일을 체크하여 허용하고 있는 정책을 파악하고, 잘못 사용하는 설정들이 있는지 체크합니다.

{
   "author": "MM3Tools",
   "background": {
      "scripts": [ "util.js", "ProxySwitch.js" ]
   },
   "browser_action": {
      "browser_style": true,
      "default_icon": {
         "16": "img/MM3_16off.png",
         "32": "img/MM3_32off.png"
      },
      "default_popup": "popup.html"
   },
   "commands": {
      "ProxySwitch-1": {
         "description": "1",
         "suggested_key": {
            "default": "Ctrl+Shift+1"
         }
      },
      "ProxySwitch-2": {
         "description": "2",
         "suggested_key": {
            "default": "Ctrl+Shift+2"
         }
      },
      "ProxySwitch-3": {
         "description": "3",
         "suggested_key": {
            "default": "Ctrl+Shift+3"
         }
      },
      "ProxySwitch-4": {
         "description": "4",
         "suggested_key": {
            "default": "Ctrl+Shift+4"
         }
      }
   },
   "default_locale": "en",
   "description": "__MSG_appDescription__",
   "icons": {
      "48": "img/MM3_48.png",
      "96": "img/MM3_96.png"
   },
   "key": "...snip...",
   "manifest_version": 2,
   "name": "MM3-ProxySwitch",
   "options_ui": {
      "open_in_tab": true,
      "page": "setting.html"
   },
   "permissions": [ "storage", "proxy", "browsingData", "http://*/*", "https://*/*" ],
   "short_name": "ProxySwitch",
   "update_url": "https://clients2.google.com/service/update2/crx",
   "version": "2018.332"
}

*각 퍼미션은 https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions 를 참고해주세요!

Source code

익스텐션 디렉토리 내부에 있는 소스코드는 실제 구동에 사용되는 코드들입니다. popup.html 같이 페이지를 표현하기 위한 markup 부터 실제 동작을 담은 js 파일들이 존재합니다. 해당 코드들을 살피면서 중요한 값(secret, key 등)이 노출되었는지, 외부로 부터 받을 수 있는 Input 들이 있는지 체크합니다.

주로 봐야할 부분은 아래와 같습니다.

  • postMessage
  • SSE
  • webSocket
  • wasm
  • API Call (ajax, xmlhttprequest, etc..)
  • localStorage / sessionStorage

Live audit

Test with devtools

익스텐션은 웹 페이지와 다른 별도의 DOM에서 동작합니다. 일반 웹 페이지라면 DevTools를 열어 체크할 수 있지만 익스텐션은 코드에 따라 뷰를 제공해주지 않거나 뷰를 트리거하기 어려울 수도 있습니다. 이럴 때 아래와 같은 방법으로 DOM 영역을 열 수 있습니다.

옵션 > 확장 기능 > 대상 확장 기능 > 뷰 검사

https://user-images.githubusercontent.com/13212227/103444418-5c80de00-4cab-11eb-9042-2e85db32c21b.png

뷰 검사를 통해 페이지를 로드했다면 background 에 각 js 등이 이미 올라온 상태이기 때문에 devtools의 console 이나 debugger를 통해서 테스트해볼 수 있습니다. 함수 정보는 위 분석중인 소스코드에서 cat과 grep 등으로 걸러내면 찾아낼 수 있습니다.

cat util.js
"use strict";function err(ex){if(ex!=null)console.error(ex,ex.message,chrome.runtime.lastError);else console.error(chrome.runtime.lastError);}function myParseInt(value){try{value=value.trim();if(/^(\-|\+)?([0-9]+|Infinity)$/.test(value))return Number(value);}catch(ex){err(ex);}return NaN;}function hostM(host,isProxy){try{let hp={};let i=host.lastIndexOf(':');if(i!=-1){hp.port=host.substring(i+1);let em=null;if(hp.port.length==0)em=chrome.i18n.getMessage('notSpecified');else{let n=myParseInt(hp.port);if(isNaN(n))

https://user-images.githubusercontent.com/13212227/103444494-0eb8a580-4cac-11eb-89b9-226f8598260e.png

chrome-extension

만약 익스텐션이 popup.html 등 view를 제공한다면 아래 이미지와 같이 chrome-extension:// 를 통해서 직접 접근하여 테스트할 수도 있습니다.

https://user-images.githubusercontent.com/13212227/103444589-db2a4b00-4cac-11eb-9d82-0c219378b175.png

이러한 경우 실제 동작을 눈으로 보면서 테스트할 수 있기 때문에 훨씬 편리합니다. 참고로 chrome-extension:// 프로토콜 또한 popup 등 페이지에서 query parse를 통해 값을 처리하는 경우 테스팅 포인트가 되기도 합니다.

chrome-extension://vulnapp/landing?c=};alert(45);function a(){//

User input

브라우저 익스텐션은 구동 시 DOM을 가지는 웹 페이지로써 일반 브라우징 영역과 격리되어 있긴 하지만, postMessage, SSE 등 여러가지 기능들을 통해 웹 페이지, API 등과 통신하고 DOM 내부에서 처리할 수 있습니다. 이는 브라우저 익스텐션 또한 일반 웹 페이지와 동일하게 웹 취약점의 영향을 받는다는 이야기입니다.

소스코드 분석으로 찾아낸 Endpoint 들에 대해서 테스트를 진행해야합니다.

A major weakness

Sensitive Data Leak

익스텐션의 기능에 따라서 내부에 중요한 정보를 포함하고 있을 가능성이 있습니다. 이러한 정보가 postMessage 등을 통해 외부에서 탈취할 수 있다면 사용자의 중요정보가 탈취될 수 있는 이슈가 됩니다.

일반적으로 저장 위치에 대한 토론이 많은데, manifest v3 기준으로 중요정보는 session storage 저장하는 것을 권고하고 있습니다.

XSS

대다수 웹 취약점이 포인트가 되겠지만, 그중에서도 XSS는 가장 중점적으로 봐야할 부분일 것 같습니다. 아무래도 클라이언드 단에서 도메인 기반의 리스크가 아닌, 광범위한 UXSS나 Browser API를 통한 추가적인 공격까지 이어질 수 있어서 확장 기능에선 조금 더 중요한 부분으로 보입니다.

Bypass CSP

브라우저 확장 기능에서 CSP는 Manifest에 명시합니다. 일반적으로 알려진 CSP 우회 방법을 통해서 CSP 정책을 우회할 수 있고, XSS 취약점이 조금 더 리스크를 가지는데 있어서 큰 도움을 줄 수 있습니다.

Javascript CVE

당연히 웹 기반의 페이지라서 Javascript 라이브러리 공개 취약점에 영향을 받습니다. 업데이트를 위해선 확장 기능의 패키지 업데이트가 필요하기 때문에 일반적으로 웹 페이지보단 업데이트가 느린편입니다. retire.js 등으로 쉽게 확인할 수 있습니다.

API Security

확장 기능에 연동되는 API 서버는 주요 분석 대상이 됩니다. 당연히 여기서 보편적인 취약점을 찾을 수 있고, 이어서 확장 기능과의 연동성도 있기 때문에 이를 활용하면 확장 기능 자체에도 영향을 줄 수 있는 취약점을 만들어낼 수 있습니다.

API Server 내 임의의 데이터를 저장시키는 취약점이 있고, 이 데이터가 확장 기능에서 XSS로 동작한다면, UXSS 또는 Browser Extension API를 사용할 수 있는 공격까지 이어질 수 있어 리스크를 높일 수 있습니다.

🛠 Environment

Include WASM

만약 WASM(Web Assembly)가 적용된 Extension이라면 wasm에 대한 분석이 추가로 필요하게 됩니다. wasm 분석에 대한 자세한 내용은 아래 링크를 참고해주세요.

웹 어셈블리(Web Assembly)는 어떻게 보안 취약점 분석을 할까요?

Inclulde SSE

SSE가 적용된 익스텐션이라면 SSE를 처리할 수 있는 도구가 필요합니다. ZAP, Burpsuite에서 모두 가능하며 자세한 내용은 아래 링크를 참고해주세요.

Cullinan > SSE

Include WebSocket

WebSocket이 적용된 익스텐션이라면 WebSocket를 처리할 수 있는 도구가 필요합니다. SSE와 동일하게 ZAP, Burpsuite에서 모두 가능하며 자세한 내용은 아래 링크를 참고해주세요.

Cullinan > WebSocket

Articles

References