.. | ||
browext-clickjacking.md | ||
browext-permissions-and-host_permissions.md | ||
browext-xss-example.md | ||
README.md |
브라우저 확장 프로그램 펜테스팅 방법론
htARTE (HackTricks AWS Red Team Expert)를 통해 AWS 해킹을 처음부터 전문가까지 배워보세요!
HackTricks를 지원하는 다른 방법:
- 회사를 HackTricks에서 광고하거나 HackTricks를 PDF로 다운로드하려면 SUBSCRIPTION PLANS를 확인하세요!
- 공식 PEASS & HackTricks 스웨그를 얻으세요.
- The PEASS Family를 발견하세요. 독점적인 NFTs 컬렉션입니다.
- 💬 Discord 그룹 또는 텔레그램 그룹에 참여하거나 Twitter 🐦 @carlospolopm을 팔로우하세요.
- Hacking 트릭을 공유하려면 HackTricks 및 HackTricks Cloud github 저장소에 PR을 제출하세요.
기본 정보
브라우저 확장 프로그램은 JavaScript로 작성되며 브라우저에 의해 백그라운드에서 로드됩니다. DOM을 가지고 있지만 다른 사이트의 DOM과 상호작용할 수 있습니다. 이는 다른 사이트의 기밀성, 무결성 및 가용성(CIA)을 침해할 수 있음을 의미합니다.
주요 구성 요소
확장 프로그램 레이아웃은 시각화되었을 때 가장 잘 보이며 세 가지 구성 요소로 구성됩니다. 각 구성 요소를 자세히 살펴보겠습니다.
콘텐츠 스크립트
각 콘텐츠 스크립트는 단일 웹 페이지의 DOM에 직접 액세스하며 잠재적으로 악성 입력에 노출됩니다. 그러나 콘텐츠 스크립트에는 확장 프로그램 코어로 메시지를 보낼 수 있는 능력 외에는 권한이 없습니다.
확장 프로그램 코어
확장 프로그램 코어에는 대부분의 확장 프로그램 권한/액세스가 포함되어 있지만, 확장 프로그램 코어는 XMLHttpRequest와 콘텐츠 스크립트를 통해서만 웹 콘텐츠와 상호작용할 수 있습니다. 또한, 확장 프로그램 코어는 호스트 머신에 직접 액세스할 수 없습니다.
네이티브 바이너리
확장 프로그램은 사용자의 전체 권한으로 호스트 머신에 액세스할 수 있는 네이티브 바이너리를 허용합니다. 네이티브 바이너리는 플래시 및 기타 브라우저 플러그인에서 사용하는 표준 넷스케이프 플러그인 응용 프로그래밍 인터페이스(NPAPI)를 통해 확장 프로그램 코어와 상호작용합니다.
경계
{% hint style="danger" %} 사용자의 전체 권한을 얻으려면 공격자는 콘텐츠 스크립트에서 확장 프로그램 코어로 악성 입력을 전달하고, 확장 프로그램 코어에서 네이티브 바이너리로 악성 입력을 전달하도록 확장 프로그램을 설득해야 합니다. {% endhint %}
확장 프로그램의 각 구성 요소는 강력한 보호 경계에 의해 서로 분리됩니다. 각 구성 요소는 별도의 운영 체제 프로세스에서 실행됩니다. 콘텐츠 스크립트와 확장 프로그램 코어는 대부분의 운영 체제 서비스에서 사용할 수 없는 샌드박스 프로세스에서 실행됩니다.
또한, 콘텐츠 스크립트는 별도의 JavaScript 힙에서 실행되어 관련 웹 페이지와 분리됩니다. 콘텐츠 스크립트와 웹 페이지는 동일한 기본 DOM에 액세스하지만 두 가지는 JavaScript 포인터를 교환하지 않으므로 JavaScript 기능이 누출되지 않습니다.
manifest.json
Chrome 확장 프로그램은 .crx 파일 확장자를 가진 ZIP 폴더입니다. 확장 프로그램의 코어는 폴더의 루트에 있는 manifest.json
파일로 레이아웃, 권한 및 기타 구성 옵션을 지정합니다.
예시:
{
"manifest_version": 2,
"name": "My extension",
"version": "1.0",
"permissions": [
"storage"
],
"content_scripts": [
{
"js": [
"script.js"
],
"matches": [
"https://example.com/*",
"https://www.example.com/*"
],
"exclude_matches": ["*://*/*business*"],
}
],
"background": {
"scripts": [
"background.js"
]
},
"options_ui": {
"page": "options.html"
}
}
content_scripts
콘텐츠 스크립트는 사용자가 일치하는 페이지로 이동할 때마다 로드됩니다. 우리의 경우에는 https://example.com/*
표현과 일치하고 *://*/*/business*
정규식과 일치하지 않는 모든 페이지입니다. 이 스크립트는 페이지 자체의 스크립트처럼 실행되며 페이지의 문서 객체 모델(DOM)에 임의로 액세스할 수 있습니다.
"content_scripts": [
{
"js": [
"script.js"
],
"matches": [
"https://example.com/*",
"https://www.example.com/*"
],
"exclude_matches": ["*://*/*business*"],
}
],
더 많은 URL을 포함하거나 제외하기 위해서는 **include_globs
**와 **exclude_globs
**를 사용할 수도 있습니다.
다음은 페이지에 설명 버튼을 추가하는 예제 콘텐츠 스크립트입니다. 이 스크립트는 저장소 API를 사용하여 확장 프로그램의 저장소에서 message
값을 검색합니다.
chrome.storage.local.get("message", result =>
{
let div = document.createElement("div");
div.innerHTML = result.message + " <button>Explain</button>";
div.querySelector("button").addEventListener("click", () =>
{
chrome.runtime.sendMessage("explain");
});
document.body.appendChild(div);
});
이 버튼을 클릭하면 콘텐츠 스크립트에서 runtime.sendMessage() API를 통해 확장 프로그램 페이지로 메시지가 전송됩니다. 이는 콘텐츠 스크립트가 API에 직접 액세스할 수 없는 제한 때문에 발생하며, storage
가 예외 중 하나입니다. 이러한 예외를 넘어선 기능을 위해 메시지가 콘텐츠 스크립트가 통신할 수 있는 확장 프로그램 페이지로 전송됩니다.
{% hint style="warning" %}
브라우저에 따라 콘텐츠 스크립트의 기능이 약간 다를 수 있습니다. 크로미움 기반 브라우저의 경우, 기능 목록은 Chrome 개발자 문서에서 확인할 수 있으며, 파이어폭스의 경우 MDN이 주요 출처입니다.
또한 콘텐츠 스크립트는 백그라운드 스크립트와 통신할 수 있는 능력을 갖고 있어 작업을 수행하고 응답을 전달할 수 있습니다.
{% endhint %}
크롬에서 콘텐츠 스크립트를 보고 디버깅하기 위해 Chrome 개발자 도구 메뉴에는 옵션 > 추가 도구 > 개발자 도구 또는 Ctrl + Shift + I를 눌러 접근할 수 있습니다.
개발자 도구가 표시되면 소스 탭을 클릭한 다음 콘텐츠 스크립트 탭을 클릭합니다. 이를 통해 다양한 확장 프로그램의 실행 중인 콘텐츠 스크립트를 관찰하고 실행 흐름을 추적하기 위해 중단점을 설정할 수 있습니다.
삽입된 콘텐츠 스크립트
{% hint style="success" %} 콘텐츠 스크립트는 필수적이지 않습니다. 대신 동적으로 스크립트를 삽입하고 프로그래밍 방식으로 웹 페이지에 주입할 수 있습니다. 이렇게 하면 더 세밀한 제어가 가능합니다. {% endhint %}
콘텐츠 스크립트를 프로그래밍 방식으로 주입하기 위해서는 스크립트를 주입할 페이지에 대한 호스트 권한이 확장 프로그램에 필요합니다. 이러한 권한은 확장 프로그램의 매니페스트 내에서 요청하거나 activeTab을 통해 일시적으로 보호받을 수 있습니다.
activeTab 기반 확장 프로그램 예제
{% code title="manifest.json" %}
{
"name": "My extension",
...
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_title": "Action Button"
}
}
{% endcode %}
- 클릭 시 JS 파일 주입:
// content-script.js
document.body.style.backgroundColor = "orange";
//service-worker.js - Inject the JS file
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
files: ["content-script.js"]
});
});
- 클릭 시 함수 주입:
//service-worker.js - Inject a function
function injectedFunction() {
document.body.style.backgroundColor = "orange";
}
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target : {tabId : tab.id},
func : injectedFunction,
});
});
스크립팅 권한 예제
In this example, we will explore how to leverage scripting permissions in browser extensions for pentesting purposes.
이 예제에서는 브라우저 확장 프로그램의 스크립팅 권한을 활용하여 펜테스팅을 수행하는 방법을 알아보겠습니다.
-
Identify the target extension: First, we need to identify the target browser extension that has scripting permissions. This can be done by examining the extension's manifest file or by inspecting the extension's source code.
-
대상 확장 프로그램 식별: 먼저, 스크립팅 권한을 가진 대상 브라우저 확장 프로그램을 식별해야 합니다. 이는 확장 프로그램의 매니페스트 파일을 조사하거나 확장 프로그램의 소스 코드를 검사하여 확인할 수 있습니다.
-
Analyze the extension's functionality: Once we have identified the target extension, we need to analyze its functionality to understand how it interacts with web pages. This can involve examining the extension's JavaScript files, background scripts, and content scripts.
-
확장 프로그램의 기능 분석: 대상 확장 프로그램을 식별한 후, 해당 확장 프로그램이 웹 페이지와 상호작용하는 방식을 이해하기 위해 기능을 분석해야 합니다. 이는 확장 프로그램의 JavaScript 파일, 백그라운드 스크립트, 콘텐츠 스크립트를 조사하는 것을 포함할 수 있습니다.
-
Exploit scripting permissions: Once we have a good understanding of the extension's functionality, we can start exploiting its scripting permissions. This can involve injecting malicious code into the extension's JavaScript files or intercepting and modifying the extension's communication with web pages.
-
스크립팅 권한 악용: 확장 프로그램의 기능을 충분히 이해한 후, 스크립팅 권한을 악용할 수 있습니다. 이는 악성 코드를 확장 프로그램의 JavaScript 파일에 삽입하거나, 확장 프로그램과 웹 페이지 간의 통신을 가로채고 수정하는 것을 포함할 수 있습니다.
-
Test and validate the exploit: Finally, we need to test and validate the exploit to ensure that it works as intended. This can involve performing various actions on web pages to verify that the exploit is successful and that we can achieve our pentesting objectives.
-
악용 테스트 및 검증: 마지막으로, 의도한 대로 작동하는지 확인하기 위해 악용을 테스트하고 검증해야 합니다. 이는 웹 페이지에서 다양한 작업을 수행하여 악용이 성공적이며 펜테스팅 목표를 달성할 수 있는지 확인하는 것을 포함할 수 있습니다.
// service-workser.js
chrome.scripting.registerContentScripts([{
id : "test",
matches : [ "https://*.example.com/*" ],
excludeMatches : [ "*://*/*business*" ],
js : [ "contentScript.js" ],
}]);
// Another example
chrome.tabs.executeScript(tabId, { file: "content_script.js" });
더 많은 URL을 포함하거나 제외하기 위해 **include_globs
**와 **exclude_globs
**를 사용할 수도 있습니다.
콘텐츠 스크립트 run_at
run_at
필드는 JavaScript 파일이 웹 페이지에 주입되는 시점을 제어합니다. 선호되는 기본값은 "document_idle"
입니다.
가능한 값은 다음과 같습니다:
document_idle
: 가능한 경우 언제든지document_start
:css
파일 이후에, 그러나 다른 DOM이 구성되거나 다른 스크립트가 실행되기 전에document_end
: DOM이 완전히 완료된 직후, 그러나 이미지와 프레임과 같은 하위 리소스가 로드되기 전에
manifest.json
을 통해
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.example.com/*"],
"run_at": "document_idle",
"js": ["contentScript.js"]
}
],
...
}
**service-worker.js
**를 통해
chrome.scripting.registerContentScripts([{
id : "test",
matches : [ "https://*.example.com/*" ],
runAt : "document_idle",
js : [ "contentScript.js" ],
}]);
백그라운드
콘텐츠 스크립트로 전송된 메시지는 백그라운드 페이지에서 수신되며, 이 페이지는 확장 프로그램의 구성 요소들을 조정하는 중심 역할을 담당합니다. 특히, 백그라운드 페이지는 직접적인 사용자 상호작용 없이도 지속적으로 동작하며, 자체적인 문서 객체 모델(DOM)을 가지고 복잡한 상호작용과 상태 관리를 가능하게 합니다.
주요 포인트:
- 백그라운드 페이지 역할: 확장 프로그램의 다양한 부분 간의 통신과 조정을 보장하는 중추적인 역할을 합니다.
- 지속성: 사용자에게는 보이지 않지만, 확장 프로그램의 기능에는 필수적인 영역으로 지속적으로 존재합니다.
- 자동 생성: 명시적으로 정의되지 않은 경우, 브라우저는 자동으로 백그라운드 페이지를 생성합니다. 이 자동 생성된 페이지에는 확장 프로그램의 매니페스트에 지정된 모든 백그라운드 스크립트가 포함되어, 확장 프로그램의 백그라운드 작업이 원활하게 동작합니다.
{% hint style="success" %} 브라우저가 백그라운드 페이지를 자동으로 생성함으로써(명시적으로 선언되지 않은 경우), 필요한 모든 백그라운드 스크립트가 통합되고 동작함으로써, 확장 프로그램의 설정 과정이 간소화되어 편의성이 제공됩니다. {% endhint %}
예시 백그라운드 스크립트:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) =>
{
if (request == "explain")
{
chrome.tabs.create({ url: "https://example.net/explanation" });
}
})
이는 메시지를 수신하기 위해 runtime.onMessage API를 사용합니다. "explain" 메시지를 받으면 tabs API를 사용하여 새 탭에서 페이지를 엽니다.
백그라운드 스크립트를 디버깅하려면 확장 프로그램 세부 정보로 이동하여 서비스 워커를 검사할 수 있습니다. 이렇게 하면 백그라운드 스크립트가 있는 개발자 도구가 열립니다:
옵션 페이지 및 기타
브라우저 확장 프로그램에는 다양한 종류의 페이지가 포함될 수 있습니다:
- 작업 페이지는 확장 프로그램 아이콘을 클릭하면 드롭다운으로 표시됩니다.
- 확장 프로그램이 새 탭에서 로드하는 페이지입니다.
- 옵션 페이지: 이 페이지는 클릭 시 확장 프로그램 위에 표시됩니다. 이전 매니페스트에서 나는
chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca
에서 이 페이지에 액세스할 수 있었거나 다음을 클릭했습니다:
이러한 페이지는 백그라운드 페이지와 달리 필요에 따라 동적으로 콘텐츠를 로드하기 때문에 지속적이지 않음에 유의하십시오. 그럼에도 불구하고, 이러한 페이지는 백그라운드 페이지와 일부 기능을 공유합니다:
- 콘텐츠 스크립트와의 통신: 백그라운드 페이지와 유사하게, 이러한 페이지는 콘텐츠 스크립트로부터 메시지를 받아 확장 프로그램 내에서 상호 작용을 용이하게 합니다.
- 확장 프로그램 전용 API에 대한 액세스: 이러한 페이지는 확장 프로그램에 정의된 권한에 따라 확장 프로그램 전용 API에 포괄적인 액세스 권한을 갖습니다.
permissions
및 host_permissions
permissions
및 **host_permissions
**은 브라우저 확장 프로그램이 가지는 권한(저장소, 위치 등) 및 어떤 웹 페이지에서 작동할 수 있는지를 나타내는 manifest.json
의 항목입니다.
브라우저 확장 프로그램은 권한이 매우 특권적일 수 있으므로 악성 확장 프로그램이나 감염된 확장 프로그램은 공격자가 민감한 정보를 도용하고 사용자를 감시하는 다양한 수단을 제공할 수 있습니다.
이러한 설정이 작동하는 방식과 어떻게 악용될 수 있는지 확인하려면 다음을 참조하십시오:
{% content-ref url="browext-permissions-and-host_permissions.md" %} browext-permissions-and-host_permissions.md {% endcontent-ref %}
content_security_policy
콘텐츠 보안 정책은 manifest.json
내부에도 선언될 수 있습니다. 정의된 경우 취약할 수 있습니다.
브라우저 확장 프로그램 페이지의 기본 설정은 상당히 제한적입니다:
script-src 'self'; object-src 'self';
CSP와 가능한 우회 방법에 대한 자세한 정보는 다음을 참조하십시오:
{% content-ref url="../content-security-policy-csp-bypass/" %} content-security-policy-csp-bypass {% endcontent-ref %}
web_accessible_resources
웹 페이지가 브라우저 확장 프로그램의 페이지(예: .html
페이지)에 액세스하려면 해당 페이지를 manifest.json
의 web_accessible_resources
필드에 언급해야 합니다.
예를 들어:
{
...
"web_accessible_resources": [
{
"resources": [ "images/*.png" ],
"matches": [ "https://example.com/*" ]
},
{
"resources": [ "fonts/*.woff" ],
"matches": [ "https://example.com/*" ]
}
],
...
}
이러한 페이지는 다음과 같은 URL로 접근할 수 있습니다:
chrome-extension://<extension-id>/message.html
공개 확장 프로그램에서는 확장 프로그램 ID에 접근할 수 있습니다:
하지만, manifest.json
매개변수 **use_dynamic_url
**을 사용하면이 ID가 동적 일 수 있습니다.
이러한 페이지에 액세스 할 수 있으면 이러한 페이지는 잠재적으로 취약한 ClickJacking이 됩니다:
{% content-ref url="browext-clickjacking.md" %} browext-clickjacking.md {% endcontent-ref %}
{% hint style="success" %} 이러한 페이지가 임의의 URL이 아닌 확장 프로그램에 의해서만로드 될 수 있도록 허용하면 ClickJacking 공격을 방지할 수 있습니다. {% endhint %}
externally_connectable
문서에 따르면, "externally_connectable"
매니페스트 속성은 runtime.connect 및 runtime.sendMessage를 통해 확장 프로그램에 연결할 수 있는 확장 프로그램 및 웹 페이지를 선언합니다.
- 확장 프로그램의 매니페스트에
externally_connectable
키가 선언되지 않았거나 **"ids": ["*"]
**로 선언된 경우, 모든 확장 프로그램은 연결할 수 있지만 웹 페이지는 연결할 수 없습니다. - 특정 ID가 지정된 경우,
"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
와 같이, 해당 응용 프로그램만 연결할 수 있습니다. - 일치하는 경우, 해당 웹 앱은 연결할 수 있습니다:
"matches": [
"https://*.google.com/*",
"*://*.chromium.org/*",
- 비어 있는 경우:
"externally_connectable": {}
, 어떤 앱이나 웹도 연결할 수 없습니다.
여기에 나열된 확장 프로그램과 URL이 적을수록, 공격 표면이 작아집니다.
{% hint style="danger" %}
XSS나 탈취에 취약한 웹 페이지가 **externally_connectable
**에 지정된 경우, 공격자는 Content Script와 그의 CSP를 완전히 우회하여 백그라운드 스크립트로 직접 메시지를 보낼 수 있습니다.
따라서, 이것은 매우 강력한 우회 방법입니다. {% endhint %}
웹 ↔︎ Content Script 통신
콘텐츠 스크립트가 작동하는 환경과 호스트 페이지가 존재하는 환경은 서로 분리되어 있어 격리가 보장됩니다. 그럼에도 불구하고, 둘 다 페이지의 문서 객체 모델(DOM), 공유 리소스와 상호작용할 수 있는 능력을 갖고 있습니다. 호스트 페이지가 콘텐츠 스크립트와 통신하거나 간접적으로 콘텐츠 스크립트를 통해 확장 프로그램과 통신하기 위해서는, 양측에서 접근 가능한 DOM을 통신 채널로 사용해야 합니다.
메시지 전송
{% code title="content-script.js" %}
var port = chrome.runtime.connect();
window.addEventListener("message", (event) => {
// We only accept messages from ourselves
if (event.source !== window) {
return;
}
if (event.data.type && (event.data.type === "FROM_PAGE")) {
console.log("Content script received: " + event.data.text);
port.postMessage(event.data.text);
}
}, false);
{% code title="example.js" %}
document.getElementById("theButton").addEventListener("click", () => {
window.postMessage(
{type : "FROM_PAGE", text : "Hello from the webpage!"}, "*");
}, false);
{% endcode %}
안전한 Post Message 통신은 수신된 메시지의 신뢰성을 확인해야 합니다. 이를 확인하기 위해 다음을 확인할 수 있습니다:
event.isTrusted
: 이 값은 이벤트가 사용자의 동작으로 인해 트리거된 경우에만 True입니다.- 콘텐츠 스크립트는 사용자가 일부 동작을 수행할 때만 메시지를 기대할 수 있습니다.
- origin 도메인: 메시지를 기대하는 도메인의 화이트리스트만 허용할 수 있습니다.
- 정규식을 사용하는 경우 매우 주의해야 합니다.
- Source:
received_message.source !== window
를 사용하여 메시지가 콘텐츠 스크립트가 수신 대기 중인 동일한 창에서 온 것인지 확인할 수 있습니다.
이전의 확인 작업은 수행되었더라도 취약할 수 있으므로 다음 페이지에서 잠재적인 Post Message 우회를 확인하세요:
{% content-ref url="../postmessage-vulnerabilities/" %} postmessage-vulnerabilities {% endcontent-ref %}
Iframe
다른 가능한 통신 방법은 Iframe URL을 통한 것일 수 있습니다. 예제는 다음에서 찾을 수 있습니다:
{% content-ref url="browext-xss-example.md" %} browext-xss-example.md {% endcontent-ref %}
DOM
이것은 "정확히" 통신 방법은 아니지만, 웹과 콘텐츠 스크립트는 웹 DOM에 액세스할 수 있습니다. 따라서, 콘텐츠 스크립트가 웹 DOM에서 정보를 읽고 있고, 웹 DOM을 신뢰한다면, 웹은 이 데이터를 수정할 수 있습니다 (웹을 신뢰해서는 안 되거나 XSS 취약점 때문에). 그리고 이로 인해 콘텐츠 스크립트가 손상될 수 있습니다.
브라우저 확장 프로그램을 손상시키기 위한 DOM 기반 XSS 예제도 다음에서 찾을 수 있습니다:
{% content-ref url="browext-xss-example.md" %} browext-xss-example.md {% endcontent-ref %}
메모리/코드 내의 민감한 정보
브라우저 확장 프로그램이 민감한 정보를 내부 메모리에 저장하는 경우, 이 정보는 덤프될 수 있으며 (특히 Windows 기기에서) 이 정보를 검색할 수 있습니다.
따라서, 브라우저 확장 프로그램의 메모리는 안전하지 않다고 간주되어야 하며, 자격증명이나 니모닉 구문과 같은 민감한 정보를 저장해서는 안 됩니다.
물론, 코드에 민감한 정보를 넣지 않도록 하십시오. 이는 공개될 것입니다.
콘텐츠 스크립트 ↔︎ 백그라운드 스크립트 통신
콘텐츠 스크립트는 runtime.sendMessage() 또는 tabs.sendMessage() 함수를 사용하여 일회성 JSON 직렬화 가능한 메시지를 보낼 수 있습니다.
응답을 처리하기 위해 반환된 Promise를 사용하세요. 하지만 하위 호환성을 위해 마지막 인수로 콜백을 전달할 수도 있습니다.
콘텐츠 스크립트에서 요청을 보내는 방법은 다음과 같습니다:
(async () => {
const response = await chrome.runtime.sendMessage({greeting: "hello"});
// do something with response here, not outside the function
console.log(response);
})();
확장 프로그램에서 요청을 보내는 방법(일반적으로 백그라운드 스크립트 사용) 콘텐츠 스크립트는 해당 함수를 사용할 수 있지만, 어떤 탭으로 보낼지 지정해야 합니다. 선택한 탭에 메시지를 보내는 방법의 예시는 다음과 같습니다:
// From https://stackoverflow.com/questions/36153999/how-to-send-a-message-between-chrome-extension-popup-and-content-script
(async () => {
const [tab] = await chrome.tabs.query({active: true, lastFocusedWindow: true});
const response = await chrome.tabs.sendMessage(tab.id, {greeting: "hello"});
// do something with response here, not outside the function
console.log(response);
})();
수신 측에서는 메시지를 처리하기 위해 runtime.onMessage 이벤트 리스너를 설정해야 합니다. 이는 콘텐트 스크립트나 확장 프로그램 페이지에서 동일하게 작동합니다.
// From https://stackoverflow.com/questions/70406787/javascript-send-message-from-content-js-to-background-js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting === "hello")
sendResponse({farewell: "goodbye"});
}
);
예시에서는 **sendResponse()
**가 동기적으로 실행되었습니다. onMessage
이벤트 핸들러를 비동기적으로 실행하기 위해서는 return true;
를 포함해야 합니다.
중요한 점은 여러 페이지가 onMessage
이벤트를 받도록 설정된 경우, 특정 이벤트에 대해 sendResponse()
를 실행하는 첫 번째 페이지만이 효과적으로 응답을 전달할 수 있다는 것입니다. 동일한 이벤트에 대한 후속 응답은 고려되지 않습니다.
새로운 확장 프로그램을 작성할 때는 콜백 대신 프로미스를 사용하는 것이 좋습니다. 콜백을 사용하는 경우, sendResponse()
함수는 동기적인 컨텍스트 내에서 직접 실행되거나 이벤트 핸들러가 true
를 반환하여 비동기 작업을 나타내는 경우에만 유효합니다. 어떤 핸들러도 true
를 반환하지 않거나 sendResponse()
함수가 메모리에서 제거되면 (가비지 컬렉션), sendMessage()
함수와 관련된 콜백이 기본적으로 트리거됩니다.
브라우저에서 확장 프로그램 로드하기
- 브라우저 확장 프로그램을 다운로드하고 압축을 해제합니다.
- **
chrome://extensions/
**로 이동하고개발자 모드
를 활성화합니다. 압축 해제된 확장 프로그램을 로드합니다
버튼을 클릭합니다.
Firefox에서는 **about:debugging#/runtime/this-firefox
**로 이동하고 임시 추가 기능 로드
버튼을 클릭합니다.
스토어에서 소스 코드 가져오기
Chrome 확장 프로그램의 소스 코드는 여러 가지 방법으로 얻을 수 있습니다. 각 옵션에 대한 자세한 설명과 지침은 아래에 제시되어 있습니다.
명령 줄을 통한 ZIP 파일로 확장 프로그램 다운로드
Chrome 확장 프로그램의 소스 코드는 명령 줄을 사용하여 ZIP 파일로 다운로드할 수 있습니다. 이는 curl
을 사용하여 특정 URL에서 ZIP 파일을 가져온 다음 ZIP 파일의 내용을 디렉토리에 추출하는 과정을 포함합니다. 다음은 순서입니다:
"extension_id"
를 실제 확장 프로그램의 ID로 대체합니다.- 다음 명령을 실행합니다:
extension_id=your_extension_id # Replace with the actual extension ID
curl -L -o "$extension_id.zip" "https://clients2.google.com/service/update2/crx?response=redirect&os=mac&arch=x86-64&nacl_arch=x86-64&prod=chromecrx&prodchannel=stable&prodversion=44.0.2403.130&x=id%3D$extension_id%26uc"
unzip -d "$extension_id-source" "$extension_id.zip"
CRX Viewer 웹사이트 사용
CRX Viewer 확장 프로그램 사용
또 다른 편리한 방법은 오픈 소스 프로젝트인 Chrome Extension Source Viewer를 사용하는 것입니다. 이는 Chrome 웹 스토어에서 설치할 수 있습니다. 뷰어의 소스 코드는 GitHub 저장소에서 확인할 수 있습니다.
로컬에 설치된 확장 프로그램의 소스 보기
로컬에 설치된 Chrome 확장 프로그램도 검사할 수 있습니다. 다음과 같은 방법으로 진행합니다:
chrome://version/
을 방문하여 Chrome 로컬 프로필 디렉토리에 액세스합니다. "Profile Path" 필드를 찾습니다.- 프로필 디렉토리 내의
Extensions/
하위 폴더로 이동합니다. - 이 폴더에는 일반적으로 읽을 수 있는 형식으로 소스 코드가 포함된 모든 설치된 확장 프로그램이 있습니다.
확장 프로그램을 식별하기 위해 ID를 이름에 매핑할 수 있습니다:
about:extensions
페이지에서 개발자 모드를 활성화하여 각 확장 프로그램의 ID를 확인합니다.- 각 확장 프로그램의 폴더 내에는 읽을 수 있는
name
필드가 포함된manifest.json
파일이 있으므로, 확장 프로그램을 식별하는 데 도움이 됩니다.
파일 압축 해제 도구 사용
Chrome 웹 스토어로 이동하여 확장 프로그램을 다운로드합니다. 파일의 확장자는 .crx
일 것입니다.
파일 확장자를 .zip
으로 변경합니다.
WinRAR, 7-Zip 등의 파일 압축 해제 도구를 사용하여 ZIP 파일의 내용을 추출합니다.
Chrome의 개발자 모드 사용
Chrome을 열고 chrome://extensions/
로 이동합니다.
오른쪽 상단에서 "개발자 모드"를 활성화합니다.
"압축 해제된 확장 프로그램을 로드합니다..."를 클릭합니다.
확장 프로그램의 디렉토리로 이동합니다.
이 방법은 소스 코드를 다운로드하지는 않지만, 이미 다운로드되거나 개발된 확장 프로그램의 코드를 보고 수정하는 데 유용합니다.
보안 감사 체크리스트
브라우저 확장 프로그램은 제한된 공격 표면을 가지고 있지만, 일부 확장 프로그램에는 취약점이나 강화할 수 있는 잠재적인 개선 사항이 있을 수 있습니다. 다음은 가장 일반적인 사항입니다:
- 가능한 한
permissions
요청을 제한합니다. - 가능한 한
host_permissions
을 제한합니다. - 강력한 **
content_security_policy
**를 사용합니다. - **
externally_connectable
**을 가능한 한 제한하고, 필요하지 않은 경우 기본값으로 남겨두지 않고 **{}
**로 지정합니다. - 여기서 XSS나 탈취에 취약한 URL이 언급되면, 공격자는 백그라운드 스크립트로 직접 메시지를 보낼 수 있습니다. 매우 강력한 우회 방법입니다.
- 가능한 한 **
web_accessible_resources
**를 제한합니다. 가능하면 비워두는 것이 좋습니다. - **
web_accessible_resources
**가 없지 않은 경우, ClickJacking을 확인합니다. - 확장 프로그램에서 웹 페이지로 통신이 발생하는 경우, 통신으로 인해 발생하는 XSS 취약점을 확인합니다.
- Post Messages를 사용하는 경우, Post Message 취약점을 확인합니다.
- Content Script가 DOM 세부 정보에 액세스하는 경우, 웹에 의해 수정되면 XSS를 도입하지 않는지 확인합니다.
- 이 통신이 Content Script -> Background script 통신에도 관여하는 경우 특히 주의합니다.
- 브라우저 확장 프로그램 코드에는 민감한 정보를 저장하지 않아야 합니다.
- 브라우저 확장 프로그램 메모리에는 민감한 정보를 저장하지 않아야 합니다.
도구
Tarnish
- 제공된 Chrome 웹 스토어 링크에서 Chrome 확장 프로그램을 추출합니다.
- manifest.json 뷰어: 확장 프로그램의 manifest를 JSON 형식으로 표시합니다.
- 지문 분석: web_accessible_resources를 감지하고 Chrome 확장 프로그램 지문 생성 JavaScript를 자동으로 생성합니다.
- 잠재적인 Clickjacking 분석: web_accessible_resources 지시문이 설정된 확장 프로그램 HTML 페이지를 감지합니다. 페이지의 목적에 따라 클릭재킹에 취약할 수 있습니다.
- 권한 경고 뷰어: 사용자가 확장 프로그램을 설치하려고 할 때 표시되는 모든 Chrome 권한 프롬프트 경고 목록을 표시합니다.
- 위험한 기능: 공격자가 악용할 수 있는 위험한 기능(예: innerHTML, chrome.tabs.executeScript와 같은 기능)의 위치를 표시합니다.
- 진입점: 확장 프로그램이 사용자/외부 입력을 받는 위치를 표시합니다. 이는 확장 프로그램의 표면적인 영역을 이해하고 악의적으로 조작된 데이터를 확장 프로그램에 전송할 수 있는 잠재적인 지점을 찾는 데 유용합니다.
- 위험한 기능 및 진입점 스캐너는 다음과 같은 생성된 경고를 가지고 있습니다:
- 경고를 일으킨 코드 스니펫 및 라인.
- 문제에 대한 설명.
- 코드가 포함된 전체 소스 파일을 볼 수 있는 "View File" 버튼.
- 경고된 파일의 경로.
- 경고된 파일의 전체 Chrome 확장 프로그램 URI.
- 파일의 유형(백그라운드 페이지 스크립트, 콘텐츠 스크립트, 브라우저 동작 등).
- 취약한 라인이 JavaScript 파일에 있는 경우, 포함된 모든 페이지
- 만약 회사가 HackTricks에 광고되길 원한다면 또는 PDF로 HackTricks를 다운로드하길 원한다면 SUBSCRIPTION PLANS를 확인하세요!
- 공식 PEASS & HackTricks 상품을 얻으세요.
- The PEASS Family를 발견하세요. 독점적인 NFTs 컬렉션입니다.
- 💬 Discord 그룹 또는 telegram 그룹에 참여하거나 Twitter 🐦 @carlospolopm을 팔로우하세요.
- Hacking 트릭을 공유하려면 HackTricks와 HackTricks Cloud github 저장소에 PR을 제출하세요.