.. | ||
browext-clickjacking.md | ||
browext-permissions-and-host_permissions.md | ||
browext-xss-example.md | ||
README.md |
Browser Extension Pentesting Methodology
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the ð¬ Discord group or the telegram group or follow us on Twitter ðŠ @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
åºæ¬æ å ±
ãã©ãŠã¶æ¡åŒµæ©èœã¯JavaScriptã§æžããããã©ãŠã¶ã«ãã£ãŠããã¯ã°ã©ãŠã³ãã§èªã¿èŸŒãŸããŸããç¬èªã®DOMãæã£ãŠããŸãããä»ã®ãµã€ãã®DOMãšçžäºäœçšããããšãã§ããŸããããã¯ãä»ã®ãµã€ãã®æ©å¯æ§ãå®å šæ§ãããã³å¯çšæ§ïŒCIAïŒãå±éºã«ãããå¯èœæ§ãããããšãæå³ããŸãã
äž»ãªã³ã³ããŒãã³ã
æ¡åŒµæ©èœã®ã¬ã€ã¢ãŠãã¯èŠèŠåããããšæãè¯ãèŠãã3ã€ã®ã³ã³ããŒãã³ãã§æ§æãããŠããŸããããããã®ã³ã³ããŒãã³ãã詳ããèŠãŠãããŸãããã
ã³ã³ãã³ãã¹ã¯ãªãã
åã³ã³ãã³ãã¹ã¯ãªããã¯åäžã®ãŠã§ãããŒãžã®DOMã«çŽæ¥ã¢ã¯ã»ã¹ã§ããæœåšçã«æªæã®ããå ¥åã«ãããããŸããããããã³ã³ãã³ãã¹ã¯ãªããã¯æ¡åŒµæ©èœã®ã³ã¢ã«ã¡ãã»ãŒãžãéä¿¡ããèœå以å€ã®æš©éãæã£ãŠããŸããã
æ¡åŒµæ©èœã³ã¢
æ¡åŒµæ©èœã³ã¢ã¯ãã»ãšãã©ã®æ¡åŒµæ©èœã®ç¹æš©/ã¢ã¯ã»ã¹ãå«ãã§ããŸãããæ¡åŒµæ©èœã³ã¢ã¯XMLHttpRequestããã³ã³ã³ãã³ãã¹ã¯ãªãããä»ããŠã®ã¿ãŠã§ãã³ã³ãã³ããšçžäºäœçšã§ããŸãããŸããæ¡åŒµæ©èœã³ã¢ã¯ãã¹ããã·ã³ã«çŽæ¥ã¢ã¯ã»ã¹ããããšã¯ã§ããŸããã
ãã€ãã£ããã€ããª
æ¡åŒµæ©èœã¯ããŠãŒã¶ãŒã®å®å šãªæš©éã§ãã¹ããã·ã³ã«ã¢ã¯ã»ã¹ã§ãããã€ãã£ããã€ããªãèš±å¯ããŸãããã€ãã£ããã€ããªã¯ãFlashãä»ã®ãã©ãŠã¶ãã©ã°ã€ã³ã§äœ¿çšãããæšæºã®Netscapeãã©ã°ã€ã³APIïŒNPAPIïŒãä»ããŠæ¡åŒµæ©èœã³ã¢ãšçžäºäœçšããŸãã
å¢ç
{% hint style="danger" %} ãŠãŒã¶ãŒã®å®å šãªæš©éãååŸããã«ã¯ãæ»æè ã¯æ¡åŒµæ©èœã«ã³ã³ãã³ãã¹ã¯ãªããããæ¡åŒµæ©èœã®ã³ã¢ãžã®æªæã®ããå ¥åãæž¡ãããã«èª¬åŸããæ¡åŒµæ©èœã®ã³ã¢ãããã€ãã£ããã€ããªãžã®æªæã®ããå ¥åãæž¡ãå¿ èŠããããŸãã {% endhint %}
æ¡åŒµæ©èœã®åã³ã³ããŒãã³ãã¯ã匷åãªä¿è·å¢çã«ãã£ãŠäºãã«åé¢ãããŠããŸããåã³ã³ããŒãã³ãã¯å¥ã ã®ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ããã»ã¹ã§å®è¡ãããŸããã³ã³ãã³ãã¹ã¯ãªãããšæ¡åŒµæ©èœã³ã¢ã¯ãã»ãšãã©ã®ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ãµãŒãã¹ã«å©çšã§ããªããµã³ãããã¯ã¹ããã»ã¹ã§å®è¡ãããŸãã
ããã«ãã³ã³ãã³ãã¹ã¯ãªããã¯å¥ã®JavaScriptããŒãã§å®è¡ãããããšã«ãã£ãŠãé¢é£ãããŠã§ãããŒãžããåé¢ãããŠããŸããã³ã³ãã³ãã¹ã¯ãªãããšãŠã§ãããŒãžã¯åãåºç€ãšãªãDOMã«ã¢ã¯ã»ã¹ã§ããŸããã2ã€ã¯JavaScriptãã€ã³ã¿ã亀æããããšã¯æ±ºããŠãªããJavaScriptæ©èœã®æŒæŽ©ãé²ããŸãã
manifest.json
Chromeæ¡åŒµæ©èœã¯ãåã«.crxãã¡ã€ã«æ¡åŒµåãæã€ZIPãã©ã«ããŒã§ããæ¡åŒµæ©èœã®ã³ã¢ã¯ããã©ã«ããŒã®ã«ãŒãã«ãã**manifest.json
**ãã¡ã€ã«ã§ãã¬ã€ã¢ãŠããæš©éãããã³ãã®ä»ã®èšå®ãªãã·ã§ã³ãæå®ããŸãã
Example:
{
"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*
æ£èŠè¡šçŸã«äžèŽããªãããŒãžã§ãããããã¯ããŒãžèªèº«ã®ã¹ã¯ãªããã®ããã«å®è¡ãããããŒãžã®Document Object Model (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" %}
ãã©ãŠã¶ã«ãã£ãŠãã³ã³ãã³ãã¹ã¯ãªããã®æ©èœã¯è¥å¹²ç°ãªãå ŽåããããŸããChromiumããŒã¹ã®ãã©ãŠã¶ã®å Žåãæ©èœãªã¹ãã¯Chrome Developers documentationã§å
¥æå¯èœã§ãFirefoxã®å Žåã¯MDNãäž»ãªæ
å ±æºãšãªããŸãã
ãŸããã³ã³ãã³ãã¹ã¯ãªããã¯ããã¯ã°ã©ãŠã³ãã¹ã¯ãªãããšéä¿¡ããèœåããããããã«ããã¢ã¯ã·ã§ã³ãå®è¡ããå¿çãè¿ãããšãã§ããŸãã
{% endhint %}
Chromeã§ã³ã³ãã³ãã¹ã¯ãªããã衚瀺ããã³ãããã°ããã«ã¯ãOptions > More tools > Developer toolsããChromeéçºè ããŒã«ã¡ãã¥ãŒã«ã¢ã¯ã»ã¹ããããCtrl + Shift + IãæŒããŸãã
éçºè ããŒã«ã衚瀺ãããããSource tabãã¯ãªãã¯ãã次ã«Content Scriptsã¿ããã¯ãªãã¯ããŸããããã«ãããããŸããŸãªæ¡åŒµæ©èœããå®è¡äžã®ã³ã³ãã³ãã¹ã¯ãªããã芳å¯ããå®è¡ãããŒã远跡ããããã®ãã¬ãŒã¯ãã€ã³ããèšå®ã§ããŸãã
æ³šå ¥ãããã³ã³ãã³ãã¹ã¯ãªãã
{% 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,
});
});
ã¹ã¯ãªããæš©éã®äŸ
// 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"]
}
],
...
}
Via service-worker.js
chrome.scripting.registerContentScripts([{
id : "test",
matches : [ "https://*.example.com/*" ],
runAt : "document_idle",
js : [ "contentScript.js" ],
}]);
background
ã³ã³ãã³ãã¹ã¯ãªããã«ãã£ãŠéä¿¡ãããã¡ãã»ãŒãžã¯ãããã¯ã°ã©ãŠã³ãããŒãžã«ãã£ãŠåä¿¡ãããæ¡åŒµæ©èœã®ã³ã³ããŒãã³ãã調æŽããäžå¿çãªåœ¹å²ãæãããŸããç¹ã«ãããã¯ã°ã©ãŠã³ãããŒãžã¯æ¡åŒµæ©èœã®ã©ã€ãã¿ã€ã ãéããŠæç¶ãããŠãŒã¶ãŒã®çŽæ¥çãªæäœãªãã«éãã«åäœããŸããç¬èªã®ããã¥ã¡ã³ããªããžã§ã¯ãã¢ãã«ïŒDOMïŒãæã¡ãè€éãªçžäºäœçšãšç¶æ 管çãå¯èœã«ããŸãã
éèŠãªãã€ã³ã:
- ããã¯ã°ã©ãŠã³ãããŒãžã®åœ¹å²: æ¡åŒµæ©èœã®ç¥çµäžæ¢ãšããŠæ©èœããæ¡åŒµæ©èœã®ããŸããŸãªéšåéã®éä¿¡ãšèª¿æŽã確ä¿ããŸãã
- æç¶æ§: ãŠãŒã¶ãŒã«ã¯èŠããªãããæ¡åŒµæ©èœã®æ©èœã«äžå¯æ¬ ãªåžžã«ååšãããšã³ãã£ãã£ã§ãã
- èªåçæ: æ瀺çã«å®çŸ©ãããŠããªãå Žåããã©ãŠã¶ã¯èªåçã«ããã¯ã°ã©ãŠã³ãããŒãžãäœæããŸãããã®èªåçæãããããŒãžã«ã¯ãæ¡åŒµæ©èœã®ãããã§ã¹ãã«æå®ããããã¹ãŠã®ããã¯ã°ã©ãŠã³ãã¹ã¯ãªãããå«ãŸããæ¡åŒµæ©èœã®ããã¯ã°ã©ãŠã³ãã¿ã¹ã¯ã®ã·ãŒã ã¬ã¹ãªæäœã確ä¿ããŸãã
{% hint style="success" %} æ瀺çã«å®£èšãããŠããªãå Žåã«ãã©ãŠã¶ãããã¯ã°ã©ãŠã³ãããŒãžãèªåçæããããšã«ãã£ãŠæäŸããã䟿å©ãã¯ããã¹ãŠã®å¿ èŠãªããã¯ã°ã©ãŠã³ãã¹ã¯ãªãããçµ±åãããæ©èœããããšãä¿èšŒããæ¡åŒµæ©èœã®ã»ããã¢ããããã»ã¹ãç°¡çŽ åããŸãã {% endhint %}
Example background script:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) =>
{
if (request == "explain")
{
chrome.tabs.create({ url: "https://example.net/explanation" });
}
})
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
ã®ãšã³ããªã§ããã©ãŠã¶æ¡åŒµæ©èœãã©ã®æš©éïŒã¹ãã¬ãŒãžãäœçœ®æ
å ±ãªã©ïŒãæã£ãŠããããã©ã®ãŠã§ãããŒãžã§ãããã瀺ããŸãã
ãã©ãŠã¶æ¡åŒµæ©èœã¯éåžžã«ç¹æš©çã§ãããããæªæã®ãããã®ã䟵害ããããã®ã¯ãæ»æè ã«æ©å¯æ å ±ãçãã ãããŠãŒã¶ãŒãç£èŠããããã®ããŸããŸãªæ段ãæäŸããå¯èœæ§ããããŸãã
ãããã®èšå®ãã©ã®ããã«æ©èœããã©ã®ããã«æªçšãããå¯èœæ§ããããã確èªããŠãã ããïŒ
{% 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
å ¬å ±æ¡åŒµæ©èœã§ã¯ãextension-idãã¢ã¯ã»ã¹å¯èœã§ãïŒ
ãã ããmanifest.json
ãã©ã¡ãŒã¿**use_dynamic_url
ã䜿çšãããŠããå Žåããã®idã¯åç**ã«ãªãå¯èœæ§ããããŸãã
{% hint style="success" %} ããã«ããŒãžãèšèŒãããŠããŠããContent Security Policyã®ãããã§ClickJackingã«å¯ŸããŠä¿è·ãããŠããå¯èœæ§ãããããšã«æ³šæããŠãã ããããããã£ãŠãClickJackingæ»æãå¯èœãã©ããã確èªããåã«ãããããã§ãã¯ããå¿ èŠããããŸãïŒframe-ancestorsã»ã¯ã·ã§ã³ïŒã {% endhint %}
ãããã®ããŒãžã«ã¢ã¯ã»ã¹ã§ããããšã¯ããããã®ããŒãžãæœåšçã«è匱ãªClickJackingã§ããããšãæå³ããŸãïŒ
{% content-ref url="browext-clickjacking.md" %} browext-clickjacking.md {% endcontent-ref %}
{% hint style="success" %} ãããã®ããŒãžãæ¡åŒµæ©èœã«ãã£ãŠã®ã¿èªã¿èŸŒãŸããã©ã³ãã ãªURLããã¯èªã¿èŸŒãŸããªãããã«ããããšã§ãClickJackingæ»æãé²ãããšãã§ããŸãã {% endhint %}
{% hint style="danger" %}
web_accessible_resources
ããã®ããŒãžãæ¡åŒµæ©èœã®ä»ã®ããŒãžãããã¯ã°ã©ãŠã³ãã¹ã¯ãªããã«é£çµ¡ããããšãã§ããããšã«æ³šæããŠãã ããããããã£ãŠããããã®ããŒãžã®ãããããXSSã«å¯ŸããŠè匱ã§ããå Žåããã倧ããªè匱æ§ãåŒãèµ·ããå¯èœæ§ããããŸãã
ããã«ã**web_accessible_resources
ã«ç€ºãããããŒãžã¯iframeå
ã§ã®ã¿éãããšãã§ããŸãããæ°ããã¿ãããã¯æ¡åŒµæ©èœIDãç¥ã£ãŠããã°æ¡åŒµæ©èœå
ã®ä»»æã®ããŒãžã«ã¢ã¯ã»ã¹ããããšãå¯èœã§ãããããã£ãŠãåããã©ã¡ãŒã¿ãæªçšããXSSãèŠã€ãã£ãå ŽåãããŒãžãweb_accessible_resources
**ã«èšå®ãããŠããªããŠãæªçšãããå¯èœæ§ããããŸãã
{% endhint %}
externally_connectable
docsã«ãããšã"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 %}
ã³ãã¥ãã±ãŒã·ã§ã³ã®æŠèŠ
æ¡åŒµæ©èœ <--> ãŠã§ãã¢ããª
ã³ã³ãã³ãã¹ã¯ãªãããšãŠã§ãããŒãžéã§éä¿¡ããããã«ãéåžžã¯ãã¹ãã¡ãã»ãŒãžã䜿çšãããŸãããããã£ãŠããŠã§ãã¢ããªã±ãŒã·ã§ã³ã§ã¯éåžž window.postMessage
é¢æ°ãžã®åŒã³åºããèŠãããã³ã³ãã³ãã¹ã¯ãªããã§ã¯ window.addEventListener
ã®ãããªãªã¹ããŒãèŠãããŸãããã ããæ¡åŒµæ©èœã¯ ãã¹ãã¡ãã»ãŒãžãéä¿¡ããŠãŠã§ãã¢ããªã±ãŒã·ã§ã³ãšéä¿¡ ããããšãã§ãïŒãããã£ãŠãŠã§ãã¯ãããæåŸ
ããå¿
èŠããããŸãïŒãåã«ãŠã§ãã«æ°ããã¹ã¯ãªãããèªã¿èŸŒãŸããããšãã§ããŸãã
æ¡åŒµæ©èœå
éåžžãæ¡åŒµæ©èœå
ã§ã¡ãã»ãŒãžãéä¿¡ããããã« chrome.runtime.sendMessage
é¢æ°ã䜿çšããïŒé垞㯠background
ã¹ã¯ãªããã«ãã£ãŠåŠçãããŸãïŒããããåä¿¡ããŠåŠçããããã«ãªã¹ããŒã chrome.runtime.onMessage.addListener
ãåŒã³åºããŠå®£èšãããŸãã
chrome.runtime.connect()
ã䜿çšããŠãåäžã®ã¡ãã»ãŒãžãéä¿¡ãã代ããã«æç¶çãªæ¥ç¶ãæã€ããšãå¯èœã§ã次ã®äŸã®ããã« ã¡ãã»ãŒãžãéä¿¡ ã åä¿¡ ããããã«äœ¿çšã§ããŸãã
chrome.runtime.connect()
ã®äŸ
```javascript
var port = chrome.runtime.connect();
// Listen for messages from the web page window.addEventListener("message", (event) => { // Only accept messages from the same window if (event.source !== window) { return; }
// Check if the message type is "FROM_PAGE" if (event.data.type && (event.data.type === "FROM_PAGE")) { console.log("Content script received: " + event.data.text); // Forward the message to the background script port.postMessage({ type: 'FROM_PAGE', text: event.data.text }); } }, false);
// Listen for messages from the background script port.onMessage.addListener(function(msg) { console.log("Content script received message from background script:", msg); // Handle the response message from the background script });
</details>
ããã¯ã°ã©ãŠã³ãã¹ã¯ãªããããç¹å®ã®ã¿ãã«ããã³ã³ãã³ãã¹ã¯ãªããã«ã¡ãã»ãŒãžãéä¿¡ããããšãå¯èœã§ã**`chrome.tabs.sendMessage`**ãåŒã³åºãéã«ã¡ãã»ãŒãžãéä¿¡ãã**ã¿ãã®ID**ãæå®ããå¿
èŠããããŸãã
### èš±å¯ããã `externally_connectable` ããæ¡åŒµæ©èœãž
`externally_connectable` èšå®ã§èš±å¯ããã**Webã¢ããªãšå€éšãã©ãŠã¶æ¡åŒµæ©èœ**ã¯ã次ã®ããã«ãªã¯ãšã¹ããéä¿¡ã§ããŸãïŒ
```javascript
chrome.runtime.sendMessage(extensionId, ...
å¿ èŠãªå Žåã¯æ¡åŒµIDãèšåããå¿ èŠããããŸãã
ãã€ãã£ãã¡ãã»ãŒãžã³ã°
ããã¯ã°ã©ãŠã³ãã¹ã¯ãªãããã·ã¹ãã å ã®ãã€ããªãšéä¿¡ããããšãå¯èœã§ããããã®éä¿¡ãé©åã«ä¿è·ãããŠããªãå ŽåãRCEãªã©ã®é倧ãªè匱æ§ã«ãããããå¯èœæ§ããããŸããåŸã§è©³ãã説æããŸãã
chrome.runtime.sendNativeMessage(
'com.my_company.my_application',
{text: 'Hello'},
function (response) {
console.log('Received ' + response);
}
);
Web âïž ã³ã³ãã³ãã¹ã¯ãªããéä¿¡
ã³ã³ãã³ãã¹ã¯ãªãããåäœããç°å¢ãšãã¹ãããŒãžãååšããç°å¢ã¯åé¢ãããŠãããéé¢ã確ä¿ãããŠããŸãããã®éé¢ã«ãããããããäž¡è ã¯ããŒãžã®ããã¥ã¡ã³ããªããžã§ã¯ãã¢ãã« (DOM)ãã€ãŸãå ±æãªãœãŒã¹ãšçžäºäœçšããèœåãæã£ãŠããŸãããã¹ãããŒãžãã³ã³ãã³ãã¹ã¯ãªãããšéä¿¡ããããããŸãã¯ã³ã³ãã³ãã¹ã¯ãªãããä»ããŠæ¡åŒµæ©èœãšéæ¥çã«éä¿¡ããããã«ã¯ãäž¡è ãã¢ã¯ã»ã¹å¯èœãªDOMãéä¿¡ãã£ãã«ãšããŠå©çšããå¿ èŠããããŸãã
ãã¹ãã¡ãã»ãŒãž
{% code title="content-script.js" %}
// This is like "chrome.runtime.sendMessage" but to maintain the connection
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);
// Forward the message to the background script
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 domain: ã¡ãã»ãŒãžãæåŸ ããå Žåã¯ãèš±å¯ãªã¹ãã®ãã¡ã€ã³ã®ã¿ãèš±å¯ãããããããŸããã
- æ£èŠè¡šçŸã䜿çšãããå Žåã¯ãéåžžã«æ³šæãå¿ èŠã§ãã
- Source:
received_message.source !== window
ã䜿çšããŠãã¡ãã»ãŒãžãã³ã³ãã³ãã¹ã¯ãªããããªã¹ãã³ã°ããŠããåããŠã£ã³ããŠããã®ãã®ã§ãããã確èªã§ããŸãã
åè¿°ã®ãã§ãã¯ã¯ãå®æœãããŠããŠãè匱ã§ããå¯èœæ§ãããããã次ã®ããŒãžã§æœåšçãªPost Messageãã€ãã¹ã確èªããŠãã ããïŒ
{% content-ref url="../postmessage-vulnerabilities/" %} postmessage-vulnerabilities {% endcontent-ref %}
Iframe
å¥ã®éä¿¡æ¹æ³ãšããŠIframe URLsãéããŠè¡ãããšãèããããŸããäŸã¯ä»¥äžã«ãããŸãïŒ
{% 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 %}
ã³ã³ãã³ãã¹ã¯ãªãã âïž ããã¯ã°ã©ãŠã³ãã¹ã¯ãªããéä¿¡
ã³ã³ãã³ãã¹ã¯ãªããã¯ã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()
é¢æ°ã«é¢é£ä»ããããã³ãŒã«ããã¯ãããã©ã«ãã§ããªã¬ãŒãããŸãã
ãã€ãã£ãã¡ãã»ãŒãžã³ã°
ãã©ãŠã¶æ¡åŒµæ©èœã¯ãã·ã¹ãã å ã®ãã€ããªãš stdin çµç±ã§éä¿¡ããããšãå¯èœã§ããã¢ããªã±ãŒã·ã§ã³ã¯ã次ã®ãã㪠json ã瀺ã json ãã€ã³ã¹ããŒã«ããå¿ èŠããããŸã:
{
"name": "com.my_company.my_application",
"description": "My Application",
"path": "C:\\Program Files\\My Application\\chrome_native_messaging_host.exe",
"type": "stdio",
"allowed_origins": ["chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"]
}
name
㯠runtime.connectNative()
ãŸã㯠runtime.sendNativeMessage()
ã«æž¡ãããæååã§ããã©ãŠã¶æ¡åŒµã®ããã¯ã°ã©ãŠã³ãã¹ã¯ãªããããã¢ããªã±ãŒã·ã§ã³ãšéä¿¡ããŸãã path
ã¯ãã€ããªãžã®ãã¹ã§ã1ã€ã®æå¹ãª type
㯠stdioïŒstdin ãš stdout ã䜿çšïŒã§ããã allowed_origins
ã¯ã¢ã¯ã»ã¹ã§ããæ¡åŒµæ©èœã瀺ããŸãïŒã¯ã€ã«ãã«ãŒãã¯äœ¿çšã§ããŸããïŒã
Chrome/Chromium ã¯ããã® JSON ãããã€ãã® Windows ã¬ãžã¹ããªã macOS ããã³ Linux ã®ããã€ãã®ãã¹ã§æ€çŽ¢ããŸãïŒè©³çŽ°ã¯ docs ãåç §ïŒã
{% hint style="success" %}
ãã©ãŠã¶æ¡åŒµã¯ããã®éä¿¡ã䜿çšããããã« nativeMessaing
æš©éã宣èšããå¿
èŠããããŸãã
{% endhint %}
ããã¯ããã€ãã£ãã¢ããªã±ãŒã·ã§ã³ã«ã¡ãã»ãŒãžãéä¿¡ããããã¯ã°ã©ãŠã³ãã¹ã¯ãªããã³ãŒãã®äŸã§ãïŒ
chrome.runtime.sendNativeMessage(
'com.my_company.my_application',
{text: 'Hello'},
function (response) {
console.log('Received ' + response);
}
);
In ãã®ããã°æçš¿ã§ã¯ããã€ãã£ãã¡ãã»ãŒãžãæªçšããè匱ãªãã¿ãŒã³ãææ¡ãããŠããŸãïŒ
- ãã©ãŠã¶æ¡åŒµæ©èœã¯ã³ã³ãã³ãã¹ã¯ãªããã®ããã®ã¯ã€ã«ãã«ãŒããã¿ãŒã³ãæã£ãŠããŸãã
- ã³ã³ãã³ãã¹ã¯ãªããã¯
sendMessage
ã䜿çšããŠããã¯ã°ã©ãŠã³ãã¹ã¯ãªããã«postMessage
ã¡ãã»ãŒãžãæž¡ããŸãã - ããã¯ã°ã©ãŠã³ãã¹ã¯ãªããã¯
sendNativeMessage
ã䜿çšããŠãã€ãã£ãã¢ããªã±ãŒã·ã§ã³ã«ã¡ãã»ãŒãžãæž¡ããŸãã - ãã€ãã£ãã¢ããªã±ãŒã·ã§ã³ã¯ã¡ãã»ãŒãžãå±éºã«æ±ããã³ãŒãå®è¡ã«ã€ãªãããŸãã
ãããŠããã®äžã§ãã©ãŠã¶æ¡åŒµæ©èœãæªçšããŠä»»æã®ããŒãžããRCEã«ç§»è¡ããäŸã説æãããŠããŸãã
ã¡ã¢ãª/ã³ãŒã/ã¯ãªããããŒãå ã®æ©å¯æ å ±
ãã©ãŠã¶æ¡åŒµæ©èœãã¡ã¢ãªå ã«æ©å¯æ å ±ãä¿åããŠããå Žåãããã¯ãã³ããããå¯èœæ§ãããïŒç¹ã«Windowsãã·ã³ã§ïŒããã®æ å ±ãæ€çŽ¢ãããå¯èœæ§ããããŸãã
ãããã£ãŠããã©ãŠã¶æ¡åŒµæ©èœã®ã¡ã¢ãªã¯å®å šãšã¯èŠãªãããã¹ãã§ã¯ãªããè³æ Œæ å ±ãããŒã¢ããã¯ãã¬ãŒãºãªã©ã®æ©å¯æ å ±ã¯ä¿åãããã¹ãã§ã¯ãããŸããã
ãã¡ãããã³ãŒãå ã«æ©å¯æ å ±ã眮ããªãã§ãã ãããããã¯å ¬éãããããšã«ãªããŸãã
ãã©ãŠã¶ããã¡ã¢ãªããã³ãããã«ã¯ãããã»ã¹ã¡ã¢ãªããã³ããããããã©ãŠã¶æ¡åŒµæ©èœã®èšå®ã«è¡ãã**Inspect pop-up
**ãã¯ãªã㯠-> **Memory
**ã»ã¯ã·ã§ã³ -> **Take a snapshot
ãéžæããCTRL+F
**ã§ã¹ãããã·ã§ããå
ã®æ©å¯æ
å ±ãæ€çŽ¢ããŸãã
ããã«ãããŒã¢ããã¯ããŒããã¹ã¯ãŒãã®ãããªéåžžã«æ©å¯æ§ã®é«ãæ å ±ã¯ãã¯ãªããããŒãã«ã³ããŒãããããšãèš±å¯ãã¹ãã§ã¯ãããŸããïŒãŸãã¯å°ãªããšãæ°ç§ä»¥å ã«ã¯ãªããããŒãããåé€ããã¹ãã§ãïŒãªããªããã¯ãªããããŒããç£èŠããŠããããã»ã¹ãããããååŸã§ããããã§ãã
ãã©ãŠã¶ã«æ¡åŒµæ©èœãèªã¿èŸŒã
- ãã©ãŠã¶æ¡åŒµæ©èœãããŠã³ããŒããã解åããŸãã
chrome://extensions/
ã«ç§»åããDeveloper Mode
ãæå¹ã«ããŸãã- **
Load unpacked
**ãã¿ã³ãã¯ãªãã¯ããŸãã
Firefoxã§ã¯ã**about:debugging#/runtime/this-firefox
ã«ç§»åããLoad Temporary Add-on
**ãã¿ã³ãã¯ãªãã¯ããŸãã
ã¹ãã¢ãããœãŒã¹ã³ãŒããååŸãã
Chromeæ¡åŒµæ©èœã®ãœãŒã¹ã³ãŒãã¯ãããŸããŸãªæ¹æ³ã§ååŸã§ããŸãã以äžã¯åãªãã·ã§ã³ã®è©³çŽ°ãªèª¬æãšæé ã§ãã
ã³ãã³ãã©ã€ã³ãä»ããŠZIPãšããŠæ¡åŒµæ©èœãããŠã³ããŒã
Chromeæ¡åŒµæ©èœã®ãœãŒã¹ã³ãŒãã¯ãã³ãã³ãã©ã€ã³ã䜿çšããŠZIPãã¡ã€ã«ãšããŠããŠã³ããŒãã§ããŸããããã¯ãç¹å®ã®URLããZIPãã¡ã€ã«ãååŸããããã«curl
ã䜿çšãããã®åŸ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ãã¥ãŒã¯ãŒãŠã§ããµã€ãã䜿çšãã
CRXãã¥ãŒã¯ãŒæ¡åŒµæ©èœã䜿çšãã
ããäžã€ã®äŸ¿å©ãªæ¹æ³ã¯ããªãŒãã³ãœãŒã¹ãããžã§ã¯ãã§ããChromeæ¡åŒµæ©èœãœãŒã¹ãã¥ãŒã¯ãŒã䜿çšããããšã§ããããã¯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/
ã«ç§»åããŸããå³äžã§ãéçºè
ã¢ãŒãããæå¹ã«ããŸããã解åãããæ¡åŒµæ©èœãèªã¿èŸŒã...ããã¯ãªãã¯ããŸããæ¡åŒµæ©èœã®ãã£ã¬ã¯ããªã«ç§»åããŸããããã¯ãœãŒã¹ã³ãŒããããŠã³ããŒããããã®ã§ã¯ãããŸãããããã§ã«ããŠã³ããŒããŸãã¯éçºãããæ¡åŒµæ©èœã®ã³ãŒãã衚瀺ããã³å€æŽããã®ã«äŸ¿å©ã§ãã
Chromeæ¡åŒµæ©èœãããã§ã¹ãããŒã¿ã»ãã
è匱ãªãã©ãŠã¶æ¡åŒµæ©èœãèŠã€ããããã«ãhttps://github.com/palant/chrome-extension-manifests-datasetã䜿çšãããããã§ã¹ããã¡ã€ã«ã«æœåšçãªè匱æ§ã®å
åããªãã確èªã§ããŸããäŸãã°ã25000人以äžã®ãŠãŒã¶ãŒãæã€æ¡åŒµæ©èœãcontent_scripts
ãããã³æš©énativeMessaging
ã確èªããããã«ïŒ
{% code overflow="wrap" %}
# Query example from https://spaceraccoon.dev/universal-code-execution-browser-extensions/
node query.js -f "metadata.user_count > 250000" "manifest.content_scripts?.length > 0 && manifest.permissions?.includes('nativeMessaging')"
{% endcode %}
ã»ãã¥ãªãã£ç£æ»ãã§ãã¯ãªã¹ã
ãã©ãŠã¶æ¡åŒµæ©èœã¯æ»æé¢ãéãããŠããŸããããã®äžã«ã¯è匱æ§ã匷åã®å¯èœæ§ãå«ãŸããŠããå ŽåããããŸãã以äžã¯æãäžè¬çãªãã®ã§ãïŒ
- èŠæ±ããã
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 -> ããã¯ã°ã©ãŠã³ãã¹ã¯ãªããéä¿¡ã«ãé¢äžããŠããå Žåã¯ç¹ã«åŒ·èª¿ãã
- ããã¯ã°ã©ãŠã³ãã¹ã¯ãªããããã€ãã£ãã¡ãã»ãŒãžã³ã°ãä»ããŠéä¿¡ããŠããå Žåãéä¿¡ãå®å šã§ãµãã¿ã€ãºãããŠããããšã確èªãã
- æ©å¯æ å ±ã¯ãã©ãŠã¶æ¡åŒµæ©èœã®ã³ãŒãå ã«ä¿åãã¹ãã§ã¯ãªã
- æ©å¯æ å ±ã¯ãã©ãŠã¶æ¡åŒµæ©èœã®ã¡ã¢ãªå ã«ä¿åãã¹ãã§ã¯ãªã
- æ©å¯æ å ±ã¯****ãã¡ã€ã«ã·ã¹ãã ã«ç¡é²åã«ä¿åãã¹ãã§ã¯ãªã
ããŒã«
Tarnish
- æäŸãããChromeãŠã§ãã¹ãã¢ãªã³ã¯ããä»»æã®Chromeæ¡åŒµæ©èœãååŸããŸãã
- manifest.json ãã¥ãŒã¯ãŒ: æ¡åŒµæ©èœã®ãããã§ã¹ãã®JSONæŽåœ¢çã衚瀺ããŸãã
- ãã£ã³ã¬ãŒããªã³ã¿ãŒåæ: 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ïŒã
- ã¹ãã£ã³çµæã®èªåãã£ãã·ã¥ãæ¡åŒµæ©èœã®ã¹ãã£ã³ãåããŠå®è¡ããéã«ã¯ããªãã®æéãããããŸããããããæ¡åŒµæ©èœãæŽæ°ãããŠããªãéãã2åç®ã¯çµæããã£ãã·ã¥ãããŠããããã»ãŒç¬æã«å®äºããŸãã
- ãªã³ã¯å¯èœãªã¬ããŒã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
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the ð¬ Discord group or the telegram group or follow us on Twitter ðŠ @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.