.. | ||
browext-clickjacking.md | ||
browext-permissions-and-host_permissions.md | ||
browext-xss-example.md | ||
README.md |
브라우저 익스텐션 펜테스팅 방법론
htARTE (HackTricks AWS Red Team Expert)를 통해 제로부터 영웅이 될 때까지 AWS 해킹을 배우세요 htARTE (HackTricks AWS Red Team Expert)!
HackTricks를 지원하는 다른 방법:
- 회사가 HackTricks에 광고되길 원하거나 HackTricks를 PDF로 다운로드하길 원한다면 구독 요금제를 확인하세요!
- 공식 PEASS & HackTricks 굿즈를 구매하세요
- The PEASS Family를 발견하세요, 당사의 독점 NFTs 컬렉션
- 💬 Discord 그룹 또는 텔레그램 그룹에 가입하거나 트위터 🐦 @carlospolopm를 팔로우하세요.
- HackTricks 및 HackTricks Cloud github 저장소에 PR을 제출하여 해킹 트릭을 공유하세요.
기본 정보
브라우저 익스텐션은 JavaScript로 작성되며 브라우저에 의해 백그라운드에서 로드됩니다. DOM을 가지고 있지만 다른 사이트의 DOM과 상호작용할 수 있습니다. 이는 다른 사이트의 기밀성, 무결성 및 가용성(CIA)을 침해할 수 있음을 의미합니다.
주요 구성 요소
익스텐션 레이아웃은 시각화되었을 때 가장 잘 보이며 세 가지 구성 요소로 구성됩니다. 각 구성 요소를 자세히 살펴보겠습니다.
콘텐츠 스크립트
각 콘텐츠 스크립트는 단일 웹 페이지의 DOM에 직접 액세스할 수 있으며 잠재적으로 악의적인 입력에 노출됩니다. 그러나 콘텐츠 스크립트에는 확장 기능 코어로 메시지를 보낼 수 있는 능력 외에는 권한이 없습니다.
익스텐션 코어
익스텐션 코어에는 대부분의 익스텐션 권한/액세스가 포함되어 있지만, 익스텐션 코어는 XMLHttpRequest 및 콘텐츠 스크립트를 통해 웹 콘텐츠와 상호작용할 수 있습니다. 또한 익스텐션 코어는 호스트 머신에 직접 액세스할 수 없습니다.
네이티브 바이너리
익스텐션은 사용자의 전체 권한을 가진 호스트 머신에 액세스할 수 있는 네이티브 바이너리를 허용합니다. 네이티브 바이너리는 Flash 및 기타 브라우저 플러그인에서 사용되는 표준 Netscape 플러그인 응용 프로그램 프로그래밍 인터페이스(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*"],
}
],
include_globs
및 **exclude_globs
**를 사용하여 더 많은 URL을 포함하거나 제외하는 것도 가능합니다.
이는 페이지에 설명 버튼을 추가하는 예제 콘텐츠 스크립트이며, 저장소 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 Developers documentation에서 확인할 수 있으며, 파이어폭스의 경우 MDN이 주요 소스로 작용합니다.
또한 콘텐츠 스크립트는 백그라운드 스크립트와 통신할 수 있어서 작업을 수행하고 응답을 전달할 수 있습니다.
{% endhint %}
크롬에서 콘텐츠 스크립트를 보고 디버깅하기 위해 Chrome 개발자 도구 메뉴에는 Options > More tools > Developer tools를 통해 액세스하거나 Ctrl + Shift + I를 누르면 됩니다.
개발자 도구가 표시된 후 Source 탭을 클릭한 다음 Content Scripts 탭을 클릭합니다. 이를 통해 여러 확장 프로그램에서 실행 중인 콘텐츠 스크립트를 관찰하고 실행 흐름을 추적하기 위해 중단점을 설정할 수 있습니다.
삽입된 콘텐츠 스크립트
{% hint style="success" %}
콘텐츠 스크립트는 필수적이지 않습니다. 동적으로 스크립트를 삽입하거나 프로그래밍 방식으로 웹 페이지에 **tabs.executeScript
**를 통해 삽입하는 것도 가능합니다. 이는 실제로 더 세분화된 제어를 제공합니다.
{% 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,
});
});
스크립팅 권한 예제
// 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" });
콘텐츠 스크립트 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
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" %}
**externally_connectable
**에 XSS 또는 탈취 공격에 취약한 웹 페이지가 표시된 경우, 공격자는 백그라운드 스크립트에 직접 메시지를 보낼 수 있게 되어 Content Script 및 해당 CSP를 완전히 우회할 수 있습니다.
따라서, 이는 매우 강력한 우회입니다.
게다가, 클라이언트가 악성 확장 프로그램을 설치하면 취약한 확장 프로그램과 통신이 허용되지 않더라도 허용된 웹 페이지에 XSS 데이터를 삽입하거나 WebRequest
또는 DeclarativeNetRequest
API를 남용하여 대상 도메인의 요청을 조작하여 JavaScript 파일의 요청을 변경할 수 있습니다. (대상 페이지의 CSP가 이러한 공격을 방지할 수 있음에 유의하십시오). 이 아이디어는 이 설명서에서 나온 것입니다.
{% endhint %}
웹 ↔︎ 콘텐츠 스크립트 통신
콘텐츠 스크립트가 작동하는 환경과 호스트 페이지가 존재하는 환경은 서로 분리되어 있어 격리가 보장됩니다. 이러한 격리에도 불구하고 두 환경은 페이지의 **문서 객체 모델 (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);
{% endcode %}
{% code title="example.js" %}
document.getElementById("theButton").addEventListener("click", () => {
window.postMessage(
{type : "FROM_PAGE", text : "Hello from the webpage!"}, "*");
}, false);
{% endcode %}
안전한 포스트 메시지 통신은 받은 메시지의 신뢰성을 확인해야 합니다. 이는 다음을 확인하여 수행할 수 있습니다:
event.isTrusted
: 이는 이벤트가 사용자 조치에 의해 트리거된 경우에만 True입니다.- 콘텐츠 스크립트는 사용자가 일부 조치를 취할 때만 메시지를 기대할 수 있습니다.
- 원본 도메인: 메시지를 기대하는 경우에는 허용 목록의 도메인만 허용할 수 있습니다.
- 정규식을 사용하는 경우 매우 주의해야 합니다.
- 소스:
received_message.source !== window
는 메시지가 콘텐츠 스크립트가 수신 대기 중인 동일한 창에서 왔는지 확인하는 데 사용할 수 있습니다.
이전 체크는 수행되었더라도 취약할 수 있으므로 다음 페이지에서 잠재적인 포스트 메시지 우회를 확인하세요:
{% 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을 신뢰한다면, 웹은 이 데이터를 수정할 수 있습니다(웹은 신뢰해서는 안 되거나 XSS 취약점이 있기 때문에) 그리고 콘텐츠 스크립트를 손상시킬 수 있습니다.
브라우저 확장 프로그램을 손상시키기 위한 DOM 기반 XSS 예제를 다음에서 찾을 수도 있습니다:
{% content-ref url="browext-xss-example.md" %} browext-xss-example.md {% endcontent-ref %}
메모리/코드 내의 민감한 정보
브라우저 확장 프로그램이 민감한 정보를 내부 메모리에 저장하는 경우, 이 정보가 덤프될 수 있으며(특히 Windows 기기에서) 이 정보를 검색할 수 있습니다.
따라서, 브라우저 확장 프로그램의 메모리는 안전하다고 보면 안 되며 자격 증명이나 니모닉 구절과 같은 민감한 정보는 저장해서는 안 됩니다.
물론, 코드에 민감한 정보를 넣지 마십시오, 그렇게 되면 공개될 것입니다.
브라우저에서 메모리를 덤프하려면 프로세스 메모리를 덤프하거나 브라우저 확장 프로그램의 설정으로 이동하여 **Inspect pop-up
**을 클릭 -> Memory
섹션에서 **Take a snaphost
**를 클릭하고 **CTRL+F
**를 사용하여 스냅샷 내에서 민감한 정보를 검색할 수 있습니다.
콘텐츠 스크립트 ↔︎ 백그라운드 스크립트 통신
콘텐츠 스크립트는 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()
함수는 동기적으로 실행되었습니다. sendResponse()
를 비동기적으로 실행하도록 onMessage
이벤트 핸들러를 수정하려면 return true;
를 반드시 포함해야 합니다.
여러 페이지가 onMessage
이벤트를 수신하도록 설정된 시나리오에서 중요한 고려 사항은 특정 이벤트에 대해 sendResponse()
를 실행하는 첫 번째 페이지만이 응답을 효과적으로 전달할 수 있다는 것입니다. 동일한 이벤트에 대한 이후 응답은 고려되지 않습니다.
새로운 확장 프로그램을 작성할 때는 콜백 대신 프로미스를 선호해아 합니다. 콜백의 사용에 관한 중요한 점은 sendResponse()
함수가 동기적인 컨텍스트 내에서 직접 실행되거나 이벤트 핸들러가 비동기 작업을 나타내기 위해 true
를 반환할 때만 유효하다는 것입니다. 핸들러 중 어느 것도 true
를 반환하지 않거나 sendResponse()
함수가 메모리에서 제거되면(가비지 수집), sendMessage()
함수와 연관된 콜백이 기본적으로 트리거됩니다.
브라우저에서 확장 프로그램 로드하기
- 브라우저 확장 프로그램 다운로드 및 압축 해제
- **
chrome://extensions/
**로 이동하고개발자 모드
를 활성화합니다. 압축 해제된 확장 프로그램 로드
버튼을 클릭합니다.
Firefox에서는 **about:debugging#/runtime/this-firefox
**로 이동하고 임시 추가 기능 로드
버튼을 클릭합니다.
스토어에서 소스 코드 가져오기
크롬 확장 프로그램의 소스 코드는 다양한 방법으로 얻을 수 있습니다. 각 옵션에 대한 자세한 설명과 지침은 아래에 나와 있습니다.
명령줄을 통한 ZIP 파일로 확장 프로그램 다운로드
크롬 확장 프로그램의 소스 코드는 명령줄을 사용하여 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 Web Store에서 설치할 수 있습니다. 뷰어의 소스 코드는 GitHub 저장소에서 확인할 수 있습니다.
로컬로 설치된 확장 프로그램의 소스 보기
로컬로 설치된 Chrome 확장 프로그램도 검사할 수 있습니다. 다음과 같이 진행할 수 있습니다:
chrome://version/
을 방문하여 "Profile Path" 필드를 찾아 Chrome 로컬 프로필 디렉토리에 액세스합니다.- 프로필 디렉토리 내의
Extensions/
하위 폴더로 이동합니다. - 이 폴더에는 일반적으로 읽기 가능한 형식의 소스 코드가 포함된 모든 설치된 확장 프로그램이 포함되어 있습니다.
확장 프로그램을 식별하기 위해 ID를 이름에 매핑할 수 있습니다:
about:extensions
페이지에서 개발자 모드를 활성화하여 각 확장 프로그램의 ID를 확인할 수 있습니다.- 각 확장 프로그램의 폴더 내에는 읽기 가능한
name
필드가 포함된manifest.json
파일이 있어 확장 프로그램을 식별하는 데 도움이 됩니다.
파일 아카이버 또는 언패커 사용
Chrome Web Store로 이동하여 확장 프로그램을 다운로드합니다. 파일의 확장자는 .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 취약점을 확인합니다.
- 콘텐츠 스크립트가 DOM 세부 정보에 액세스하는 경우, 해당 정보가 웹에서 수정되어 XSS를 도입하지 않는지 확인합니다.
- 특히 이 통신이 콘텐츠 스크립트 -> 백그라운드 스크립트 통신에 관여하는 경우 특별히 강조합니다.
- 브라우저 확장 프로그램 코드 내에 민감한 정보를 저장해서는 안 됩니다.
- 브라우저 확장 프로그램 메모리에 민감한 정보를 저장해서는 안 됩니다.
도구
Tarnish
- 제공된 Chrome 웹스토어 링크에서 Chrome 확장 프로그램을 추출합니다.
- manifest.json 뷰어: 확장 프로그램의 manifest의 JSON-prettified 버전을 간단히 표시합니다.
- 지문 분석: web_accessible_resources의 감지 및 Chrome 확장 프로그램 지문 JavaScript의 자동 생성.
- 잠재적인 Clickjacking 분석: web_accessible_resources 지시문이 설정된 확장 프로그램 HTML 페이지의 감지. 이러한 페이지는 페이지의 목적에 따라 Clickjacking에 취약할 수 있습니다.
- 권한 경고 뷰어: 사용자가 확장 프로그램을 설치하려고 할 때 표시되는 모든 Chrome 권한 프롬프트 경고 목록을 표시합니다.
- 위험한 기능: 공격자가 악용할 수 있는 위험한 기능의 위치를 표시합니다 (예: innerHTML, chrome.tabs.executeScript와 같은 기능).
- 진입점: 사용자/외부 입력을 받는 확장 프로그램의 위치를 표시합니다. 이는 확장 프로그램의 표면적인 영역을 이해하고 악의적으로 조작된 데이터를 확장 프로그램에 보낼 수 있는 잠재적인 지점을 찾는 데 유용합니다.
- 위험한 기능 및 진입점 스캐너는 생성된 경고에 대해 다음을 제공합니다:
- 경고를 일으킨 코드 스니펫 및 라인.
- 문제에 대한 설명.
- 경고가 발생한 파일의 전체 소스 파일을 볼 수 있는 "View File" 버튼.
- 경고를 일으킨 파일의 경로.
- 경고를 일으킨 파일의 전체 Chrome 확장 프로그램 URI.
- JavaScript 파일에 취약한 라인이 있는 경우, 해당 라인이 포함된 모든 페이지의 경로 및 해당 페이지의 유형 및 web_accessible_resource 상태.
- 콘텐츠 보안 정책 (CSP) 분석 및 우회 확인기: 확장 프로그램의 CSP의 취약점을 지적하고 허용 목록에 있는 CDN 등으로 인해 CSP를 우회할 수 있는 잠재적인 방법을 밝혀냅니다.
- 알려진 취약한 라이브러리: Retire.js를 사용하여 알려진 취약한 JavaScript 라이브러리의 사용을 확인합니다.
- 확장 프로그램 및 형식화된 버전 다운로드.
- 원본 확장 프로그램 다운로드.
- 확장 프로그램의 형식화된 버전 다운로드 (자동으로 예쁘게 정리된 HTML 및 JavaScript).
- 스캔 결과의 자동 캐싱, 확장 프로그램 스캔 실행은 처음에는 많은 시간이 걸리지만 두 번째로 실행할 때, 확장 프로그램이 업데이트되지 않은 경우 결과가 캐시되어 거의 즉시 실행됩니다.
- 링크 가능한 보고서 URL, tarnish에 의해 생성된 확장 프로그램 보고서를 다른 사람에게 쉽게 링크할 수 있습니다.
Neto
프로젝트 Neto는 Firefox 및 Chrome과 같은 잘 알려진 브라우저용 브라우저 플러그인 및 확장 프로그램의 숨겨진 기능을 분석하고 해독하기 위해 고안된 Python 3 패키지입니다. 이는 패키지된 파일을 압축 해제하여 확장 프로그램의 manifest.json
, 로컬라이제이션 폴더 또는 Javascript 및 HTML 소스 파일에서 이러한 기능을 추출하는 프로세스를 자동화합니다.
참고 자료
- 이 방법론에 대한 도움을 준 @naivenom에게 감사드립니다.
- https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing
- https://palant.info/2022/08/10/anatomy-of-a-basic-extension/
- https://palant.info/2022/08/24/attack-surface-of-extension-pages/
- https://palant.info/2022/08/31/when-extension-pages-are-web-accessible/
- https://help.passbolt.com/assets/files/PBL-02-report.pdf
- https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts
- https://developer.chrome.com/docs/extensions/mv2/background-pages
- https://thehackerblog.com/kicking-the-rims-a-guide-for-securely-writing-and-auditing-chrome-extensions/
- https://gist.github.com/LongJohnCoder/9ddf5735df3a4f2e9559665fb864eac0
htARTE (HackTricks AWS Red Team Expert)를 통해 제로부터 AWS 해킹을 전문가로 배우세요
HackTricks를 지원하는 다른 방법:
- HackTricks에서 귀하의 회사 광고를 보고 싶거나 PDF 형식의 HackTricks를 다운로드하려면 구독 요금제를 확인하세요!
- 공식 PEASS & HackTricks 스왜그를 구매하세요
- PEASS Family를 발견하세요, 당사의 독점 NFTs 컬렉션
- 💬 Discord 그룹에 가입하거나 텔레그램 그룹에 가입하거나 Twitter 🐦에서 팔로우하세요 @carlospolopm.**
- 해킹 요령을 공유하려면 PR을 제출하여 HackTricks 및 HackTricks Cloud github 저장소를 확인하세요.