.. | ||
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에 광고되길 원하거나 PDF 형식의 HackTricks를 다운로드하고 싶다면 SUBSCRIPTION PLANS를 확인하세요!
- 공식 PEASS & HackTricks 굿즈를 구매하세요
- The PEASS Family를 발견하세요, 당사의 독점 NFTs 컬렉션
- 💬 Discord 그룹에 가입하거나 텔레그램 그룹에 참여하거나 트위터 🐦 @carlospolopm를 팔로우하세요.
- 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 Developers documentation에서 확인할 수 있으며, 파이어폭스의 경우 MDN이 주요 소스로 작용합니다.
또한 콘텐츠 스크립트는 백그라운드 스크립트와 통신할 수 있어서 작업을 수행하고 응답을 전달할 수 있습니다.
{% endhint %}
크롬에서 콘텐츠 스크립트를 보고 디버깅하기 위해 Chrome 개발자 도구 메뉴에는 옵션 > 더보기 도구 > 개발자 도구로 접근하거나 Ctrl + Shift + I를 누르면 됩니다.
개발자 도구가 표시된 후 소스 탭을 클릭한 다음 콘텐츠 스크립트 탭을 클릭합니다. 이를 통해 여러 확장 프로그램의 실행 중인 콘텐츠 스크립트를 관찰하고 실행 흐름을 추적하기 위해 중단점을 설정할 수 있습니다.
삽입된 콘텐츠 스크립트
{% 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" });
include_globs
및 **exclude_globs
**를 사용하여 더 많은 URL을 포함하거나 제외하는 것도 가능합니다.
콘텐츠 스크립트 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
In public extensions the extension-id is accesible:
Although, if the manifest.json
parameter use_dynamic_url
is used, this id can be dynamic.
Being allowed to access these pages make these pages potentially vulnerable ClickJacking:
{% content-ref url="browext-clickjacking.md" %} browext-clickjacking.md {% endcontent-ref %}
{% hint style="success" %} Allowing these pages to be loaded only by the extension and not by random URLs could prevent CLickJacking attacks. {% endhint %}
externally_connectable
A per the docs, The "externally_connectable"
manifest property declares which extensions and web pages can connect to your extension via runtime.connect and runtime.sendMessage.
- If the
externally_connectable
key is not declared in your extension's manifest or it's declared as"ids": ["*"]
, all extensions can connect, but no web pages can connect. - If specific IDs are specified, like in
"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
, only those applications can connect. - If matches are specified, those web apps will be able to connect:
"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 %}
안전한 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을 신뢰한다면, 웹이 이 데이터를 수정할 수 있습니다(웹은 신뢰해서는 안 되거나 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()
함수는 동기적으로 실행되었습니다. sendResponse()
함수를 비동기적으로 실행하기 위해 onMessage
이벤트 핸들러를 수정할 때, return true;
를 반드시 포함해야 합니다.
여러 페이지가 onMessage
이벤트를 수신하도록 설정된 시나리오에서 중요한 고려 사항은 특정 이벤트에 대해 sendResponse()
를 실행하는 첫 번째 페이지만이 응답을 효과적으로 전달할 수 있다는 것입니다. 동일한 이벤트에 대한 이후 응답은 고려되지 않습니다.
새로운 확장 프로그램을 작성할 때는 콜백(callbacks) 대신 프로미스(promises)를 선호해야 합니다. 콜백의 사용에 관한 중요한 점은, sendResponse()
함수가 동기적인 컨텍스트 내에서 직접 실행되거나 이벤트 핸들러가 비동기 작업을 나타내기 위해 true
를 반환할 때만 유효하다는 것입니다. 핸들러 중 어느 것도 true
를 반환하지 않거나 sendResponse()
함수가 메모리에서 제거되면(가비지 수집), sendMessage()
함수와 연관된 콜백이 기본적으로 트리거됩니다.
브라우저에 확장 프로그램 로드하기
- 브라우저 확장 프로그램을 다운로드하고 압축을 해제합니다.
- **
chrome://extensions/
**로 이동하고개발자 모드
를 활성화합니다. 압축 해제된 확장 프로그램을 로드
버튼을 클릭합니다.
Firefox에서는 **about:debugging#/runtime/this-firefox
**로 이동하고 임시 추가 기능 로드
버튼을 클릭합니다.
스토어에서 소스 코드 가져오기
크롬 확장 프로그램의 소스 코드는 다양한 방법으로 얻을 수 있습니다. 각 옵션에 대한 자세한 설명과 지침은 아래에 나와 있습니다.
명령줄을 통해 ZIP 파일로 확장 프로그램 다운로드
크롬 확장 프로그램의 소스 코드는 명령줄을 사용하여 ZIP 파일로 다운로드할 수 있습니다. 이는 curl
을 사용하여 특정 URL에서 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 로컬 프로필 디렉토리에 액세스합니다.- 프로필 디렉토리 내의
Extensions/
하위 폴더로 이동합니다. - 이 폴더에는 일반적으로 읽기 가능한 형식의 소스 코드가 포함된 모든 설치된 확장 프로그램이 포함되어 있습니다.
확장 프로그램을 식별하기 위해 ID를 이름에 매핑할 수 있습니다:
about:extensions
페이지에서 개발자 모드를 활성화하여 각 확장 프로그램의 ID를 볼 수 있습니다.- 각 확장 프로그램의 폴더 내에서
manifest.json
파일에는 읽기 가능한name
필드가 포함되어 있어 확장 프로그램을 식별하는 데 도움이 됩니다.
파일 아카이버 또는 언패커 사용
Chrome 웹 스토어로 이동하여 확장 프로그램을 다운로드합니다. 파일은 .crx
확장자를 가집니다. 파일 확장자를 .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와 같은 기능).
- 진입점: 확장 프로그램이 사용자/외부 입력을 받는 위치를 표시합니다. 이는 확장 프로그램의 표면적을 이해하고 악의적으로 조작된 데이터를 확장 프로그램에 보낼 수 있는 잠재적인 지점을 찾는 데 유용합니다.
- 위험한 기능 및 진입점 스캐너는 생성된 경고에 대해 다음을 제공합니다:
- 경고를 일으킨 코드 스니펫 및 라인.
- 문제에 대한 설명.
- 경고를 일으킨 전체 소스 파일을 볼 수 있는 "파일 보기" 버튼.
- 경고를 일으킨 파일의 경로.
- 경고를 일으킨 파일의 전체 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 그룹에 가입하거나 텔레그램 그룹에 가입하거나 트위터 🐦 @carlospolopm을 팔로우하세요.
- 해킹 팁을 공유하려면 HackTricks 및 HackTricks Cloud github 저장소에 PR을 제출하세요.