Tarayıcı Uzantısı Pentesting Metodolojisi
Reading time: 26 minutes
tip
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking'i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
Temel Bilgiler
Tarayıcı uzantıları JavaScript ile yazılır ve tarayıcı tarafından arka planda yüklenir. Kendi [DOM]'u vardır ancak diğer sitelerin DOM'larıyla etkileşime girebilir. Bu, diğer sitelerin gizliliğini, bütünlüğünü ve erişilebilirliğini (CIA) tehlikeye atabileceği anlamına gelir.
Ana Bileşenler
Uzantı düzenleri görselleştirildiğinde en iyi görünür ve üç bileşenden oluşur. Her bir bileşeni derinlemesine inceleyelim.
 (1) (1).png)
Content Scripts
Her content script, tek bir web sayfasının DOM'una doğrudan erişime sahiptir ve bu nedenle potansiyel olarak kötü amaçlı girdiye maruz kalır. Ancak content script, extension core'a mesaj gönderme yeteneği dışında başka izinlere sahip değildir.
Extension Core
Extension core, uzantının çoğu ayrıcalık/erişimini içerir, ancak extension core yalnızca web içeriğiyle [XMLHttpRequest] ve content script'ler aracılığıyla etkileşime girebilir. Ayrıca extension core'un host makinesine doğrudan erişimi yoktur.
Native Binary
Uzantı, kullanıcının tam ayrıcalıklarıyla host makinesine erişebilen bir native binary'ye izin verir. Native binary, Flash ve diğer tarayıcı eklentileri tarafından kullanılan standart Netscape Plugin Application Programming Interface (NPAPI) üzerinden extension core ile etkileşir.
Boundaries
caution
Kullanıcının tam ayrıcalıklarını elde etmek için, bir saldırganın extension'ı content script'ten extension core'a ve extension core'dan native binary'ye kötü amaçlı girdi iletmeye ikna etmesi gerekir.
Uzantının her bileşeni birbirinden güçlü koruyucu sınırlarla ayrılmıştır. Her bileşen ayrı bir işletim sistemi sürecinde çalışır. Content script'ler ve extension core'lar, çoğu işletim sistemi servisinin erişemediği sandbox süreçlerde çalışır.
Ayrıca, content script'ler ilişkili oldukları web sayfalarından ayrı bir JavaScript heap'inde çalışarak ayrılır. Content script ile web sayfası aynı alttaki DOM'a erişime sahiptir, ancak ikisi asla JavaScript pointer'ları alışverişi yapmaz, bu da JavaScript işlevselliğinin leaking olmasını engeller.
manifest.json
A Chrome extension, .crx file extension olan bir ZIP klasörüdür. Uzantının çekirdeği, klasörün kökünde bulunan manifest.json
dosyasıdır; bu dosya düzeni, izinleri ve diğer yapılandırma seçeneklerini belirtir.
Örnek:
{
"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
Content scripts, kullanıcı eşleşen bir sayfaya gittiğinde yüklenir; bizim durumumuzda https://example.com/*
ifadesiyle eşleşen ve *://*/*/business*
regex'iyle eşleşmeyen herhangi bir sayfa. Bu script'ler sayfanın kendi script'leri gibi çalışır ve sayfanın Document Object Model (DOM) üzerinde her türlü erişime sahiptir.
"content_scripts": [
{
"js": [
"script.js"
],
"matches": [
"https://example.com/*",
"https://www.example.com/*"
],
"exclude_matches": ["*://*/*business*"],
}
],
Diğer URL'leri dahil etmek veya hariç tutmak için include_globs
ve exclude_globs
kullanmak da mümkündür.
Bu, the storage API kullanılarak uzantının depolamasından message
değerini almak için sayfaya bir explain button ekleyecek örnek bir content script'tir.
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)
})
.png)
Bu düğmeye tıklandığında content script, runtime.sendMessage() API kullanarak extension sayfalarına bir mesaj gönderir. Bunun nedeni content script'in API'lara doğrudan erişimindeki kısıtlamadır; storage
bu kısıtlamanın nadir istisnalarındandır. Bu istisnaların ötesindeki işlevsellik için, content script'lerin iletişim kurabildiği extension sayfalarına mesaj gönderilir.
warning
Tarayıcıya bağlı olarak, content script'in yetenekleri biraz değişiklik gösterebilir. Chromium tabanlı tarayıcılar için yetenekler listesi Chrome Developers documentation adresinde, Firefox içinse birincil kaynak MDN olarak hizmet vermektedir.
Ayrıca, content script'lerin background scripts ile iletişim kurma yeteneğine sahip olduğu ve böylece eylemler gerçekleştirebildikleri ve yanıtları iletebildikleri de kayda değerdir.
Chrome'da content script'leri görüntülemek ve hata ayıklamak için Chrome developer tools menüsüne Options > More tools > Developer tools yoluyla veya Ctrl + Shift + I tuşlarına basarak erişilebilir.
Developer tools görüntülendiğinde Source tab tıklanmalı, ardından Content Scripts sekmesi seçilmelidir. Bu, çeşitli extension'lardan çalışan content script'leri gözlemlemeye ve yürütme akışını izlemek için breakpoint'ler ayarlamaya olanak tanır.
Injected content scripts
tip
Content Scripts aren't mandatory — ayrıca script'leri dinamik olarak enjekte etmek ve web sayfalarına programatik olarak enjekte etmek de tabs.executeScript
ile mümkündür. Bu aslında daha ince kontroller sağlar.
Bir content script'in programatik olarak enjekte edilmesi için, script'lerin enjekte edileceği sayfa için extension'ın host permissions olması gerekir. Bu izinler, uzantının manifestinde bunları talep ederek ya da geçici olarak activeTab aracılığıyla güvence altına alınabilir.
Örnek activeTab tabanlı uzantı
{
"name": "My extension",
...
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_title": "Action Button"
}
}
- Tıklanınca bir JS dosyası enjekte et:
// 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"],
})
})
- Bir fonksiyon enjekte et tıklama üzerine:
//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,
})
})
Betik izinleriyle örnek
// 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" })
Daha fazla URL'i dahil etmek veya hariç tutmak için include_globs
ve exclude_globs
kullanılabilir.
İçerik Scriptleri run_at
The run_at
field controls JavaScript dosyalarının web sayfasına ne zaman enjekte edileceğini. Tercih edilen ve varsayılan değer "document_idle"
'dir.
Olası değerler:
document_idle
: Mümkün olduğundadocument_start
:css
içindeki dosyaların ardından, ancak başka herhangi bir DOM oluşturulmadan veya başka bir script çalıştırılmadan önce.document_end
: DOM tamamlandıktan hemen sonra, ancak resimler ve frame'ler gibi alt kaynaklar yüklenmeden önce.
manifest.json
ile
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.example.com/*"],
"run_at": "document_idle",
"js": ["contentScript.js"]
}
],
...
}
Üzerinden service-worker.js
chrome.scripting.registerContentScripts([
{
id: "test",
matches: ["https://*.example.com/*"],
runAt: "document_idle",
js: ["contentScript.js"],
},
])
background
İçerik script'leri tarafından gönderilen mesajlar, eklentinin bileşenlerini koordine etmede merkezi bir rol oynayan arka plan sayfası tarafından alınır. Özellikle, arka plan sayfası eklentinin yaşam süresi boyunca kalıcıdır ve doğrudan kullanıcı etkileşimi olmadan arka planda çalışır. Kendi Belge Nesne Modeli (DOM)'una sahiptir; bu, karmaşık etkileşimlere ve durum yönetimine olanak tanır.
Önemli Noktalar:
- Arka Plan Sayfası Rolü: Eklenti için sinir merkezi görevi görür; eklentinin farklı parçaları arasında iletişim ve koordinasyonu sağlar.
- Süreklilik: Kullanıcı tarafından görünmeyen, ancak eklentinin işlevselliği için ayrılmaz olan sürekli bir bileşendir.
- Otomatik Oluşturma: Açıkça tanımlanmadığında tarayıcı otomatik olarak bir arka plan sayfası oluşturur. Bu otomatik oluşturulan sayfa, manifestte belirtilen tüm background scripts'i içerecek ve eklentinin arka plan görevlerinin sorunsuz çalışmasını sağlayacaktır.
tip
Tarayıcının (açıkça belirtilmediğinde) otomatik olarak bir arka plan sayfası oluşturmasının sağladığı kolaylık, gerekli tüm background scripts'in entegre edilip çalışır durumda olmasını sağlayarak eklentinin kurulum sürecini sadeleştirir.
Örnek 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:
Options pages and other
Browser extensions can contain various kinds of pages:
- Action pages are displayed in a drop-down when the extension icon is clicked.
- Pages that the extension will load in a new tab.
- Option Pages: This page displays on top of the extension when clicked. In the previous manifest In my case I was able to access this page in
chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca
or clicking:
.png)
Note that these pages aren't persistent like background pages as they load dynamically content on necessity. Despite this, they share certain capabilities with the background page:
- Communication with Content Scripts: Similar to the background page, these pages can receive messages from content scripts, facilitating interaction within the extension.
- Access to Extension-Specific APIs: These pages enjoy comprehensive access to extension-specific APIs, subject to the permissions defined for the extension.
permissions
& host_permissions
permissions
and host_permissions
are entries from the manifest.json
that will indicate which permissions the browser extensions has (storage, location...) and in which web pages.
As browser extensions can be so privileged, a malicious one or one being compromised could allow the attacker different means to steal sensitive information and spy on the user.
Check how these settings work and how they could get abused in:
BrowExt - permissions & host_permissions
content_security_policy
A content security policy can be declared also inside the manifest.json
. If there is one defined, it could be vulnerable.
The default setting for browser extension pages is rather restrictive:
script-src 'self'; object-src 'self';
CSP ve olası bypass'lar hakkında daha fazla bilgi için bakınız:
Content Security Policy (CSP) Bypass
web_accessible_resources
Bir web sayfasının Browser Extension'ın bir sayfasına erişebilmesi için, örneğin bir .html
sayfası, bu sayfanın manifest.json
içindeki web_accessible_resources
alanında belirtilmiş olması gerekir.
Örneğin:
{
...
"web_accessible_resources": [
{
"resources": [ "images/*.png" ],
"matches": [ "https://example.com/*" ]
},
{
"resources": [ "fonts/*.woff" ],
"matches": [ "https://example.com/*" ]
}
],
...
}
Bu sayfalara şu şekilde bir URL ile erişilebilir:
chrome-extension://<extension-id>/message.html
Herkese açık extension'larda extension-id erişilebilir:
.png)
Ancak, manifest.json
parametresi use_dynamic_url
kullanılıyorsa, bu id dinamik olabilir.
tip
Burada bir sayfa belirtilmiş olsa bile, bu sayfa ClickJacking'e karşı korunuyor olabilir; bunun nedeni Content Security Policy'dir. Bu yüzden bir ClickJacking saldırısının mümkün olduğunu doğrulamadan önce onu (frame-ancestors bölümü) kontrol etmeniz gerekir.
Bu sayfalara erişim izni verilmesi, bu sayfaları potansiyel olarak ClickJacking'e açık hale getirebilir:
tip
Bu sayfaların sadece extension tarafından yüklenmesine izin verilip rastgele URL'lerden yüklenmesine izin verilmemesi ClickJacking saldırılarını engelleyebilir.
caution
web_accessible_resources
içindeki sayfaların ve extension'ın diğer sayfalarının background scripts ile iletişim kurabildiğini unutmayın. Bu nedenle bu sayfalardan biri XSS'e karşı savunmasızsa daha büyük bir zafiyete yol açabilir.
Ayrıca, web_accessible_resources
içinde belirtilen sayfaları iframe içinde açabileceğinizi, ancak yeni bir sekmeden extension ID bilinerek extension içindeki herhangi bir sayfaya erişilebileceğini unutmayın. Bu yüzden aynı parametreleri kötüye kullanan bir XSS bulunursa, sayfa web_accessible_resources
içinde yapılandırılmış olmasa bile istismar edilebilir.
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.
- Eğer extension'ınızın manifest'inde
externally_connectable
anahtarı tanımlı değilse veya"ids": ["*"]
olarak tanımlanmışsa, tüm extension'lar bağlanabilir, ancak hiçbir web sayfası bağlanamaz. - Eğer belirli ID'ler belirtilmişse, örneğin
"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
, sadece bu uygulamalar bağlanabilir. - Eğer matches belirtilmişse, bu web uygulamaları bağlanabilecektir:
"matches": [
"https://*.google.com/*",
"*://*.chromium.org/*",
- Eğer boş olarak belirtilmişse:
"externally_connectable": {}
, hiçbir app veya web bağlanamayacaktır.
The less extensions and URLs indicated here, the smaller the attack surface will be.
caution
Eğer externally_connectable
içinde XSS veya takeover'a açık bir web sayfası belirtilmişse, bir saldırgan mesajları doğrudan background script'e gönderebilecek, Content Script ve onun CSP'sini tamamen atlayarak.
Bu yüzden bu çok güçlü bir bypass.
Dahası, eğer client rouge bir extension kurarsa, vulnerable extension ile iletişim kurmasına izin verilmese bile, izin verilen bir web sayfasına XSS data enjekte edebilir veya hedeflenen bir domain üzerindeki istekleri manipüle etmek için WebRequest
veya DeclarativeNetRequest
API'lerini kötüye kullanarak bir sayfanın JavaScript file isteğini değiştirebilir. (Hedef sayfadaki CSP'nin bu saldırıları engelleyebileceğini unutmayın). Bu fikir bu writeup'tan geliyor.
Communication summary
Extension <--> WebApp
Content script ile web sayfası arasında iletişim kurmak için genellikle post messages kullanılır. Bu nedenle, web uygulamasında genellikle window.postMessage
fonksiyonuna çağrılar ve content script'te window.addEventListener
gibi listener'lar bulursunuz. Ancak dikkat edin, extension aynı zamanda web uygulamasıyla Post Message göndererek iletişim kurabilir (dolayısıyla web bunun gelmesini beklemelidir) veya sadece web'in yeni bir script yüklemesini sağlayabilir.
Inside the extension
Genellikle extension içinde mesaj göndermek için chrome.runtime.sendMessage
fonksiyonu kullanılır (genellikle background
script tarafından işlenir) ve bu mesajı almak ve işlemek için chrome.runtime.onMessage.addListener
çağrılarak bir listener tanımlanır.
Tek tek mesaj göndermek yerine kalıcı bir bağlantı için chrome.runtime.connect()
kullanmak da mümkündür; bunu aşağıdaki örnekte olduğu gibi mesaj göndermek ve almak için kullanabilirsiniz:
chrome.runtime.connect()
örnek
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
})
Ayrıca, bir arka plan betiğinden belirli bir sekmede bulunan bir içerik betiğine chrome.tabs.sendMessage
çağırarak mesaj göndermek de mümkündür; burada mesaja göndereceğiniz sekmenin ID'sini belirtmeniz gerekir.
İzin verilen externally_connectable
'den eklentiye
externally_connectable
yapılandırmasında izin verilen Web uygulamaları ve harici tarayıcı eklentileri istekleri şu şekilde gönderebilirler :
chrome.runtime.sendMessage(extensionId, ...
Gerekli olduğunda extension ID'den bahsedilecektir.
Native Messaging
Background scripts, sistem içindeki binaries ile iletişim kurabilir; bu iletişim doğru şekilde güvenli hale getirilmezse kritik güvenlik açıklarına (ör. RCEs) yatkın olabilir. More on this later.
chrome.runtime.sendNativeMessage(
"com.my_company.my_application",
{ text: "Hello" },
function (response) {
console.log("Received " + response)
}
)
Web ↔︎ Content Script İletişimi
The environments where content scripts operate and where the host pages exist are separated from one another, ensuring isolation. Despite this isolation, both have the ability to interact with the page's Document Object Model (DOM), a shared resource. For the host page to engage in communication with the content script, or indirectly with the extension through the content script, it is required to utilize the DOM that is accessible by both parties as the communication channel.
Post Messages
// 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
)
document.getElementById("theButton").addEventListener(
"click",
() => {
window.postMessage(
{ type: "FROM_PAGE", text: "Hello from the webpage!" },
"*"
)
},
false
)
Güvenli bir Post Message iletişimi, alınan mesajın doğruluğunu kontrol etmelidir; bu şu kontroller yapılarak yapılabilir:
event.isTrusted
: Bu yalnızca event bir kullanıcı eylemi tarafından tetiklendiğinde True olur- Content script yalnızca kullanıcı bir eylem gerçekleştirdiğinde mesaj bekliyor olabilir
- origin domain: yalnızca allowlist'teki domainlerden mesaj bekliyor olabilir.
- Bir regex kullanılıyorsa çok dikkatli olun
- Source:
received_message.source !== window
ifadesi, mesajın Content Script'in dinlediği aynı pencereden gelip gelmediğini kontrol etmek için kullanılabilir.
Önceki kontroller yapılsa bile zayıf olabilir, bu yüzden aşağıdaki sayfada potansiyel Post Message bypass'larını kontrol edin:
Iframe
Başka bir iletişim yolu Iframe URLs aracılığıyla olabilir; bir örneğini şu yerde bulabilirsiniz:
DOM
Bu tam olarak bir iletişim yolu olmasa da, web ve content script web DOM'a erişime sahip olacak. Yani, eğer content script buradan bazı bilgileri okuyor ve web DOM'a güveniyorsa, web bu veriyi değiştirebilir (çünkü web'e güvenilmemeli veya web XSS'e karşı savunmasız olabilir) ve Content Script'i ele geçirebilir.
Bir browser extension'ı ele geçirmek için DOM tabanlı XSS örneğini şurada da bulabilirsiniz:
Content Script ↔︎ Background Script Communication
A Content Script, bir one-time JSON-serializable mesaj göndermek için runtime.sendMessage() veya tabs.sendMessage() fonksiyonlarını kullanabilir.
Yanıtı işlemek için dönen Promise'i kullanın. Ancak, geriye dönük uyumluluk için yine de son argüman olarak bir callback geçebilirsiniz.
Bir content script'ten istek göndermek şöyle görünür:
;(async () => {
const response = await chrome.runtime.sendMessage({ greeting: "hello" })
// do something with response here, not outside the function
console.log(response)
})()
İsteği extension üzerinden (genellikle bir background script) göndermek. Seçilmiş sekmedeki content script'e mesaj gönderme örneği:
// 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)
})()
Alıcı tarafta, mesajı işlemek için runtime.onMessage event listener kurmanız gerekir. Bu, content script veya extension page'den aynı görünür.
// 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" })
})
In the example highlighted, sendResponse()
was executed in a synchronous fashion. To modify the onMessage
event handler for asynchronous execution of sendResponse()
, it's imperative to incorporate return true;
.
Vurgulanan örnekte, sendResponse()
eşzamanlı olarak çalıştırıldı. onMessage
event handler'ını sendResponse()
'ın eşzamansız çalışması için değiştirmek istiyorsanız return true;
eklemeniz zorunludur.
An important consideration is that in scenarios where multiple pages are set to receive onMessage
events, the first page to execute sendResponse()
for a specific event will be the only one able to deliver the response effectively. Any subsequent responses to the same event will not be taken into account.
Önemli bir nokta: Birden fazla sayfanın onMessage
eventi alacak şekilde ayarlandığı durumlarda, belirli bir event için sendResponse()
'ı çalıştıran ilk sayfa yanıtı iletebilen tek sayfa olacaktır. Aynı event için sonraki yanıtlar dikkate alınmayacaktır.
When crafting new extensions, the preference should be towards promises as opposed to callbacks. Concerning the use of callbacks, the sendResponse()
function is considered valid only if it's executed directly within the synchronous context, or if the event handler indicates an asynchronous operation by returning true
. Should none of the handlers return true
or if the sendResponse()
function is removed from memory (garbage-collected), the callback associated with the sendMessage()
function will be triggered by default.
Yeni uzantılar (extensions) oluştururken, callback'ler yerine promises tercih edilmelidir. Callback kullanımı açısından, sendResponse()
fonksiyonu yalnızca eşzamanlı bağlam içinde doğrudan çalıştırıldığında veya event handler'ı true
döndürerek eşzamansız bir işlem olduğunu belirttiğinde geçerlidir. Hiçbir handler true
döndürmezse veya sendResponse()
bellekten kaldırılırsa (garbage-collected), sendMessage()
ile ilişkilendirilmiş callback varsayılan olarak tetiklenecektir.
Native Messaging
Browser extensions also allow to communicate with binaries in the system via stdin. The application must install a json indicating so in a json like:
Tarayıcı uzantıları ayrıca binaries in the system via stdin ile iletişim kurmaya olanak verir. Uygulama, bunu belirten bir json dosyasını şu şekilde yüklemelidir:
{
"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/"]
}
Where the name
is the string passed to runtime.connectNative()
or runtime.sendNativeMessage()
to communicate with the application from the background scripts of the browser extension. The path
is the path to the binary, there is only 1 valid type
which is stdio (use stdin and stdout) and the allowed_origins
indicate the extensions that can access it (and can't have wildcard).
Chrome/Chromium will search for this json in some windows registry and some paths in macOS and Linux (more info in the docs).
tip
Tarayıcı uzantısının bu iletişimi kullanabilmesi için ayrıca nativeMessaing
iznini bildirmesi gerekir.
Aşağıda bir arka plan script'inin native uygulamaya mesaj gönderirken nasıl göründüğüne örnek verilmiştir:
chrome.runtime.sendNativeMessage(
"com.my_company.my_application",
{ text: "Hello" },
function (response) {
console.log("Received " + response)
}
)
In this blog post, native messages'ı istismar eden zafiyetli bir desen önerilmektedir:
- Browser extension'in content script için bir wildcard deseni vardır.
- Content script,
sendMessage
kullanarakpostMessage
mesajlarını background script'e iletir. - Background script,
sendNativeMessage
kullanarak mesajı native application'a iletir. - Native application mesajı tehlikeli şekilde işler; bu da kod yürütülmesine yol açabilir.
Ve içinde herhangi bir sayfadan RCE'ye, bir browser extension'ı istismar ederek nasıl ulaşılacağına dair bir örnek açıklanmaktadır.
Bellek/Kod/Panodaki Hassas Bilgiler
Eğer bir Browser Extension hassas bilgileri belleğinde saklıyorsa, bu bilgiler (özellikle Windows makinelerde) bellek dökümü alınarak elde edilebilir ve aranabilir.
Bu nedenle, Browser Extension'in belleği güvenli kabul edilmemeli ve kimlik bilgileri veya mnemonic ifadeler gibi hassas bilgiler saklanmamalıdır.
Elbette, kod içinde hassas bilgi bulundurmayın; çünkü kod herkese açık olacaktır.
Tarayıcıdan bellek dökümü almak için işlem belleğinin dökümünü alabilir veya browser extension ayarlarına gidip Inspect pop-up
'a tıklayabilirsiniz -> Memory
bölümünde -> Take a snaphost
ve CTRL+F
ile snapshot içinde hassas bilgileri arayabilirsiniz.
Ayrıca mnemonic anahtarlar veya parolalar gibi yüksek düzeyde hassas bilgiler panoya kopyalanmasına izin verilmemeli (veya en azından birkaç saniye sonra panodan silinmelidir), çünkü panoyu izleyen süreçler bunları ele geçirebilir.
Tarayıcıda Extension Yükleme
- Browser Extension'i indirin ve zip'ten çıkarın
chrome://extensions/
adresine gidin veDeveloper Mode
'u etkinleştirinLoad unpacked
butonuna tıklayın
Firefox'ta about:debugging#/runtime/this-firefox
adresine gidin ve Load Temporary Add-on
butonuna tıklayın.
Getting the source code from the store
Bir Chrome extension'un kaynak kodu çeşitli yollarla elde edilebilir. Aşağıda her seçenek için ayrıntılı açıklamalar ve talimatlar bulunmaktadır.
Komut Satırı ile Extension'u ZIP olarak İndirme
Bir Chrome extension'un kaynak kodu komut satırı kullanılarak ZIP dosyası olarak indirilebilir. Bu işlem, belirli bir URL'den ZIP dosyasını almak için curl
kullanmayı ve ardından ZIP içeriğini bir dizine çıkarmayı içerir. İşte adımlar:
"extension_id"
'yi extension'un gerçek ID'si ile değiştirin.- Aşağıdaki komutları çalıştırın:
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"
Use the CRX Viewer website
Use the CRX Viewer extension
Başka bir kullanışlı yöntem, açık kaynaklı bir proje olan Chrome Extension Source Viewer'ı kullanmaktır. Bu uzantıyı Chrome Web Store'dan yükleyebilirsiniz. Viewer'ın kaynak kodu GitHub repository'sinde mevcuttur: https://github.com/Rob--W/crxviewer
View source of locally installed extension
Yerel olarak yüklü Chrome uzantıları da incelenebilir. Yapılışı:
- Chrome yerel profil dizinine gitmek için
chrome://version/
adresini açın ve "Profile Path" alanını bulun. - Profil dizini içindeki
Extensions/
alt klasörüne gidin. - Bu klasör tüm yüklü uzantıları içerir; kaynak kodları genellikle okunabilir bir biçimdedir.
Uzantıları tanımlamak için ID'leri isimlerle eşleyebilirsiniz:
about:extensions
sayfasında Developer Mode'u etkinleştirerek her uzantının ID'sini görebilirsiniz.- Her uzantı klasörü içinde
manifest.json
dosyasında okunabilir birname
alanı bulunur; bu alan uzantıyı tanımlamanıza yardımcı olur.
Use a File Archiver or Unpacker
Chrome Web Store'a gidip uzantıyı indirin. Dosya .crx
uzantısına sahip olacaktır. Dosya uzantısını .crx
'den .zip
'e değiştirin. ZIP dosyasının içeriğini çıkarmak için herhangi bir dosya arşivleyici (WinRAR, 7-Zip, vb.) kullanın.
Use Developer Mode in Chrome
Chrome'u açın ve chrome://extensions/
adresine gidin. Sağ üstte "Developer mode"u etkinleştirin. "Load unpacked extension..." öğesine tıklayın. Uzantınızın bulunduğu dizine gidin. Bu işlem kaynak kodunu indirmez, ancak zaten indirilmiş veya geliştirilmiş bir uzantının kodunu görüntülemek ve değiştirmek için kullanışlıdır.
Chrome extension manifest dataset
Vulnerable browser extensions tespit etmeye çalışmak için thehttps://github.com/palant/chrome-extension-manifests-dataset kullanabilir ve manifest dosyalarında potansiyel olarak tehlikeli işaretleri kontrol edebilirsiniz. Örneğin, 25000'den fazla kullanıcısı olan, content_scripts
ve izin nativeMessaing
içeren uzantıları kontrol etmek için:
# 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')"
Post-exploitation: Forced extension load & persistence (Windows)
Chromium'u, her kullanıcı için olan Preferences dosyasını doğrudan düzenleyip geçerli HMACs oluşturarak arka kapı ile ele geçirme konusunda gizli bir teknik; bu, tarayıcının herhangi bir uyarı veya bayrak göstermeden rastgele unpacked extension'ı kabul edip etkinleştirmesine neden olur.
Forced Extension Load Preferences Mac Forgery Windows
Güvenlik Denetimi Kontrol Listesi
Tarayıcı uzantılarının (Browser Extensions) saldırı yüzeyi sınırlı olsa da, bazıları zafiyetler veya sertleştirme (hardening) iyileştirmeleri içerebilir. Aşağıdakiler en yaygın olanlardır:
-
Sınırlandırın mümkün olduğunca istenen
permissions
-
Sınırlandırın mümkün olduğunca
host_permissions
-
Güçlü bir
content_security_policy
kullanın -
Sınırlandırın mümkün olduğunca
externally_connectable
öğesini; eğer gerek yoksa ve mümkünse, varsayılan olarak bırakmayın,{}
belirtin - Eğer burada XSS veya takeover'a karşı savunmasız bir URL belirtilmişse, bir saldırgan background scripts'e doğrudan mesaj gönderebilecektir. Çok güçlü bir bypass.
-
Sınırlandırın mümkün olduğunca
web_accessible_resources
'ı, mümkünse boş bile bırakın. -
Eğer
web_accessible_resources
boş değilse, ClickJacking için kontrol edin - Eğer uzantıdan (extension) web sayfasına herhangi bir iletişim oluyorsa, iletişimde oluşabilecek XSS zafiyetlerini kontrol edin.
- Post Messages kullanılıyorsa, Post Message vulnerabilities için kontrol edin.
- Eğer Content Script DOM detaylarına erişiyorsa, web tarafından değiştirildiklerinde XSS oluşturmadıklarından emin olun
- Bu iletişim ayrıca Content Script -> Background script communication'ı da içeriyorsa özel vurgu yapın
- Eğer background script native messaging ile iletişim kuruyorsa, iletişimin güvenli ve sanitize edildiğini kontrol edin
- Gizli bilgiler saklanmamalıdır Browser Extension kodu içinde
- Gizli bilgiler saklanmamalıdır Browser Extension belleği (memory) içinde
- Gizli bilgiler saklanmamalıdır dosya sisteminde korunmasız şekilde
Browser Extension Risks
- Uygulama https://crxaminer.tech/ tarayıcı uzantısının (browser extension) istediği permissions gibi bazı verileri analiz ederek uzantının kullanım risk seviyesini belirler.
Tools
Tarnish
- Verilen bir Chrome webstore linkinden herhangi bir Chrome extension'ı çeker.
- manifest.json viewer: uzantının manifest'inin JSON-prettified halini gösterir.
- Fingerprint Analysis: web_accessible_resources tespiti ve otomatik olarak Chrome extension fingerprinting JavaScript üretimi.
- Potential Clickjacking Analysis: web_accessible_resources direktifi ayarlı extension HTML sayfalarını tespit eder. Amaçlarına bağlı olarak bu sayfalar clickjacking'e karşı potansiyel olarak savunmasız olabilir.
- Permission Warning(s) viewer: kullanıcı uzantıyı yüklemeye çalıştığında gösterilecek tüm Chrome izin uyarılarının listesini gösterir.
- Dangerous Function(s): innerHTML, chrome.tabs.executeScript gibi potansiyel olarak sömürülebilecek tehlikeli fonksiyonların konumlarını gösterir.
- Entry Point(s): uzantının kullanıcı/dış girdiyi nereden aldığı gösterilir. Bu, uzantının yüzey alanını anlamak ve kötü niyetli verilerin gönderilebileceği potansiyel noktaları bulmak için faydalıdır.
- Hem Dangerous Function(s) hem de Entry Point(s) tarayıcılarının ürettiği uyarılar için aşağıdakileri sağlar:
- Uyarıya sebep olan ilgili kod snippet'i ve satırı.
- Sorunun açıklaması.
- Tam kaynak dosyasını görmek için “View File” butonu.
- Uyarılan dosyanın yolu.
- Uyarılan dosyanın tam Chrome extension URI'sı.
- Dosyanın türü (Background Page script, Content Script, Browser Action vb.).
- Eğer zafiyetli satır bir JavaScript dosyasında ise, dahil edildiği tüm sayfaların yolları ve bu sayfaların türleri ile web_accessible_resource durumu.
- Content Security Policy (CSP) analyzer and bypass checker: Uzantınızın CSP'sindeki zayıflıkları işaretler ve CSP'yi atlatmaya yönelik potansiyel yolları (ör. beyaz listeye alınmış CDN'ler) gösterir.
- Known Vulnerable Libraries: Bilinen zafiyetli JavaScript kütüphanelerinin kullanımını kontrol etmek için Retire.js kullanır.
- Uzantıyı indirme ve formatlanmış versiyonlarını indirme.
- Orijinal uzantıyı indirme.
- Beautified edilmiş versiyonunu indirme (otomatik prettified HTML ve JavaScript).
- Tarama sonuçlarının otomatik önbelleğe alınması; ilk tarama zaman alır, ancak uzantı güncellenmediyse ikinci tarama neredeyse anında sonuç verir.
- Tarnish tarafından oluşturulan bir uzantı raporuna kolayca bağlantı verebilen linklenebilir rapor URL'leri.
Neto
Project Neto, Firefox ve Chrome gibi bilinen tarayıcılar için tarayıcı plugin'leri ve uzantılarının gizli özelliklerini analiz edip ortaya çıkarmak üzere tasarlanmış bir Python 3 paketidir. Paketlenmiş dosyaların zip'ini açma işlemini otomatikleştirir ve bu özellikleri manifest.json
, localization klasörleri veya Javascript ve HTML kaynak dosyaları gibi ilgili kaynaklardan çıkarır.
References
- Thanks to @naivenom for the help with this methodology
- 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
tip
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking'i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.