Browser Extension Pentesting Methodology
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
브라우저 확장 프로그램은 JavaScript로 작성되며 브라우저에 의해 백그라운드에서 로드됩니다. 각 확장 프로그램은 DOM을 가지고 있지만 다른 사이트의 DOM과 상호작용할 수 있습니다. 이는 다른 사이트의 기밀성, 무결성 및 가용성(CIA)을 위협할 수 있음을 의미합니다.
확장 프로그램 레이아웃은 시각화할 때 가장 잘 보이며 세 가지 구성 요소로 구성됩니다. 각 구성 요소를 자세히 살펴보겠습니다.
각 콘텐츠 스크립트는 단일 웹 페이지의 DOM에 직접 접근할 수 있으며, 따라서 잠재적으로 악의적인 입력에 노출됩니다. 그러나 콘텐츠 스크립트는 확장 프로그램 코어에 메시지를 전송할 수 있는 능력 외에는 권한이 없습니다.
확장 프로그램 코어는 대부분의 확장 프로그램 권한/접근을 포함하지만, 확장 프로그램 코어는 XMLHttpRequest 및 콘텐츠 스크립트를 통해서만 웹 콘텐츠와 상호작용할 수 있습니다. 또한, 확장 프로그램 코어는 호스트 머신에 직접 접근할 수 없습니다.
확장 프로그램은 사용자의 전체 권한으로 호스트 머신에 접근할 수 있는 네이티브 바이너리를 허용합니다. 네이티브 바이너리는 Flash 및 기타 브라우저 플러그인에서 사용되는 표준 Netscape Plugin Application Programming Interface (NPAPI)를 통해 확장 프로그램 코어와 상호작용합니다.
사용자의 전체 권한을 얻으려면 공격자는 확장 프로그램이 콘텐츠 스크립트에서 확장 프로그램의 코어로, 그리고 확장 프로그램의 코어에서 네이티브 바이너리로 악의적인 입력을 전달하도록 설득해야 합니다.
확장 프로그램의 각 구성 요소는 강력한 보호 경계로 서로 분리되어 있습니다. 각 구성 요소는 별도의 운영 체제 프로세스에서 실행됩니다. 콘텐츠 스크립트와 확장 프로그램 코어는 대부분의 운영 체제 서비스에서 사용할 수 없는 샌드박스 프로세스에서 실행됩니다.
또한, 콘텐츠 스크립트는 별도의 JavaScript 힙에서 실행되어 관련 웹 페이지와 분리됩니다. 콘텐츠 스크립트와 웹 페이지는 같은 기본 DOM에 접근할 수 있지만, 두 개는 JavaScript 포인터를 교환하지 않아 JavaScript 기능의 유출을 방지합니다.
manifest.json
Chrome 확장 프로그램은 단순히 .crx 파일 확장자를 가진 ZIP 폴더입니다. 확장 프로그램의 코어는 폴더의 루트에 있는 manifest.json
파일로, 레이아웃, 권한 및 기타 구성 옵션을 지정합니다.
Example:
content_scripts
Content scripts는 사용자가 일치하는 페이지로 이동할 때 로드됩니다. 이 경우 https://example.com/*
표현과 일치하는 모든 페이지이며 *://*/*/business*
정규 표현식과 일치하지 않습니다. 이들은 페이지의 자체 스크립트처럼 실행되며 페이지의 Document Object Model (DOM)에 임의로 접근할 수 있습니다.
더 많은 URL을 포함하거나 제외하기 위해 include_globs
및 **exclude_globs
**를 사용할 수도 있습니다.
다음은 저장소 API를 사용하여 확장 프로그램의 저장소에서 message
값을 검색할 때 페이지에 설명 버튼을 추가하는 예제 콘텐츠 스크립트입니다.
이 버튼이 클릭되면 콘텐츠 스크립트에 의해 확장 페이지로 메시지가 전송됩니다. 이는 runtime.sendMessage() API를 활용한 것입니다. 콘텐츠 스크립트는 API에 직접 접근하는 데 제한이 있으며, storage
가 몇 가지 예외 중 하나입니다. 이러한 예외를 넘어서는 기능을 위해서는 콘텐츠 스크립트가 통신할 수 있는 확장 페이지로 메시지가 전송됩니다.
브라우저에 따라 콘텐츠 스크립트의 기능이 약간 다를 수 있습니다. Chromium 기반 브라우저의 경우 기능 목록은 Chrome Developers documentation에서 확인할 수 있으며, Firefox의 경우 MDN이 주요 출처입니다. 또한 콘텐츠 스크립트는 백그라운드 스크립트와 통신할 수 있는 능력이 있어, 작업을 수행하고 응답을 전달할 수 있다는 점도 주목할 만합니다.
Chrome에서 콘텐츠 스크립트를 보기 및 디버깅하려면 Chrome 개발자 도구 메뉴에 접근할 수 있습니다: 옵션 > 추가 도구 > 개발자 도구 또는 Ctrl + Shift + I를 눌러서 접근할 수 있습니다.
개발자 도구가 표시되면 소스 탭을 클릭한 후 콘텐츠 스크립트 탭을 클릭합니다. 이를 통해 다양한 확장에서 실행 중인 콘텐츠 스크립트를 관찰하고 실행 흐름을 추적하기 위해 중단점을 설정할 수 있습니다.
콘텐츠 스크립트는 필수적이지 않습니다. 웹 페이지에 동적으로 주입하거나 프로그래밍 방식으로 주입할 수 있는 스크립트를 **tabs.executeScript
**를 통해 주입할 수 있습니다. 이는 실제로 더 세밀한 제어를 제공합니다.
콘텐츠 스크립트를 프로그래밍 방식으로 주입하려면 확장이 스크립트를 주입할 페이지에 대한 호스트 권한을 가져야 합니다. 이러한 권한은 확장의 매니페스트 내에서 요청하거나 activeTab을 통해 임시로 확보할 수 있습니다.
클릭 시 JS 파일 주입:
클릭 시 함수 주입:
더 많은 URL을 포함하거나 제외하려면 include_globs
및 **exclude_globs
**를 사용할 수 있습니다.
run_at
run_at
필드는 JavaScript 파일이 웹 페이지에 주입되는 시점을 제어합니다. 선호되는 기본 값은 "document_idle"
입니다.
가능한 값은 다음과 같습니다:
document_idle
: 가능한 경우 언제든지
document_start
: css
의 파일이 로드된 후, 그러나 다른 DOM이 구성되거나 다른 스크립트가 실행되기 전에.
document_end
: DOM이 완료된 직후, 그러나 이미지 및 프레임과 같은 하위 리소스가 로드되기 전에.
manifest.json
을 통해**service-worker.js
**를 통해
background
내용 스크립트가 전송한 메시지는 배경 페이지에서 수신되며, 이는 확장 구성 요소를 조정하는 중앙 역할을 합니다. 특히, 배경 페이지는 확장의 수명 동안 지속되며, 사용자와의 직접적인 상호작용 없이 조용히 작동합니다. 자체 문서 객체 모델(DOM)을 가지고 있어 복잡한 상호작용 및 상태 관리를 가능하게 합니다.
주요 사항:
배경 페이지 역할: 확장의 신경 센터 역할을 하여 다양한 부분 간의 통신 및 조정을 보장합니다.
지속성: 사용자에게는 보이지 않지만 확장의 기능에 필수적인 항상 존재하는 개체입니다.
자동 생성: 명시적으로 정의되지 않은 경우, 브라우저는 자동으로 배경 페이지를 생성합니다. 이 자동 생성된 페이지는 확장 매니페스트에 지정된 모든 배경 스크립트를 포함하여 확장의 배경 작업이 원활하게 작동하도록 보장합니다.
명시적으로 선언되지 않았을 때 브라우저가 배경 페이지를 자동으로 생성하는 편리함은 모든 필요한 배경 스크립트가 통합되고 작동하도록 보장하여 확장 설정 프로세스를 간소화합니다.
Example background script:
It uses runtime.onMessage API to listen to messages. When an "explain"
message is received, it uses tabs API to open a page in a new tab.
To debug the background script you could go to the extension details and inspect the service worker, this will open the developer tools with the background script:
브라우저 확장 프로그램은 다양한 종류의 페이지를 포함할 수 있습니다:
작업 페이지는 확장 아이콘을 클릭할 때 드롭다운에 표시됩니다.
확장 프로그램이 새 탭에서 로드할 페이지.
옵션 페이지: 이 페이지는 클릭 시 확장 프로그램 위에 표시됩니다. 이전 매니페스트에서는 chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca
에서 이 페이지에 접근할 수 있었거나 클릭하여 접근할 수 있었습니다:
이 페이지들은 필요에 따라 동적으로 콘텐츠를 로드하므로 백그라운드 페이지처럼 지속적이지 않다는 점에 유의하세요. 그럼에도 불구하고, 이들은 백그라운드 페이지와 특정 기능을 공유합니다:
콘텐츠 스크립트와의 통신: 백그라운드 페이지와 유사하게, 이 페이지들은 콘텐츠 스크립트로부터 메시지를 받을 수 있어 확장 프로그램 내에서의 상호작용을 촉진합니다.
확장 프로그램 전용 API 접근: 이 페이지들은 확장 프로그램에 대해 정의된 권한에 따라 확장 프로그램 전용 API에 대한 포괄적인 접근을 누립니다.
permissions
& host_permissions
**permissions
**와 **host_permissions
**는 manifest.json
의 항목으로, 브라우저 확장 프로그램이 어떤 권한(저장소, 위치 등)을 가지고 있는지와 어떤 웹 페이지에서 이를 사용할 수 있는지를 나타냅니다.
브라우저 확장 프로그램은 매우 특권적일 수 있으므로, 악의적인 확장 프로그램이나 손상된 확장 프로그램은 공격자가 민감한 정보를 훔치고 사용자에 대해 스파이할 수 있는 다양한 수단을 허용할 수 있습니다.
이 설정이 어떻게 작동하는지 및 어떻게 악용될 수 있는지 확인하세요:
BrowExt - permissions & host_permissionscontent_security_policy
콘텐츠 보안 정책은 manifest.json
내에서도 선언할 수 있습니다. 정의된 것이 있다면, 취약할 수 있습니다.
브라우저 확장 페이지의 기본 설정은 다소 제한적입니다:
CSP 및 잠재적 우회에 대한 자세한 내용은 다음을 확인하십시오:
Content Security Policy (CSP) Bypassweb_accessible_resources
웹 페이지가 브라우저 확장의 페이지에 접근하기 위해서는, 예를 들어 .html
페이지, 이 페이지는 manifest.json
의 web_accessible_resources
필드에 언급되어야 합니다.
예를 들어:
이 페이지는 다음과 같은 URL에서 접근할 수 있습니다:
공개 확장에서 extension-id에 접근할 수 있습니다:
하지만, manifest.json
매개변수 **use_dynamic_url
**이 사용되면, 이 id는 동적일 수 있습니다.
여기 언급된 페이지가 있더라도, Content Security Policy 덕분에 ClickJacking에 대해 보호될 수 있습니다. 따라서 ClickJacking 공격이 가능한지 확인하기 전에 (frame-ancestors 섹션) 이를 확인해야 합니다.
이 페이지에 접근할 수 있는 것은 이 페이지들이 잠재적으로 ClickJacking에 취약할 수 있음을 의미합니다:
BrowExt - ClickJacking이 페이지들이 무작위 URL이 아닌 확장만 로드할 수 있도록 허용하면 ClickJacking 공격을 방지할 수 있습니다.
**web_accessible_resources
**의 페이지와 확장의 다른 페이지들도 백그라운드 스크립트에 연락할 수 있습니다. 따라서 이러한 페이지 중 하나가 XSS에 취약하다면 더 큰 취약점을 열 수 있습니다.
또한, **web_accessible_resources
**에 표시된 페이지는 iframe 내에서만 열 수 있지만, 새 탭에서 확장 ID를 알고 있으면 확장의 모든 페이지에 접근할 수 있습니다. 따라서 동일한 매개변수를 악용하는 XSS가 발견되면, 페이지가 **web_accessible_resources
**에 구성되어 있지 않더라도 악용될 수 있습니다.
externally_connectable
문서에 따르면, "externally_connectable"
매니페스트 속성은 어떤 확장과 웹 페이지가 runtime.connect 및 runtime.sendMessage를 통해 귀하의 확장에 연결할 수 있는지를 선언합니다.
externally_connectable
키가 귀하의 확장 매니페스트에 선언되지 않았거나 **"ids": ["*"]
**로 선언된 경우, 모든 확장이 연결할 수 있지만, 웹 페이지는 연결할 수 없습니다.
특정 ID가 지정된 경우, 예를 들어 "ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
, 오직 해당 애플리케이션만 연결할 수 있습니다.
matches가 지정된 경우, 해당 웹 앱은 연결할 수 있습니다:
비어 있는 것으로 지정된 경우: "externally_connectable": {}
, 어떤 앱이나 웹도 연결할 수 없습니다.
여기에서 적은 확장 및 URL이 표시될수록 공격 표면이 작아집니다.
웹 페이지가 XSS 또는 탈취에 취약한 경우 **externally_connectable
**에 표시되면, 공격자는 배경 스크립트에 직접 메시지를 보낼 수 있어, Content Script와 그 CSP를 완전히 우회할 수 있습니다.
따라서, 이는 매우 강력한 우회입니다.
게다가, 클라이언트가 악성 확장을 설치하면, 취약한 확장과 통신할 수 없더라도 허용된 웹 페이지에 XSS 데이터를 주입하거나 WebRequest
또는 DeclarativeNetRequest
API를 남용하여 특정 도메인에서 요청을 조작하고 JavaScript 파일에 대한 페이지 요청을 변경할 수 있습니다. (대상 페이지의 CSP가 이러한 공격을 방지할 수 있습니다). 이 아이디어는 이 글에서 나왔습니다.
Content script와 웹 페이지 간의 통신에는 일반적으로 포스트 메시지가 사용됩니다. 따라서 웹 애플리케이션에서는 일반적으로 window.postMessage
함수 호출을 찾을 수 있으며, Content script에서는 **window.addEventListener
**와 같은 리스너를 찾을 수 있습니다. 그러나 확장이 Post Message를 보내 웹 애플리케이션과 통신할 수도 있으며 (따라서 웹은 이를 예상해야 함) 웹이 새 스크립트를 로드하도록 만들 수도 있습니다.
일반적으로 chrome.runtime.sendMessage
함수가 확장 내에서 메시지를 보내는 데 사용되며 (일반적으로 background
스크립트에서 처리됨), 이를 수신하고 처리하기 위해 **chrome.runtime.onMessage.addListener
**를 호출하는 리스너가 선언됩니다.
단일 메시지를 보내는 대신 지속적인 연결을 위해 **chrome.runtime.connect()
**를 사용할 수도 있으며, 다음 예제와 같이 메시지를 보내고 받는 데 사용할 수 있습니다:
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE) GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)