.. | ||
browext-clickjacking.md | ||
browext-permissions-and-host_permissions.md | ||
browext-xss-example.md | ||
README.md |
Μεθοδολογία Ελέγχου Ασφάλειας Επέκτασης Προγράμματος Περιήγησης
Μάθετε το χάκινγκ του AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!
Άλλοι τρόποι υποστήριξης του HackTricks:
- Αν θέλετε να δείτε την εταιρεία σας διαφημισμένη στο HackTricks ή να κατεβάσετε το HackTricks σε μορφή PDF ελέγξτε τα ΣΧΕΔΙΑ ΣΥΝΔΡΟΜΗΣ!
- Αποκτήστε το επίσημο PEASS & HackTricks swag
- Ανακαλύψτε την Οικογένεια PEASS, τη συλλογή μας από αποκλειστικά NFTs
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @carlospolopm.
- Μοιραστείτε τα χάκινγκ κόλπα σας υποβάλλοντας PRs στα HackTricks και HackTricks Cloud αποθετήρια του github.
Βασικές Πληροφορίες
Οι επεκτάσεις προγράμματος περιήγησης γράφονται σε JavaScript και φορτώνονται από το πρόγραμμα περιήγησης στο παρασκήνιο. Διαθέτουν το DOM τους αλλά μπορούν να αλληλεπιδρούν με τα DOM άλλων ιστοσελίδων. Αυτό σημαίνει ότι μπορεί να διακινδυνεύσει την εμπιστευτικότητα, την ακεραιότητα και τη διαθεσιμότητα άλλων ιστοσελίδων (CIA).
Κύρια Στοιχεία
Οι διατάξεις των επεκτάσεων φαίνονται καλύτερες όταν οπτικοποιούνται και αποτελούνται από τρία στοιχεία. Ας εξετάσουμε κάθε στοιχείο αναλυτικά.
Σενάρια Περιεχομένου
Κάθε σενάριο περιεχομένου έχει άμεση πρόσβαση στο DOM μιας μόνο ιστοσελίδας και είναι έτσι εκτεθειμένο σε ενδεχόμενη κακόβουλη είσοδο. Ωστόσο, το σενάριο περιεχομένου δεν περιλαμβάνει άλλες άδειες εκτός από τη δυνατότητα αποστολής μηνυμάτων στον πυρήνα της επέκτασης.
Πυρήνας Επέκτασης
Ο πυρήνας της επέκτασης περιέχει τις περισσότερες από τις προνομιακές/πρόσβασης της επέκτασης, αλλά ο πυρήνας της επέκτασης μπορεί να αλληλεπιδρά με το περιεχόμενο του ιστού μέσω του XMLHttpRequest και των σεναρίων περιεχομένου. Επίσης, ο πυρήνας της επέκτασης δεν έχει άμεση πρόσβαση στην κύρια μονάδα.
Φυσικός Δυαδικός
Η επέκταση επιτρέπει ένα φυσικό δυαδικό που μπορεί να έχει πρόσβαση στην κύρια μονάδα του χρήστη με πλήρεις προνομιακές δικαιώματα του χρήστη. Το φυσικό δυαδικό αλληλεπιδρά με τον πυρήνα της επέκτασης μέσω της τυπικής διεπαφής προγραμματισμού εφαρμογών Netscape (NPAPI) που χρησιμοποιείται από το Flash και άλλα πρόσθετα προγράμματα περιήγησης.
Όρια
{% hint style="danger" %} Για να αποκτήσει κάποιος τις πλήρεις προνομιακές δικαιώματα του χρήστη, ένας επιτιθέμενος πρέπει να πείσει την επέκταση να περάσει κακόβουλη είσοδο από το σενάριο περιεχομένου στον πυρήνα της επέκτασης και από τον πυρήνα της επέκτασης στο φυσικό δυαδικό. {% endhint %}
Κάθε στοιχείο της επέκτασης διαχωρίζεται μεταξύ του από ισχυρά προστατευτικά όρια. Κάθε στοιχείο λειτουργεί σε ένα ξεχωριστό διαδικτυακό διεργασία. Τα σενάρια περιεχομένου και οι πυρήνες επέκτασης λειτουργούν σε διεργασίες αμμοθόλογησης που δεν είναι διαθέσιμες στις περισσότερες υπηρεσίες λειτουργικού συστήματος.
Επιπλέον, τα σενάρια περιεχομένου διαχωρίζονται από τις σχετικές ιστοσελίδες τους με τον τρόπο ότι λειτουργούν σε ξεχωριστή στοίβα JavaScript. Το σενάριο περιεχομένου και η ιστοσελίδα έχουν πρόσβαση στο ίδιο υποκείμενο DOM, αλλά τα δύο ποτέ δεν ανταλλάσσουν δείκτες JavaScript, αποτρέποντας τη διαρροή λειτουργικότητας JavaScript.
manifest.json
Μια επέκταση Chrome είναι απλά ένας φάκελος ZIP με την κατάληξη αρχείου .crx. Ο πυρήνας της επέκτασης είναι το αρχείο 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
Τα content scripts φορτώνονται κάθε φορά που ο χρήστης πλοηγείται σε μια αντιστοιχη σελίδα, στην περίπτωσή μας οποιαδήποτε σελίδα που ταιριάζει με την έκφραση https://example.com/*
και δεν ταιριάζει με το *://*/*/business*
regex. Εκτελούνται όπως τα δικά scripts της σελίδας και έχουν αυθαίρετη πρόσβαση στο Document Object Model (DOM).
"content_scripts": [
{
"js": [
"script.js"
],
"matches": [
"https://example.com/*",
"https://www.example.com/*"
],
"exclude_matches": ["*://*/*business*"],
}
],
Για να συμπεριλάβετε ή να αποκλείσετε περισσότερα URLs, είναι επίσης δυνατόν να χρησιμοποιήσετε τα include_globs
και exclude_globs
.
Αυτό είναι ένα παράδειγμα script περιεχομένου που θα προσθέσει ένα κουμπί εξήγησης στη σελίδα όταν η αποθήκευση 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);
});
Ένα μήνυμα στέλνεται στις σελίδες της επέκτασης από τον content script όταν αυτό το κουμπί πατιέται, μέσω της χρήσης του API runtime.sendMessage(). Αυτό οφείλεται στον περιορισμό του content script στην άμεση πρόσβαση σε APIs, με το storage
να αποτελεί μία από τις λίγες εξαιρέσεις. Για λειτουργίες πέραν αυτών των εξαιρέσεων, τα μηνύματα στέλνονται στις σελίδες της επέκτασης με τις οποίες τα content scripts μπορούν να επικοινωνήσουν.
{% hint style="warning" %}
Ανάλογα με τον περιηγητή, οι δυνατότητες του content script μπορεί να διαφέρουν ελαφρώς. Για τους περιηγητές που βασίζονται στο Chromium, η λίστα των δυνατοτήτων είναι διαθέσιμη στην τεκμηρίωση των Προγραμματιστών του Chrome, ενώ για τον Firefox, η MDN λειτουργεί ως η κύρια πηγή.
Είναι επίσης σημαντικό να σημειωθεί ότι τα content scripts έχουν τη δυνατότητα να επικοινωνούν με τα background scripts, επιτρέποντάς τους να εκτελούν ενέργειες και να μεταδίδουν απαντήσεις πίσω.
{% endhint %}
Για την προβολή και αποσφαλμάτωση των content scripts στο Chrome, το μενού εργαλείων προγραμματιστή του Chrome μπορεί να προσπελαστεί από τις Επιλογές > Περισσότερα εργαλεία > Εργαλεία προγραμματιστή ή πατώντας Ctrl + Shift + I.
Μόλις εμφανιστούν τα εργαλεία προγραμματιστή, πρέπει να γίνει κλικ στην Καρτέλα Πηγής, ακολουθούμενο από την Καρτέλα Content Scripts. Αυτό επιτρέπει την παρατήρηση των εκτελούμενων content scripts από διάφορες επεκτάσεις και την ρύθμιση σημείων διακοπής για την παρακολούθηση της ροής εκτέλεσης.
Ενσωματωμένα content scripts
{% hint style="success" %}
Σημειώστε ότι τα Content Scripts δεν είναι υποχρεωτικά καθώς είναι επίσης δυνατή η δυναμική ενσωμάτωση σεναρίων και η προγραμματική ενσωμάτωσή τους σε ιστοσελίδες μέσω του tabs.executeScript
. Αυτό προσφέρει περισσότερο λεπτομερή έλεγχο.
{% endhint %}
Για την προγραμματική ενσωμάτωση ενός content script, η επέκταση πρέπει να έχει δικαιώματα κατοχής για τη σελίδα στην οποία τα σενάρια θα ενσωματωθοϋν. Αυτά τα δικαιώματα μπορούν να ασφαλιστούν είτε με τον αιτούντας τα μέσα στον κατάλογο της επέκτασης είτε προσωρινά μέσω του 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 ή την εκτέλεση οποιουδήποτε άλλου script.document_end
: Αμέσως μετά την ολοκλήρωση του DOM, αλλά πριν φορτωθούν υπο-πόροι όπως εικόνες και frames.
Μέσω 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" ],
}]);
Υπόβαθρο
Τα μηνύματα που στέλνονται από τα content scripts λαμβάνονται από τη σελίδα υποβάθρου, η οποία διαδραματίζει ένα κεντρικό ρόλο στον συντονισμό των στοιχείων της επέκτασης. Ειδικότερα, η σελίδα υποβάθρου διατηρείται καθ' όλη τη διάρκεια ζωής της επέκτασης, λειτουργώντας διακριτικά χωρίς άμεση αλληλεπίδραση με τον χρήστη. Διαθέτει το δικό της Document Object Model (DOM), επιτρέποντας πολύπλοκες αλληλεπιδράσεις και διαχείριση καταστάσεων.
Κύρια Σημεία:
- Ρόλος Σελίδας Υποβάθρου: Δρα ως το κέντρο νεύρων για την επέκταση, εξασφαλίζοντας την επικοινωνία και τον συντονισμό μεταξύ των διαφόρων τμημάτων της επέκτασης.
- Μόνιμοτητα: Είναι μια παρουσία που υπάρχει συνεχώς, αόρατη για τον χρήστη αλλά ουσιώδης για τη λειτουργικότητα της επέκτασης.
- Αυτόματη Δημιουργία: Αν δεν οριστεί ρητά, ο περιηγητής θα δημιουργήσει αυτόματα μια σελίδα υποβάθρου. Αυτή η αυτόματη δημιουργημένη σελίδα θα περιλαμβάνει όλα τα σενάρια υποβάθρου που καθορίζονται στο αρχείο προδιαγραφών της επέκτασης, εξασφαλίζοντας την άνετη λειτουργία των εργασιών υποβάθρου της επέκτασης.
chrome.runtime.onMessage.addListener((request, sender, sendResponse) =>
{
if (request == "explain")
{
chrome.tabs.create({ url: "https://example.net/explanation" });
}
})
Χρησιμοποιεί το runtime.onMessage API για να ακούει μηνύματα. Όταν λάβει ένα μήνυμα "explain"
, χρησιμοποιεί το tabs API για να ανοίξει μια σελίδα σε ένα νέο tab.
Για να εντοπίσετε σφάλματα στο φόντο script μπορείτε να πάτε στις λεπτομέρειες της επέκτασης και να επιθεωρήσετε τον υπηρεσιακό εργαζόμενο, αυτό θα ανοίξει τα εργαλεία προγραμματιστή με το φόντο script:
Σελίδες επιλογών και άλλες
Οι επεκτάσεις προγραμμάτων περιήγησης μπορούν να περιέχουν διάφορα είδη σελίδων:
- Σελίδες δράσης εμφανίζονται σε ένα αναπτυσσόμενο μενού όταν γίνει κλικ στο εικονίδιο της επέκτασης.
- Σελίδες που η επέκταση θα φορτώσει σε ένα νέο tab.
- Σελίδες Επιλογών: Αυτή η σελίδα εμφανίζεται επάνω από την επέκταση όταν γίνει κλικ. Στο προηγούμενο μανιφέστο στην περίπτωσή μου μπόρεσα να έχω πρόσβαση σε αυτή τη σελίδα στο
chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca
ή κάνοντας κλικ:
Σημειώστε ότι αυτές οι σελίδες δεν είναι μόνιμες όπως οι φόντο σελίδες καθώς φορτώνουν δυναμικά περιεχόμενο όταν απαιτείται. Παρόλα αυτά, μοιράζονται ορισμένες ικανότητες με τη φόντο σελίδα:
- Επικοινωνία με Σενάρια Περιεχομένου: Παρόμοια με τη φόντο σελίδα, αυτές οι σελίδες μπορούν να λαμβάνουν μηνύματα από σενάρια περιεχομένου, διευκολύνοντας την αλληλεπίδραση εντός της επέκτασης.
- Πρόσβαση σε Ειδικές Εφαρμογές της Επέκτασης: Αυτές οι σελίδες απολαμβάνουν πλήρη πρόσβαση σε ειδικές εφαρμογές της επέκτασης, υπόκειται στις άδειες που έχουν οριστεί για την επέκταση.
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
, αυτή η σελίδα πρέπει να αναφέρεται στο πεδίο web_accessible_resources
του manifest.json
.
Για παράδειγμα:
{
...
"web_accessible_resources": [
{
"resources": [ "images/*.png" ],
"matches": [ "https://example.com/*" ]
},
{
"resources": [ "fonts/*.woff" ],
"matches": [ "https://example.com/*" ]
}
],
...
}
Αυτές οι σελίδες είναι προσβάσιμες στο URL όπως:
chrome-extension://<extension-id>/message.html
Στις δημόσιες επεκτάσεις το αναγνωριστικό της επέκτασης είναι προσβάσιμο:
Ωστόσο, εάν χρησιμοποιηθεί το παράμετρος use_dynamic_url
στο αρχείο manifest.json
, το αναγνωριστικό μπορεί να είναι δυναμικό.
{% hint style="success" %} Σημειώστε ότι ακόμα κι αν μια σελίδα αναφέρεται εδώ, ενδέχεται να είναι προστατευμένη από ClickJacking χάρη στη Πολιτική Ασφαλείας Περιεχομένου. Έτσι, πρέπει επίσης να το ελέγξετε (ενότητα frame-ancestors) πριν επιβεβαιώσετε ότι είναι δυνατή μια επίθεση ClickJacking. {% 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
μέσα σε iframes, αλλά από ένα νέο tab είναι δυνατή η πρόσβαση σε οποιαδήποτε σελίδα στην επέκταση γνωρίζοντας το αναγνωριστικό της επέκτασης. Επομένως, εάν βρεθεί ένα XSS εκμεταλλευόμενο τις ίδιες παραμέτρους, μπορεί να εκμεταλλευτεί ακόμα κι αν η σελίδα δεν έχει διαμορφωθεί στο web_accessible_resources
.
{% endhint %}
externally_connectable
Σύμφωνα με τα έγγραφα, η ιδιότητα μανιφέστου "externally_connectable"
δηλώνει ποιες επεκτάσεις και ιστοσελίδες μπορούν να συνδεθούν στην επέκτασή σας μέσω runtime.connect και runtime.sendMessage.
- Εάν το κλειδί
externally_connectable
δεν έχει δηλωθεί στο μανιφέστο της επέκτασής σας ή έχει δηλωθεί ως"ids": ["*"]
, όλες οι επεκτάσεις μπορούν να συνδεθούν, αλλά καμία ιστοσελίδα δεν μπορεί να συνδεθεί. - Εάν δηλωθούν συγκεκριμένα αναγνωριστικά, όπως στο
"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
, μόνο αυτές οι εφαρμογές μπορούν να συνδεθούν. - Εάν δηλωθούν αντιστοιχίσεις, αυτές οι ιστοσελίδες θα μπορούν να συνδεθούν:
"matches": [
"https://*.google.com/*",
"*://*.chromium.org/*",
- Εάν ορίζεται ως κενό:
"externally_connectable": {}
, κανένα app ή ιστοσελίδα δεν θα μπορεί να συνδεθεί.
Όσο λιγότερες επεκτάσεις και URLs υποδεικνύονται εδώ, τόσο μικρότερη θα είναι η επιφάνεια επίθεσης.
{% hint style="danger" %}
Εάν μια ιστοσελίδα ευάλωτη σε XSS ή εξανάλωση υποδεικνύεται στο externally_connectable
, ένας επιτιθέμενος θα μπορεί να στείλει μηνύματα απευθείας στο φόντο σενάριο, παρακάμπτοντας εντελώς το Content Script και το CSP του.
Επομένως, αυτή είναι μια πολύ ισχυρή παράκαμψη.
Επιπλέον, εάν ο πελάτης εγκαταστήσει μια ψεύτικη επέκταση, ακόμα κι αν δεν του επιτρέπεται να επικοινωνήσει με την ευάλωτη επέκταση, θα μπορούσε να ενθέσει δεδομένα XSS σε μια επιτρεπόμενη ιστοσελίδα ή να καταχραστεί τα APIs WebRequest
ή DeclarativeNetRequest
για να παραπλανήσει αιτήσεις σε έναν στοχευμένο τομέα, τροποποιώντας μια αίτηση σελίδας για ένα αρχείο JavaScript. (Σημειώστε ότι το CSP στη στοχευμένη σελίδα θα μπορούσε να αποτρέψει αυτές τις επιθέσεις). Αυτή η ιδέα προέρχεται από αυτήν την ανάλυση.
{% endhint %}
Σύνοψη επικοινωνίας
Επέκταση <--> WebApp
Για να επικοινωνήσουν μεταξύ τους το Content Script και η ιστοσελίδα συνήθως χρησιμοποιούν μηνύματα. Συνεπώς, στην web εφαρμογή συνήθως θα βρείτε κλήσεις στη συνάρτηση window.postMessage
και στο Content Script ακροατές όπως window.addEventListener
. Ωστόσο, η επέκταση θα μπορούσε επίσης να επικοινωνήσει με την web εφαρμογή στέλνοντας ένα Post Message (και επομένως η web θα πρέπει να το περιμένει) ή απλά να κάνει τη web να φορτώσει ένα νέο script.
Μέσα στην επέκταση
Συνήθως χρησιμοποιείται η συνάρτηση chrome.runtime.sendMessage
για να στείλει ένα μήνυμα μέσα στην επέκταση (συνήθως χειρίζεται από το σενάριο background
) και για να το λάβει και να το χειριστεί δηλώνεται ένας ακροατής καλώντας chrome.runtime.onMessage.addListener
.
Είναι επίσης δυνατό να χρησιμοποιηθεί το chrome.runtime.connect()
για να έχει μια μόνιμη σύνδεση αντί να στέλνει μεμονωμένα μηνύματα, είναι δυνατό να το χρησιμοποιήσετε για να στείλετε και λάβετε μηνύματα όπως στο παρακάτω παράδειγμα:
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
});
Είναι επίσης δυνατή η αποστολή μηνυμάτων από ένα σενάριο φόντου προς ένα σενάριο περιεχομένου που βρίσκεται σε ένα συγκεκριμένο καρτέλα καλώντας το chrome.tabs.sendMessage
όπου θα πρέπει να υποδείξετε το ID της καρτέλας στην οποία θα σταλεί το μήνυμα.
Από το επιτρεπόμενο externally_connectable
προς την επέκταση
Οι web εφαρμογές και εξωτερικές επεκτάσεις περιηγητή που επιτρέπονται στη διαμόρφωση externally_connectable
μπορούν να στείλουν αιτήματα χρησιμοποιώντας:
chrome.runtime.sendMessage(extensionId, ...
Όπου χρειάζεται να αναφερθεί το ID της επέκτασης.
Επικοινωνία Ιστού ↔︎ Σεναρίου Περιεχομένου
Τα περιβάλλοντα όπου λειτουργούν τα σενάρια περιεχομένου και όπου υπάρχουν οι σελίδες φιλοξενίας είναι χωρισμένα μεταξύ τους, εξασφαλίζοντας απομόνωση. Παρά την απομόνωση αυτή, και τα δύο έχουν τη δυνατότητα να αλληλεπιδρούν με το Μοντέλο Αντικειμένου του Εγγράφου (DOM) της σελίδας, ένα κοινό πόρο. Για τη σελίδα φιλοξενίας να εμπλακεί στην επικοινωνία με το σενάριο περιεχομένου, ή έμμεσα με την επέκταση μέσω του σεναρίου περιεχομένου, απαιτείται η χρήση του DOM που είναι προσβάσιμος από τις δύο πλευρές ως κανάλι επικοινωνίας.
Αποστολή Μηνυμάτων
{% code title="σενάριο-περιεχομένου.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 μόνο εάν το συμβάν προκλήθηκε από μια ενέργεια χρήστη- Το περιεχόμενο script μπορεί να περιμένει ένα μήνυμα μόνο εάν ο χρήστης εκτελεί κάποια ενέργεια
- Προέλευση domain: μπορεί να περιμένει ένα μήνυμα μόνο από λίστα επιτρεπόμενων domains.
- Εάν χρησιμοποιείται ένα regex, να είστε πολύ προσεκτικοί
- Πηγή: Το
received_message.source !== window
μπορεί να χρησιμοποιηθεί για να ελεγχθεί αν το μήνυμα ήταν από το ίδιο παράθυρο όπου το Content Script ακούει.
Οι προηγούμενοι έλεγχοι, ακόμη και αν πραγματοποιηθούν, μπορεί να είναι ευάλωτοι, οπότε ελέγξτε στην ακόλουθη σελίδα τις πιθανές παρακάμψεις 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
Αυτό δεν είναι "ακριβώς" ένας τρόπος επικοινωνίας, αλλά το web και το περιεχόμενο script θα έχουν πρόσβαση στο web DOM. Έτσι, εάν το περιεχόμενο script διαβάζει κάποιες πληροφορίες από αυτό, εμπιστευόμενο το web DOM, το web θα μπορούσε να τροποποιήσει αυτά τα δεδομένα (επειδή το web δεν πρέπει να εμπιστεύεται, ή επειδή το web είναι ευάλωτο στο XSS) και να θέσει σε κίνδυνο το Content Script.
Μπορείτε επίσης να βρείτε ένα παράδειγμα ενός DOM based XSS για την απειλή μιας επέκτασης προγράμματος περιήγησης στο:
{% content-ref url="browext-xss-example.md" %} browext-xss-example.md {% endcontent-ref %}
Επικοινωνία Περιεχομένου Script ↔︎ Σεναρίου Φόντου
Ένα Περιεχόμενο Script μπορεί να χρησιμοποιήσει τις λειτουργίες runtime.sendMessage() ή tabs.sendMessage() για να στείλει ένα μήνυμα μιας φοράς που μπορεί να σειριοποιηθεί σε JSON.
Για να χειριστείτε τη απάντηση, χρησιμοποιήστε την επιστρεφόμενη Promise. Ωστόσο, για συμβατότητα προς τα πίσω, μπορείτε ακόμη να περάσετε ένα κλήση πίσω ως το τελευταίο όρισμα.
Η αποστολή ενός αιτήματος από ένα περιεχόμενο script φαίνεται έτσι:
(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 ακροατή γεγονότων για να χειριστείτε το μήνυμα. Αυτό φαίνεται το ίδιο είτε από ένα script περιεχομένου είτε από τη σελίδα επέκτασης.
// From https://stackoverflow.com/questions/70406787/javascript-send-message-from-content-js-to-background-js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting === "hello")
sendResponse({farewell: "goodbye"});
}
);
Στο παραδειγμα που τονίζεται, η sendResponse()
εκτελέστηκε με σύγχρονο τρόπο. Για να τροποποιηθεί ο χειριστής συμβάντος onMessage
για ασύγχρονη εκτέλεση της sendResponse()
, είναι απαραίτητο να ενσωματωθεί το return true;
.
Ένα σημαντικό σημείο προς σκέψη είναι ότι σε περιπτώσεις όπου πολλές σελίδες έχουν οριστεί να λαμβάνουν συμβάντα onMessage
, η πρώτη σελίδα που εκτελεί τη sendResponse()
για ένα συγκεκριμένο συμβάν θα είναι η μόνη που θα μπορεί να παραδώσει αποτελεσματικά την απόκριση. Οποιεσδήποτε μετέπειτα απαντήσεις στο ίδιο συμβάν δεν θα ληφθούν υπόψη.
Κατά τη δημιουργία νέων επεκτάσεων, η προτίμηση θα πρέπει να είναι προς τις υποσχέσεις αντί για τις επαναλήψεις κλήσεων. Όσον αφορά τη χρήση των επαναλήψεων κλήσεων, η λειτουργία sendResponse()
θεωρείται έγκυρη μόνο εάν εκτελείται απευθείας εντός του συγχρόνου πλαισίου, ή εάν ο χειριστής συμβάντος υποδεικνύει μια ασύγχρονη λειτουργία επιστρέφοντας true
. Εάν κανένας από τους χειριστές δεν επιστρέψει true
ή εάν η λειτουργία sendResponse()
αφαιρεθεί από τη μνήμη (συλλεκτηρισμός σκουπιδιών), η επανάκληση που σχετίζεται με τη λειτουργία sendMessage()
θα ενεργοποιηθεί από προεπιλογή.
Ευαίσθητες Πληροφορίες στη Μνήμη/Κώδικα/Πρόχειρο
Εάν μια Επέκταση Προγράμματος Περιήγησης αποθηκεύει ευαίσθητες πληροφορίες μέσα στη μνήμη της, αυτές μπορεί να διαρρεύσουν (ειδικά σε μηχανές Windows) και να αναζητηθούν για αυτές τις πληροφορίες.
Συνεπώς, η μνήμη της Επέκτασης Προγράμματος Περιήγησης δεν πρέπει να θεωρηθεί ασφαλής και ευαίσθητες πληροφορίες όπως διαπιστευτήρια ή μνημονικές φράσεις δεν πρέπει να αποθηκεύονται.
Φυσικά, μην τοποθετείτε ευαίσθητες πληροφορίες στον κώδικα, καθώς θα γίνουν δημόσιες.
Για να διαρρεύσετε τη μνήμη από τον περιηγητή μπορείτε να διαρρεύσετε τη μνήμη της διεργασίας ή να πηγαίνετε στις ρυθμίσεις της επέκτασης του περιηγητή κάνοντας κλικ στο Επιθεώρηση αναδυόμενου παραθύρου
-> Στην ενότητα Μνήμη
-> Κάντε μια στιγμιότυπο
και CTRL+F
για αναζήτηση μέσα στο στιγμιότυπο για ευαίσθητες πληροφορίες.
Επιπλέον, υψηλά ευαίσθητες πληροφορίες όπως μνημονικά κλειδιά ή κωδικοί δεν πρέπει να επιτρέπεται να αντιγράφονται στο πρόχειρο (ή τουλάχιστον να αφαιρούνται από το πρόχειρο μέσα σε λίγα δευτερόλεπτα) επειδή τότε διεργασίες παρακολούθησης του πρόχειρου θα μπορούσαν να τα λάβουν.
Φόρτωση Επέκτασης στον Περιηγητή
- Λήψη της Επέκτασης Περιηγητή & αποσυμπίεση
- Πηγαίνετε στο
chrome://extensions/
και ενεργοποιήστε τηνΛειτουργία Προγραμματιστή
- Κάντε κλικ στο κουμπί
Φόρτωση αποσυμπιεσμένου
Στο Firefox πηγαίνετε στο about:debugging#/runtime/this-firefox
και κάνετε κλικ στο κουμπί Φόρτωση Προσωρινής Πρόσθετης Εφαρμογής
.
Λήψη του πηγαίου κώδικα από το κατάστημα
Ο πηγαίος κώδικας μιας επέκτασης Chrome μπορεί να ληφθεί μέσω διαφόρων μεθόδων. Παρακάτω παρέχονται λεπτομερείς εξηγήσεις και οδηγίες για κάθε επιλογή.
Λήψη Επέκτασης ως ZIP μέσω Εντολών Κελύφους
Ο πηγαίος κώδικας μιας επέκτασης Chrome μπορεί να ληφθεί ως αρχείο ZIP χρησιμοποιώντας το κέλυφος εντολών. Αυτό περιλαμβάνει τη χρήση του curl
για να ανακτήσετε το αρχείο ZIP από μια συγκεκριμένη διεύθυνση URL και στη συνέχεια την εξαγωγή των περιεχομένων του αρχείου ZIP σε έναν κατάλογο. Ορίστε τα ακόλουθα βήματα:
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. Ο πηγαίος κώδικας του viewer είναι διαθέσιμος στο αποθετήριο GitHub.
Προβολή πηγής της τοπικά εγκατεστημένης επέκτασης
Οι επεκτάσεις Chrome που είναι εγκατεστημένες τοπικά μπορούν επίσης να ελεγχθούν. Ακολουθήστε τα παρακάτω βήματα:
- Αποκτήστε πρόσβαση στον τοπικό φάκελο προφίλ του Chrome επισκεπτόμενοι τη διεύθυνση
chrome://version/
και εντοπίζοντας το πεδίο "Διαδρομή προφίλ". - Πλοηγηθείτε στον υποφάκελο
Επεκτάσεις/
μέσα στον φάκελο προφίλ. - Αυτός ο φάκελος περιέχει όλες τις εγκατεστημένες επεκτάσεις, συνήθως με τον πηγαίο κώδικό τους σε μια ευανάγνωστη μορφή.
Για να αναγνωρίσετε τις επεκτάσεις, μπορείτε να αντιστοιχίσετε τα IDs τους με τα ονόματά τους:
- Ενεργοποιήστε τη λειτουργία Προγραμματιστή στη σελίδα
about:extensions
για να δείτε τα IDs κάθε επέκτασης. - Μέσα σε κάθε φάκελο επέκτασης, το αρχείο
manifest.json
περιέχει ένα ευανάγνωστο πεδίοname
, που σας βοηθά να αναγνωρίσετε την επέκταση.
Χρησιμοποιήστε ένα Αρχειοθέτη ή Αποσυμπιεστή
Πηγαίνετε στο Chrome Web Store και κατεβάστε την επέκταση. Το αρχείο θα έχει την κατάληξη .crx
. Αλλάξτε την κατάληξη του αρχείου από .crx
σε .zip
. Χρησιμοποιήστε οποιονδήποτε αρχειοθέτη (όπως WinRAR, 7-Zip, κλπ.) για να εξάγετε τα περιεχόμενα του αρχείου ZIP.
Χρησιμοποιήστε τη λειτουργία Προγραμματιστή στο Chrome
Ανοίξτε το Chrome και μεταβείτε στη διεύθυνση chrome://extensions/
. Ενεργοποιήστε το "Λειτουργία προγραμματιστή" στην πάνω δεξιά γωνία. Κάντε κλικ στο "Φόρτωση αποσυμπιεσμένης επέκτασης...". Πλοηγηθείτε στον κατάλογο της επέκτασής σας. Αυτό δεν κατεβάζει τον πηγαίο κώδικα, αλλά είναι χρήσιμο για την προβολή και την τροποποίηση του κώδικα μιας ήδη κατεβασμένης ή αναπτυγμένης επέκτασης.
Λίστα Ελέγχου Ασφάλειας
Ακόμα και αν οι Επεκτάσεις Περιήγησης έχουν μια περιορισμένη επιφάνεια επίθεσης, μερικές από αυτές ενδέχεται να περιέχουν ευπάθειες ή πιθανές βελτιώσεις στην ενίσχυση. Οι παρακάτω είναι οι πιο συνηθισμένες:
- Περιορίστε όσο το δυνατόν περισσότερες ζητούμενες
άδειες
- Περιορίστε όσο το δυνατόν περισσότερο τις
host_permissions
- Χρησιμοποιήστε μια ισχυρή
content_security_policy
- Περιορίστε όσο το δυνατόν περισσότερο τις
externally_connectable
, αν δεν απαιτείται καμία και είναι δυνατόν, μην την αφήνετε από προεπιλογή, καθορίστε{}
- Αν η URL ευάλωτη σε XSS ή σε ανάληψη αναφέρεται εδώ, ένας επιτιθέμενος θα μπορεί να στείλει μηνύματα στα scripts φόντου απευθείας. Πολύ ισχυρή παράκαμψη.
- Περιορίστε όσο το δυνατόν περισσότερο τις
web_accessible_resources
, ακόμα και κενές αν είναι δυνατόν. - Αν το
web_accessible_resources
δεν είναι κανένα, ελέγξτε για ClickJacking - Αν υπάρχει οποιαδήποτε επικοινωνία από την επέκταση προς τη σελίδα web, ελέγξτε για XSS ευπάθειες που προκαλούνται στην επικοινωνία.
- Αν χρησιμοποιούνται Post Messages, ελέγξτε για ευπάθειες Post Message.
- Αν το Content Script έχει πρόσβαση σε λεπτομέρειες DOM, ελέγξτε ότι δεν εισάγουν ένα XSS αν τροποποιηθούν από το web
- Δώστε έμφαση εάν αυτή η επικοινωνία εμπλέκεται επίσης στη Επικοινωνία Σεναρίου Περιεχομένου -> Σεναρίου Φόντου
- Ευαίσθητες πληροφορίες δεν πρέπει να αποθηκεύονται μέσα στον Κώδικα της Επέκτασης Περιήγησης
- Ευαίσθητες πληροφορίες δεν πρέπει να αποθηκεύονται μέσα στη Μνήμη της Επέκτασης Περιήγησης
Εργαλεία
Tarnish
- Ανακτά οποιαδήποτε επέκταση Chrome από έναν σύνδεσμο που παρέχεται από το Chrome webstore.
- manifest.json viewer: απλά εμφανίζει μια μορφοποιημένη JSON έκδοση του πηγαίου κώδικα του manifest της επέκτασης.
- Ανάλυση Αναγνώρισης Αποτυπώματος: Ανίχνευση των web_accessible_resources και αυτόματη δημιουργία JavaScript αποτυπώματος επέκτασης Chrome.
- Ανάλυση Πιθανού Clickjacking: Ανίχνευση σελίδων HTML επέκτασης με την οδηγία web_accessible_resources οι οποίες είναι ευάλωτες στο clickjacking ανάλογα με τον σκοπό των σελίδων.
- Προβολή Προειδοποιήσεων Δικαιωμάτων: που εμφανίζει μια λίστα με όλες τις προειδοποιήσεις δικαιωμάτων Chrome που θα εμφανιστούν όταν ο χρήστης προσπαθήσει να εγκαταστήσει την επέκταση.
- Επικίνδυνες Λειτουργίες: εμφανίζει την τοποθεσία επικίνδυνων λειτουργιών που θα μπορούσαν ενδεχομένως να εκμεταλλευτεί ένας επιτιθέμενος (π.χ. λειτουργίες όπως innerHTML, chrome.tabs.executeScript).
- Σημεία Εισόδου: δείχνει πού η επέκταση δέχεται εισόδους χρήστη/εξωτερικές. Αυτό είναι χρήσιμο για την κατανόηση της επιφάνειας μιας επέκτασης και την αναζήτηση πιθανών σημείων για την αποστολή κακόβουλα διαμορφωμένων δεδομένων στην επέκταση.
- Και οι δύο σαρωτές Επικίνδυνων Λειτουργιών και Σημείων Εισόδου έχουν τα ακόλουθα για τις δημιουργημένες ειδοποιήσεις:
- Σχετικό απόσπασμα κώδικα και γραμμή που προκάλεσε την ειδοποίηση.
- Περιγραφή του προβλήματος.
- Ένα κουμπί "Προβολή Αρχείου" για να δείτε τ
- Εάν θέλετε να δείτε την εταιρεία σας διαφημισμένη στο HackTricks ή να κατεβάσετε το HackTricks σε μορφή PDF ελέγξτε τα ΣΧΕΔΙΑ ΣΥΝΔΡΟΜΗΣ!
- Αποκτήστε το επίσημο PEASS & HackTricks swag
- Ανακαλύψτε Την Οικογένεια PEASS, τη συλλογή μας από αποκλειστικά NFTs
- Εγγραφείτε στη 💬 ομάδα Discord ή στη ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @carlospolopm.
- Μοιραστείτε τα κόλπα σας στο χάκινγκ υποβάλλοντας PRs στα HackTricks και HackTricks Cloud αποθετήρια του github.